Laravel NATSRPC Server
This package implements a JSON-RPC server over a NATS transport.
You can call methods on other services without changing your workflow too much
composer require dpniel_ch/laravel-natsrpc-server
Running the NATS-RPC Server
This package includes a server binary that manages the long lived connections with a nats server and offloads requests and events to a pool of
php workers it manages.
The php workers transform a nats-rpc payload into an Illuminate\Http\Request
and pass this off to laravels kernel to be handled by an \App\Nats\Controller
which has been configured in routes/nats.php
To run the server you need to create a config file for the natsrunner binary.
Create a file called .natsrpc.yml
in the root of your project directory
# The name of this service. This should be unique to the project
# But the same for multiple instance/clustered setup.
service: "com.service.test"
server:
# Command to start the php/laravel bridge
# Would be php vendor/bin/natsrunner.php in a normal project
# Unless you role your own bridge.
command: php vendor/bin/natsrunner.php
pool:
# Number of php processes to maintain
num_workers: 5
# Max number of jobs each process should handle before being destroyed
# and recreated. This helps manage php memory usage.
max_jobs: 100
# Nats connection config
nats:
host: "nats://192.168.64.10"
user: ""
pass: ""
# External Services to subscribe to for events
subscribe:
- "com.service.client"
- "com.service.auth"
Once that's in place from the root of your project
# mac
$ chmod +x vendor/bin/natsrunner
# or linux
$ chmod +x vendor/bin/natsrunner-linux
# Start
$ vendor/bin/natsrunner
If all is well you should now have a functioning server ready to accept requests through nats.
NatsRPC Controllers
$ php artisan make:nats-controller FooController
This will create a basic controller in app/Nats/Controllers with an index method. Now with Nats-RPC we just have to return an array of data
from the controller method which the calling route dispatcher will wrap into a JsonRpcResponse to send back.
// ...
class FooController
{
public function index(RequestParams $params)
{
// echo it back
return $params->all();
}
}
To make this controller accessable we need to bind it in the nats route file routes/nats.php
(You will need to create this)
// in routes/nats.php
// This binds all public controller methods to the given prefix of "foo"
// So calling "foo.bar" would call the bar function in the bound FooController.
$router->bindController("foo", "FooController");
// Or to bind just a single method
$router->bind("foo.index", "FooController@index");
Now to call this method in the new controller we can use the include NatsRPC Client.
use NatsRPC\Client\Service;
$service = Service::create("com.service.test"); // The service we want to talk to
$resp = $service->request("foo", ["test" => "data"]);
// Or
$resp = $service->request("foo.index", ["test" => "data"]);
if (!$resp->hasError() && $resp->hasResult()) {
dd($resp->result());
}
Broadcast Events over nats
You can either use the nats()
helper function to broadcast an event or get an instance of the NatsRPC Client and publish
nats("user.login", ["user" => $user->id]);
// Or
use NatsRPC\Client\Client;
app()->make(Client::class)->publish("user.login", [...])
Any service that is listening on a services events will fire a NatsRPC\Events\ServiceEvent
which applications can listen on and react to in the normal laravel Listener flow.