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

' , 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: