9 June, 2020
More and more developers and companies are discovering the benefits of microservices. And while PHP is usually not the first choice for this architecture, it is now more than viable to create efficient web apps based on microservices with PHP. To that end, Google’s gRPC and Protobuf solutions are a big help. Today, I’m going to show you how to use gRPC with PHP.
But before we get to the gRPC PHP issue, let’s talk a little about how the gRPC framework can help ease some typical microservices pains in the first place.
Microservices and gRPC – introduction
As the need for scalability and reliability grows, the microservices architecture becomes more and more popular. The main advantage of microservices is the possibility of adding more resources in places where they are actually needed as well as fault isolation, simplicity of the modules and possibility to use different technologies across the platform.
As great as it sounds, microservices-based applications struggle with some challenges of their own. Difficulties with global testing, hard debugging, deployment problems, the complexity of communication between services and versioning are usually listed as the major drawbacks of the microservices concept. This is where Google steps in with its gRPC and Protobuf solutions.
The gRPC is a universal framework based on the remote procedure call (RPC) protocol. The main idea of RPC is to create a service whose methods can be called remotely as if they were the client methods. The framework provides bidirectional streaming with integrated authentication and HTTP2-based transport.
Benefits of gRPC
To serialize the structured data, gRPC uses protocol buffers. With protocol buffers, you can define the structure of the data in a .proto file and then use a generator to produce the source code in a variety of programming languages. Which leads to the first advantage of the protocol buffers – an easy and fast way to establish the communication base for the services. Another benefit of using the buffers is backward compatibility. You can update the data structure with no impact on the parts of the system deployed with the previous format. Also, the protocol buffers are simple, small and fast. You can read detailed information about gRPC and protocol buffers at the framework’s official website as well as in Google’s resources for developers.
gRPC for PHP
gRPC works across languages and platforms. Does it mean that it can be used with PHP? PHP is not considered the best solution for microservices mainly because of its memory issues, speed, single-threading and short-lived streaming. Still, developing microservices with PHP is possible, and with the right tools, it can be quite effective.
There are solutions such as Mezzio (formerly Expressive) and Swoft frameworks supporting asynchronous programming through Swoole. The gRPC has no direct support for building a PHP-based server. This can be done with third-party tools such as the spiral/php-grpc server. What about the client’s side, is it supported? The answer is yes.
As gRPC’s popularity grows, you may find yourself in need of integrating it with some services based on it even when your application does not use the microservices architecture. For example, you may want to use some cloud services such as Google APIs. Also, as I mentioned, microservices development encourages using different technologies for the modules. This can become handy if you want to migrate gradually from a monolith PHP application to microservices using different languages such as Node.js, Golang or Python.
Adding gRPC to PHP application
Here are steps you need to take to introduce gRPC communication in your PHP application.
1. Make sure you have gRPC and the PHP gRPC extension up and running.
You can do that by running php -m | head in command line. If the extension is not listed, you will need to install it. The instructions on how to do that can be found here.
If you want to use Docker and your base PHP image does not have the extension, you will need to add something like this to your Dockerfile:
RUN pecl install grpc && \
2. Add Google Protobuf, gRPC and the gRPC extension to your project using Composer:
composer req google/protobuf
composer req grpc/grpc
composer req ext-grpc
3. Get the protobuf compiler protoc or use a docker image for file generation.
You can get protoc by following this guide.
Instead of installing protoc locally, you can use the docker image that will help with the file generation.
4. Add the .proto files to your application and generate your PHP files.
The first step here would be getting the protofile/protofiles and placing them in the application. For demonstration purposes, I have downloaded the Google Example Bookstore API protofile and used it in a simple library application in Symfony. The bookstore.proto file is used in Google gRPC tutorials and it is available here. It is also pasted below. In the top part of the file, you will find information about the syntax version, imports and bookstore service definition. Further on you will see the resources, requests and responses definitions.
Next step is to take care of the source code generation, which was processed via namely/docker-protoc with the following command:
docker run -v `pwd`:/defs namely/protoc-all -f library.proto -l php -o library/
The command should be run from the .proto file directory. The -o switch is optional and allows for specifying the source code location. The -f switch points in the file can be replaced with -d to process all protofiles in the location. The place of protorepo generation can be modified with -i switch. More details can be found in the namely/docker-protoc documentation linked in point 3.
Let’s take a look at the generated classes and their structure. I have placed my proto file and the generated code out of the src directory but it can be placed anywhere. The generated tree looks as follows:
The generated client code is shown below. It is worth it to note that the comment at the very top of the generated code should not be modified.
Besides the client, we also see resource classes which are models of the actual data. You can see the Book.php resource class below.
The structure of gRPC requests is also defined in the proto file and gives us the generated classes. For instance the GetBookRequest.php:
After sending the gRPC request, we will get the response containing either the resource or the response class. The response classes represent the set of data, for example, the list of resources. Let’s check out the ListBooksResponse.php.
The response should also contain information about the request status. You can find detailed information about gRPC statuses and error handling here.
5. Use the generated code in the application.
Once we have the generated code, we can easily wrap it in the custom class which will allow the communication with gRPC service as if it was part of the system. Below you can see an example implementation of the method and gRPC error handling.
gRPC PHP summary
The connection with gRPC service may seem complicated, especially if you are used to REST and have never used remote procedure calls before. But thanks to Protobuf and protoc generator, it is actually quite simple.
Using generated files in a PHP application, you can easily establish communication with the microservices written in any language. Choosing the gRPC as a communication protocol while migrating the system from a monolith architecture to microservices may be a huge advantage. Contract programming supported by protocol buffers helps set up a communication base for the services and maintain backward compatibility. The simplicity and speed of protocol buffers make for an efficient system.
Using gRPC and protocol buffers, we can take advantage of the microservices and build simple, isolated modules with PHP, other technologies or both. The gRPC also provides a convenient way of utilizing the cloud services or any third party service we may want to use. When used that way, the gRPC PHP combination can become really powerful!