Hello friends, hope you are doing well!
I'm gonna describe how easy to run PHP gRPC-server and code NodeJS gRPC- client. At this article, I will highlight only the more important parts of setting up the workflow. Here, You can find a done repository. If you aren't acquainted with gRPC, look at the following link.
There will be considered a fast solution spiral/php-grpc to gRPC-server. Let's start off.
Firstly, look at docker-compose file:
version: '3.3'
services:
grpc_php_server: # grpc server
build:
context: ./containers/php
dockerfile: php.docker
container_name: grpc_php_server
working_dir: /app
command: ./rr-grpc serve -v -d
volumes:
- ./src/php:/app
grpc_php_protoc: # protoc generator
image: grpc/php
container_name: grpc_protoc
working_dir: /app
volumes:
- ./src/php:/app
client_nodejs: # grpc client
image: node:latest
container_name: client_nodejs
command: node ./client.js
working_dir: /app
links:
- grpc_php_server
depends_on:
- grpc_php_server
volumes:
- ./src/nodejs:/app
As you could see it's a very simple docker-compose
file.
Note: if you want to play around, don't forget to grab all dependencies.
docker-compose run grpc_php_server composer install
docker-compose run client_nodejs npm install
The proto
file was drawn up as very primitive way as I can 😏.
contrived.proto
is for server
and client
:
syntax = "proto3";
package service;
service ContrivedService {
rpc ContrivedMethod (ContrivedMessageRequest) returns (ContrivedMessageResponse) {
}
}
message ContrivedMessageRequest {
string body = 1;
}
message ContrivedMessageResponse {
string body = 1;
}
That one was put at php/proto
and nodejs/proto
directories.
For generating needed interfaces and initiation skeleton for gRPC-server the following command was used:
docker-compose run grpc_php_protoc protoc --plugin=./protoc-gen-php-grpc --php_out=/app --php-grpc_out=/app ./proto/contrived.proto
The setting of grpc-server
was hosted at root directory .rr.yaml
:
grpc:
listen: "tcp://:3000"
proto: "./proto/contrived.proto"
workers:
command: "php worker.php"
pool:
numWorkers: 1
maxJobs: 1
The worker.php
can look like:
<?php
declare(strict_types=1);
/**
* Sample GRPC PHP server.
*/
use Spiral\Goridge;
use Spiral\RoadRunner;
ini_set('display_errors', 'stderr');
require "vendor/autoload.php";
$server = new \Spiral\GRPC\Server();
$server->registerService(\Service\ContrivedServiceInterface::class, new \Service\ContrivedService());
$w = new RoadRunner\Worker(new Goridge\StreamRelay(STDIN, STDOUT));
$server->serve($w);
The ContrivedService.php
can look like:
<?php
namespace Service;
use Service\ContrivedMessageRequest;
use Service\ContrivedMessageResponse;
use Service\ContrivedServiceInterface;
use Spiral\GRPC;
class ContrivedService implements ContrivedServiceInterface
{
/**
* @param GRPC\ContextInterface $ctx
* @param ContrivedMessageRequest $in
* @return ContrivedMessageResponse
*
* @throws GRPC\Exception\InvokeException
*/
public function ContrivedMethod(GRPC\ContextInterface $ctx, ContrivedMessageRequest $in): ContrivedMessageResponse
{
$response = new ContrivedMessageResponse();
$response->setBody("Hello");
return $response;
}
}
So, let's move up to js-client.
The client.js
can look like:
const path = require('path');
const PROTO_PATH = path.resolve(__dirname, './proto/contrived.proto');
const GRPCClient = require('node-grpc-client');
const myClient = new GRPCClient(PROTO_PATH, 'service', 'ContrivedService', 'grpc_php_server:3000');
const dataToSend = {
body: 'Nodejs client!'
};
myClient.runService('ContrivedMethod', dataToSend, (err, res) => {
if (err) {
console.error(err);
}
console.log('Service response\n', res);
});
For trying it out was used the following command:
docker-compose up
The output result:
grpc_php_server | DEBU[0000] [rpc]: started
grpc_php_server | DEBU[0000] [grpc]: started
client_nodejs | Service response
client_nodejs | { body: 'Hello' }
As you could see it's tremendous simple to start working with gRPC and start thinking of adapting that one to our workflow.
What kind of benefits of adopting GRPC:
- Easy to understand.
- Web infrastructure already built on top of HTTP.
- Great tooling for testing, inspection, and modification.
- Loose coupling between clients/server makes changes easy.
- High-quality HTTP implementations in every language.
Top comments (1)
Another benefit of GRPC is much higher performance compared to classic REST.