2021-03-31 18:19:43 +08:00
# gRPC Service
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
The quickstart-php in the official gRPC documentation is easy to mislead PHPer. According to the documentation on the official website, it is very complex to run the gRPC service, not to mention the entire set of RPC services.
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
[tech| 再探 grpc ](https://www.jianshu.com/p/f3221df39e6f ) is recommended to have a read, which explains the basic knowledge of implementing gRPC in PHP.
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
Hyperf has further encapsulated gRPC support. The hyperf-skeleton project is taken as an example to explain the entire steps in detail:
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
- .proto file and related configuration examples
- gRPC server example
- gRPC client example
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
## .proto file and related configuration examples
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
- Define proto file - `grpc.proto`
2019-05-01 00:49:14 +08:00
```proto3
syntax = "proto3";
package grpc;
service hi {
rpc sayHello (HiUser) returns (HiReply) {
}
}
message HiUser {
string name = 1;
int32 sex = 2;
}
message HiReply {
string message = 1;
HiUser user = 2;
}
```
2021-03-31 18:19:43 +08:00
- Use protoc to generate sample code
2019-05-01 00:49:14 +08:00
```
2021-03-31 18:19:43 +08:00
# Use the linux package management tool to install protoc. Let's take alpine as an example. You can also refer to the Dockerfile under hyperf-skeleton
2019-05-01 00:49:14 +08:00
apk add protobuf
2021-03-31 18:19:43 +08:00
# Use protoc to automatically generate code
2019-05-01 00:49:14 +08:00
protoc --php_out=grpc/ grpc.proto
# tree grpc
grpc
├── GPBMetadata
│ └── Grpc.php
└── Grpc
├── HiReply.php
└── HiUser.php
```
2021-03-31 18:19:43 +08:00
- Configure composer.json, use the automatic loading of the code under `grpc/` . If different `package` settings are used in the proto file, or a different directory is used, adjust accordingly. And then, execute `composer dump-autoload after adding` make it active.
2019-05-01 00:49:14 +08:00
```json
"autoload": {
"psr-4": {
"App\\": "app/",
"GPBMetadata\\": "grpc/GPBMetadata",
"Grpc\\": "grpc/Grpc"
},
"files": [
]
},
```
2021-03-31 18:19:43 +08:00
## gRPC server example
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
- gRPC server configuration
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
`server.php` file(refer to [config ](zh-cn/config.md )):
2019-05-01 00:49:14 +08:00
```php
'servers' => [
....
[
'name' => 'grpc',
'type' => Server::SERVER_HTTP,
'host' => '0.0.0.0',
'port' => 9503,
'sock_type' => SWOOLE_SOCK_TCP,
'callbacks' => [
2021-03-31 18:19:43 +08:00
Event::ON_REQUEST => [\Hyperf\GrpcServer\Server::class, 'onRequest'],
2019-05-01 00:49:14 +08:00
],
],
],
```
2021-03-31 18:19:43 +08:00
- gRPC server routing configuration
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
`routes.php` file(refer to [router ](zh-cn/router.md )):
2019-05-01 00:49:14 +08:00
```php
Router::addServer('grpc', function () {
Router::addGroup('/grpc.hi', function () {
Router::post('/sayHello', 'App\Controller\HiController@sayHello');
});
});
```
2021-03-31 18:19:43 +08:00
`sayHello` method in `HiController.php` file:
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
```php
public function sayHello(HiUser $user)
{
$message = new HiReply();
$message->setMessage("Hello World");
$message->setUser($user);
return $message;
}
```
Correspondence between the definition in the .proto file and gRPC server routing: `/{package}.{service}/{rpc}`
- If you would like to go further in this
2019-05-01 00:49:14 +08:00
2021-07-22 11:09:39 +08:00
How gRPC server processes gRPC requests(`vendor/hyperf/grpc-server/src/CoreMiddleware.php)`: `\Hyperf\GrpcServer\CoreMiddleware::process()` parse the `request_uri` and get the `/{package}.{service}/{rpc}` information, and then call the encapsulated gRPC decode class `\Hyperf\Grpc\Parser::deserializeMessage` , you can get the requested plaintext information
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
How gRPC server responds to gRPC? You may get the answer through provided information above.
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
## gRPC client example
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
The sample code can be found in `GrpcController` :
2019-05-01 00:49:14 +08:00
```php
public function hello()
{
2021-03-31 18:19:43 +08:00
// This client is coroutine-safe and can be reused
2019-05-01 00:49:14 +08:00
$client = new \App\Grpc\HiClient('127.0.0.1:9503', [
'credentials' => null,
]);
$request = new \Grpc\HiUser();
$request->setName('hyperf');
$request->setSex(1);
/**
* @var \Grpc\HiReply $reply
*/
list($reply, $status) = $client->sayHello($request);
$message = $reply->getMessage();
$user = $reply->getUser();
2021-03-31 18:19:43 +08:00
2019-05-01 00:49:14 +08:00
var_dump(memory_get_usage(true));
return $message;
}
```
2021-03-31 18:19:43 +08:00
Hyperf has already encapsulated `\Hyperf\GrpcClient\BaseClient` , expand it if needed according to the definition in .proto file:
2019-05-01 00:49:14 +08:00
```php
class HiClient extends BaseClient
{
public function sayHello(HiUser $argument)
{
2021-03-31 18:19:43 +08:00
return $this->_simpleRequest(
2019-05-01 00:49:14 +08:00
'/grpc.hi/sayHello',
$argument,
[HiReply::class, 'decode']
);
}
}
```
2021-03-31 18:19:43 +08:00
The gRPC client also supports gRPC's Streaming mode. Take two-way flow as an example:
```php
< ?
public function hello()
{
$client = new RouteGuideClient('127.0.0.1:50051');
$note = new RouteNote();
$call = $client->routeChat();
$call->push($note);
$call->push($note);
/** @var RouteNote $note */
[$note,] = $call->recv();
[$note,] = $call->recv();
}
```
> Note that in streaming mode, you must manually catch the disconnected exception (`Hyperf\GrpcClient\Exception\GrpcClientException`) and choose whether to retry or not.
2021-04-02 12:58:11 +08:00
## At the end
2019-05-01 00:49:14 +08:00
2021-03-31 18:19:43 +08:00
If you are a high-frequency user of gRPC, you are welcome to pay attention to the follow-up developer tools of hyperf, which can generate a full set of gRPC code based on the .proto file.