hzwz / grpc-server
swoft grpc custom server
1.1
2021-08-14 01:14 UTC
Requires
- php: >=7.0
- google/protobuf: ^3.11
- grpc/grpc: ^1.39
- swoft/connection-pool: v2.0.11
- swoft/framework: v2.0.11
This package is auto-updated.
Last update: 2025-03-01 00:28:41 UTC
README
1. 下载组件
composer下载:composer require hzwz/grpc-server dev-master
2. 创建Grpc和相关目录
1. 在 app/ 目录下创建一个Grpc目录
2. 在 Grpc/ 目录里分别创建protos和Services两个目录
- 说明:protos目录里是存放 *.proto相关文件。Services目录里是实现接口转换的
*.proto文件定义实例:
syntax = "proto3";
package Brother;
service Agents {
rpc initProfitPersonInfo(initProfitPersonRequest) returns(initProfitPersonResponse); //把运营商初始化为默认的分成人员
rpc getGroupIdsFromShare(getShareGroupListByShareUserRequest) returns(getShareGroupListByShareUserResponse); //根据合伙人ID返回对应的分组ID集
rpc getCompositeUserInfo(getCompositeUserInfoRequest) returns(getCompositeUserInfoResponse); //通过用户类型和手机号获取对应用户信息
}
message baseField {
int64 u_id = 1;
int32 u_type = 2;
int32 company_id = 3;
}
//把运营商初始化为默认的分成人员
message initProfitPersonRequest {
int32 group_id = 1;
baseField baseFields = 2;
}
message initProfitPersonResponse {}
//根据合伙人ID返回对应的分组ID集
message getShareGroupListByShareUserRequest {
baseField baseFields = 1;
}
message getShareGroupListByShareUserResponse {
repeated string data = 1;
}
//通过用户类型和手机号获取对应用户信息
message getCompositeUserInfoRequest {
int32 u_type = 1;
int32 company_id = 2;
string phone = 3;
}
message getCompositeUserInfoResponse {
string id = 1;
string nickname = 2;
string phone = 3;
string headImgUrl = 4;
}
- 通过定义好的*.proto文件生成实际的代码:
protoc --php_out=. --grpc_out=. --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin *.proto
说明:
1. --php_out 这个是生成php代码的一个指令
2. --grpc_out 这个是生成php grpc客户端代码的指令
3. 指令后面的 =. 这个是表示为:在当前目录下生成,也可以指定具体的目录。
4. --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin
这个是表示:生成grpc代码时所使用的grpc插件和对应插件所在的位置
5. --proto_path 指令可以指定 *.proto文件的具体路径
6. 除了--proto_path外还有一个别名 -I 和--proto_path作用是一样的
- 更详细的可以查看对应的文档:
Servierce说明:
- 哪些服务类和接口是需要提供给兄弟服务调用的,可以在这个目下处理:
- 比如汽车桩用户中心里的:运营商,C端用户两个服务的一些接口需要提供给兄弟服务调用,目录定义参考如下:
1. Services/Brother/OperatorService 运营商服务类
2. Services/Brother/UserService C端用户服务类
- 服务类定义好以后就需要定义服务路由了。GRPC路由和HTTP路由定义形式不太一样,所以单独的提供了一个 @GrpcService() 注解指令来设置GRPC路由。
- 设置格式是:包名+服务类名。如下:
<?php /** * @GrpcService(prefix="Brother/Agents") */ class BrotherService {}
- 说明:Brother就是在定义proto文件时指定的package包名,Agents就是proto里定义的service名。如下:
syntax = "proto3";
//包名称(对应的实际就是PHP的namespace命名空间地址)
package Brother;
//rpc服务(就是客户端需要调用服务端的接口服务类)
service Agents {}
- 注:完整路由的处理大概逻辑是:获取到每个服务类的前缀路由后,然后通过PHP的反射动态的获取到每个类里的服务方法,最后在组装成实际的GRPC路由格式。
通过protoc等相关指令生成grpc代码后,其客户端对应的路由格式如下:
<?php class AgentsClient extends \Grpc\BaseStub { public function initProfitPersonInfo(\Brother\AgentsRequest $argument, $metadata = [], $options = []) { return $this->_simpleRequest('/Brother.Agents/initProfitPersonInfo', //这个就是Grpc路由 $argument, ['\Brother\AgentResponse', 'decode'], $metadata, $options); } }
- /Brother.Agents/initProfitPersonInfo' 这个就是路由。最后生成的就是这个格式
一个完整的GrpcService实例如下:
- 例:设备中心通过grpc方式调用汽车桩用户中心里的 [运营商初始化为默认的分成人员]接口:
<?php /** * Class BrotherService * @package App\Grpc\Services\Brother * * @GrpcService(prefix="Brother/Agents") */ class BrotherService { /** * 把运营商初始化为默认的分成人员 * * @Middleware(AddDefaultProfitValidationMiddleware::class) * * @param AgentsRequest $agentsRequest * @return AgentResponse */ public function initProfitPersonInfo(AgentsRequest $agentsRequest): AgentResponse { //获取swoft/Reuqest类 $request = context()->getRequest(); //获取调用接口时所传递的参数(如果这里需要的话。不需要可以不用获取) $requestParams = $request->input(); //调用实际控制器的方法,并传递Request类 $result = bean(BrotherController::class)->initProfitPersonInfo($request); //初始化响应类(这个响应类是通过proto文件定义好,然后生成的响应类) $response = new AgentResponse(); //设置响应参数(这里可能会有多个,我这里只是写了一个实例) $response->setData(json_encode($result, 1)); //返回 return $response; } }
Middleware说明
- 我们已经写好的Controller类里可能已经有实现自己的中间件,但是由于Http和Grpc的方式不一样,所以无法完全兼容。不过有一个折中的处理方式是:如果在Service服务类里在调用Controller类里的某个方法之前需要先去执行已实现的某个中间件里的代码时,可以在Service类上或Service类里的某个方法上定义一下@middleware()这个注解指令,引入的use路径是:use Hzwz\Grpc\Server\Annotation\Mapping\Middleware;然后把中间件类名称或者别名放进去就好了。
- 实例如下:
<?php use Hzwz\Grpc\Server\Annotation\Mapping\Middleware; //引入这个路径 class BrotherService { /** * 把运营商初始化为默认的分成人员 * * @Middleware(AddDefaultProfitValidationMiddleware::class) //这里定义 * * @param AgentsRequest $agentsRequest * @return AgentResponse */ public function initProfitPersonInfo(AgentsRequest $agentsRequest): AgentResponse {} }
- 底层实现的是和Http同一个Middleware接口。