Image

Op Software Engineering opleidingen wordt er vaak alleen ingegaan op REST (of oudere standaarden bv. SOAP) voor communicatie tussen verschillende applicaties, terwijl er naast REST nog meer interessante en veel gebruikte standaarden zijn. Voorbeelden hiervan zijn GraphQL en gRPC. Beiden hebben weer andere voordelen ten opzichte van REST. In deze blog ga ik in op een van deze twee, namelijk gRPC. Ik heb een mini project opgezet dat gebruik maakt van gRPC, om zo te bekijken hoe je de communicatie tussen verschillende applicaties op zet door middel van gRPC. Zo krijg je een beeld van wat er komt kijken bij het opzetten van projecten die door middel van gRPC met elkaar communiceren. Hiervoor heb ik een project opgezet, waarbij ik in deze blog in ga op de grotere onderdelen die komen kijken bij gRPC.

TLDR; De source code is te vinden op de volgende link: https://gitlab.com/stijn98s/blogs/how-to-use-grpc-with-a-php-backend.


Wat is gRPC?

gRPC is een moderne Remote procedure call (RPC) framework, ontwikkeld door Google, dat gebruik maakt van Protocol buffers (Protobufs) om data te verzenden tussen verschillende applicaties. Hierbij wordt er gebruikt gemaakt van het HTTP/2 protocol. Met gRPC kan de client direct een methode op de server aanroepen alsof het een lokaal object is, waardoor het gemakkelijk is om gedistribueerde applicaties te maken. gRPC tools zijn al voor veel veschillende programeertalen beschikbaar, namelijk voor Go, Java, C#, Node.js, Python, PHP en Ruby.


Setup

Voor de opzet van dit project heb ik 3 repositories gemaakt, namelijk de frontend, backend en protos repository. Voor de frontend wordt er gebruik gemaakt van Vue.js 3 en gRPC web en voor de backend wordt er gebruik gemaakt van Spiral en Roadrunner. De protos repository wordt gebruikt om alle protobufs in op te slaan, waarna deze als submodule in de frontend en backend wordt ingeladen.

Voor de communicatie heeft gRPC web een proxy nodig die HTTP omzet naar gRPC. Hiervoor maak ik gebruik van Envoy. Om al deze services op te kunnen opzetten maak ik gebruik van Docker en Docker Compose.


Ontwikkeling

Na het opzetten kunnen de protobuf bestanden gemaakt worden. In het protobuf bestand definieer je de acties die de server moet implementeren, de berichten die over deze actie gestuurd worden en het resultaat wat ontvangen moet worden. Daardoor weet de client dan welke acties deze kan aanroepen.

Op basis van bovenstaand bestand kan er nu in de backend en frontend repositories code gegenereerd worden. Hiervoor wordt er in de backend een interface klasse gemaakt die je zal moeten implementeren. De frontend genereerd een client klasse waarop aparte functies zitten per actie. Beiden genereren daarnaast ook nog de object klasses van de berichten die over de acties gestuurd en ontvangen worden.

Backend: php app.php grpc:generate protos/task.proto Frontend: protoc -I=./protos task.proto --js_out=import_style=commonjs,binary:./gen --grpc-web_out=import_style=typescript,mode=grpcwebtext:./gen

Met de gegenereerde code kan voor de backend de service geimplementeerd worden, waarbij het belangrijk is dat je de gegenereerde service interface implementeert. Om de data persistent te maken heb ik gebruik gemaakt van Cycle ORM. In de acties haal ik de data op of sla ik deze op in de database en geef ik de objecten terug die gedefinieerd zijn in het protobuf bestand.

Nu kan in de frontend repository de client aangemaakt en de functies aangeroepen worden. Bij het aanmaken van de client geef je mee op welke url de service te bereiken is. Als deze service beveiligd is kunnen hier ook nog de inloggegevens ingevuld worden.

Ik heb deze acties in een VueX store en vervolgens in een Promise gezet, om deze acties gemakkelijk in de views asynchroon aan te kunnen roepen. In de store kunnen ook de andere acties geimplementeerd worden.

Door limitaties van PHP is streaming helaas niet mogelijk. Hiervoor is wel een oplossing, namelijk door gebruik van een Go gRPC service en jobs in Spiral. Meer hierover lees je op https://spiral.dev/docs/grpc-streaming. Dit zou je bij de lijst endpoint kunnen gebruiken om de realtime updates binnen te krijgen. Zo krijgt een andere client de data wanneer deze is aangepast.


Conclusie

gRPC tools voor PHP zijn al in een ver stadium, maar lopen momenteel tegen de limitaties aan van de taal. PHP is wel bezig om een aantal functionaliteiten in de taal te maken die streaming gemakkelijker maken. Kijk bijvoorbeeld naar Fibers. Daarnaast worden tools zoals Roadrunner, die het mogelijk maken om PHP processen levend te houden tussen requests wat een significate prestatie verbeteringen met zich meebrengt, steeds meer volwassen.


Bronnen

https://en.wikipedia.org/wiki/Remote_procedure_call https://en.wikipedia.org/wiki/Protocol_Buffers https://grpc.io/docs/what-is-grpc/core-concepts/ https://github.com/protocolbuffers/protobuf/tree/master/php https://developers.google.com/protocol-buffers/docs/proto3 https://spiral.dev/docs/grpc-streaming https://cycle-orm.dev/docs