PHP搞微服务杂谈(四) 实现GRPC服务反射

拉点家长

看这一篇的同学,如果对利用hyperf(php+swoole)+ gRPC 实现微服务还没了解可以翻一下前面的分享。使用hyperf + gRPC 的同学相信都看过了文档中关于gRPC的实现 hyperf.wiki/3.0/#/zh-cn/grpc。按照文档跑成功的服务,是没有反射的,也就是使用 Use Server Reflection 提示了异常。

先解释下为何要使用gRPC服务反射,服务反射是在开发/测试阶段方便调试,我们都清楚gRPC是通过protobuf定义服务,服务端是基于服务定义实现,而客户端也是基于服务定义去调用。gRPC 服务反射它能提供服务的定义信息,简单的来说,就是服务反射向客户端提供了服务的定义。 因此客户端不需要预编译服务定义就能与服务端进行交互。

当然可以不选择服务反射,我们可以在Postman中选用导入.proto文件。但每次定义文件更新就得跟着更新(再导入),就变成了……. 是的,难受

这个时候就开始羡慕起用GO实现的gRPC服务,只要注册反射就能享用,更新了定义点刷新就可以了

不行!PHP也得拥有!!!

模仿

是的,最快解决的方式就是参照 GO gRPC库对服务反射的实现 github.com/grpc/grpc-go/blob/maste... (感兴趣的同学可以研究下)

其实就是实现gRPC服务对反射的定义,定义如下:

github.com/grpc/grpc/blob/master/s...

根据请求类型,分别把服务列表(ListServices)、服务定义(FileDescriptor)响应即可。

服务列表的实现相对简单,我们是通过路由定义了服务路径,因此获取路由就能得到服务列表。

服务定义(FileDescriptor)就复杂很多了,从GO实现上看是需要将 FileDescriptor 通过 proto.Marshal 转字节,再将字节类型的数据响应。当然在此之前我们还得通过两种方式找到 FileDescriptor,一种是 (file_by_filename) 通过文件名获取定义,例如 xxx/xxx/xxx.proto。另一种是(file_containing_symbol)通过声明获取 如:package.service.method。

了解了如何处理 就开干!

实现

第一步:肯定是先根据服务定义完成方法,配置好路由

第二步:实现不同的请求类型

这边我只实现了这三种请求类型,也能满足反射,但实际上还包括其他类型(感兴趣同学可以接着完成)。获取服务列表(ListServices)相对简单,大家可以看代码了解下github.com/crayxn/hyperf-grpc/blob... 。FileContainingSymbol、FileByFilename 两个其实是一样的就是为了获取到服务定义,并转byte类型 响应。

第三步:获取服务定义

跟Go不同的是,通过gRPC官方PHP插件生成的代码,是自带Byte类型的文件内容,再通过内容生成 FileDescriptor 并 存到 \Google\Protobuf\Internal\DescriptorPool 池里。

这边我为了偷懒,就直接rewrite了DescriptorPool 实现了通过类获取proto文件名、通过proto文件名获取服务定义内容。因为已经有Byte类型的定义内容就偷懒不再先获取FileDescriptor再去转Byte(找个借口,大家应该清楚php转byte的难受)。

第四步:响应

最后将不同请求类型对应的响应对象设置完成响应就可以了。

相关实现可以参照:github.com/crayxn/hyperf-grpc/blob...

运行demo可以参照:github.com/crayxn/grpc-stream-demo

如果对您有帮助,就点个赞吧

本作品采用《CC 协议》,转载必须注明作者和本文链接
from crayxn github.com/crayxn
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 6
CodingHePing

顶顶

1年前 评论
Crayxn (楼主) 1年前

:+1: :+1: :+1: :+1: :+1: :+1: :+1:

1年前 评论

file 大哥 我按着你的步骤和demo写了 服务能正常启动。之后 postman 反射不到接口 导入protocol 后访问接口就会报这个错 。

环境 用的你的docker 镜像

帮看看是啥问题

10个月前 评论
Crayxn (楼主) 10个月前
Rapidphil (作者) 10个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!