## 编写一个微服务 通过编写一个微服务,让我们快速了解框架的使用,编写一个微服务非常简单,其实就是启动一个命令行程序,在程序中启动一个 gRPC Server,然后将 Service 注册到 Server 中即可。 ## 定义 API 我们使用 protobuf 文件来定义服务 API 接口。这是一种非常方便的方式来严格定义 API 并为服务器和客户端提供具体的类型。 这是一个示例定义。 greeter.proto ~~~ syntax = "proto3"; package php.micro.grpc.greeter; service Say { rpc Hello(Request) returns (Response) {} } message Request { string name = 1; } message Response { string msg = 1; } ~~~ 在这里,我们定义了名为 php.micro.grpc.greeter 的服务,服务中定义了 Say.Hello 方法。 ## 生成 API 接口 我们将上面的 .proto 文件保存到 [/protos](https://github.com/mix-php/mix-micro-skeleton/tree/master/protos) 目录,使用代码生成工具生成 Server/Client 代码,工具的安装见 “安装说明->微服务开发” 章节。 ``` protoc --php_out=. --mix_out=. greeter.proto ``` 执行后将生成以下文件: ``` ├── GPBMetadata │   └── Greeter.php ├── Php │   └── Micro │   └── Grpc │   └── Greeter │      ├── Request.php │      ├── Response.php │      ├── SayClient.php │      └── SayInterface.php └── greeter.proto ``` 其中 Request.php、Response.php 为 `--php_out` 生成,SayClient.php SayInterface.php 由 `--mix_out` 生成。 接下来我们将生成的文件加入到 composer autoload 中,我们修改 composer.json: ``` "autoload-dev": { "psr-4": { "GPBMetadata\\": "protos/GPBMetadata/", "Php\\": "protos/Php/" } } ``` 修改后执行 `composer dump-autoload` 使其生效。 ## 实现处理程序 编写一个服务类,实现 protoc-gen-mix 生成的 SayInterface 接口: ~~~ <?php namespace App\Grpc\Services\Greeter; use Mix\Context\Context; use Php\Micro\Grpc\Greeter\Response; use Php\Micro\Grpc\Greeter\SayInterface; /** * Class SayService * @package App\Grpc\Services\Greeter */ class SayService implements SayInterface { /** * Hello * @param Context $context * @param \Php\Micro\Grpc\Greeter\Request $request * @return Response */ public function Hello(Context $context, \Php\Micro\Grpc\Greeter\Request $request): Response { $response = new Response(); $response->setMsg(sprintf('hello, %s', $request->getName())); return $response; } } ~~~ 骨架中提供了 `StartCommand.php` 的通用启动命令,里面包含: - Server 启动/停止:[StartCommand.php#L63](https://github.com/mix-php/mix-micro-skeleton/blob/master/app/Grpc/Commands/StartCommand.php#L63) - 微服务注册:[StartCommand.php#L95](https://github.com/mix-php/mix-micro-skeleton/blob/master/app/Grpc/Commands/StartCommand.php#L95) - 处理程序注册到 Server 中:创建一个 [GreeterCommand.php#L19](https://github.com/mix-php/mix-micro-skeleton/blob/master/app/Grpc/Commands/GreeterCommand.php#L18) 继承 `StartCommand::class` 并实现 init 方法。 - 在命令配置中配置 `GreeterCommand::class` 启动命令:[commands/grpc.php#L5](https://github.com/mix-php/mix-micro-skeleton/blob/master/manifest/commands/grpc.php#L5) ## 运行服务 ~~~ $ php bin/mix.php grpc:greeter ____ ______ ___ _____ ___ _____ / /_ _____ / __ `__ \/ /\ \/ /__ / __ \/ __ \/ __ \ / / / / / / / /\ \/ _ / /_/ / / / / /_/ / /_/ /_/ /_/_/ /_/\_\ / .___/_/ /_/ .___/ /_/ /_/ Server Name: mix-grpc System Name: darwin PHP Version: 7.3.12 Swoole Version: 4.5.0RC1 Framework Version: 2.2.2 [2020-05-19 18:49:21] GRPC.INFO: Server started [0.0.0.0:57249] [2020-05-19 18:49:21] GRPC.INFO: Register service [php.micro.grpc.greeter-6593b8aa-99be-11ea-8195-000057bdb82e] ~~~ ## 写一个客户端 通常我们在 API、Web 模块中调用 gRPC 服务: ~~~ // 通过服务名称拨号一个连接 $dialer = new \Mix\JsonRpc\Client\Dialer([ 'registry' => new \Mix\Micro\Etcd\Registry('http://127.0.0.1:2379/v3'), ]); $conn = $dialer->dialFromService('php.micro.grpc.greeter'); // 通过连接创建客户端 $client = new \Php\Micro\Grpc\Greeter\SayClient($conn); // 发送请求 $request = new \Php\Micro\Grpc\Greeter\Request(); $request->setName('xiaoming'); $response = $client->Hello($request); // 打印结果 var_dump($response->getMsg()); ~~~ - 查看客户端调用实例:[SayController.php#L54](https://github.com/mix-php/mix-micro-skeleton/blob/master/app/Api/Controllers/Greeter/SayController.php#L54)