大家好~我是
米洛
!
我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程
,希望大家多多支持。
欢迎关注我的公众号米洛的测开日记
,获取最新文章教程!
# 回顾
上一节我们浅谈了支持grpc的相关思路,只抛出了问题,但没有解决问题
,那这一节我们就来聊聊相关的解决方案。
# 核心问题
回到之前的核心问题,我们在进行一次grpc的请求时,首先不太明确服务部署的地址
,当服务是多节点部署的时候,我们希望能够自动获取到服务的ip和端口。这个问题挺好解决,业内常用的注册中心就那几种,还记得我们之前讲过的系统设置
页面吗?
系统设置里面现在可以多加一项,注册中心类型/注册中心地址/服务/方法节点路径,根据配置好的设置针对不同的注册中心,完成我们想要的功能。
但还有一个stub的问题,这个虽然比较麻烦,但也不是没有办法解决
。
# grpcurl
上一节我们提到过一个关键词: grpc_reflection
。没错,这就是我们解决问题的关键。
在介绍反射的时候,我们先来看看一款工具: grpcurl(github一搜就知道)
不难发现,其实它是一款类似于CURL
的工具,基于go编写。api也和curl比较接近,但有个问题,它并没有提供python的api。
由于我具备go代码
的阅读能力,所以我很好奇它是怎么支持无proto调用grpc接口
的,为此我前段时间一直在阅读它的源码。
在阅读他代码的时候,我意外地发现了grpc的一个特质: grpc_reflection,这个简单的说就是grpc反射。(资料也相当少)
# 服务端开启反射
- 安装grpcio-reflection
pip install grpcio-reflection
- 允许服务开启反射
这边别忘记
from grpc_reflection.v1alpha import reflection
这样启动的时候,服务就开启了反射,我们就可以用grpcurl请求接口了。
简单的说,在grpc服务启动的时候,如果打开了grpc_reflection开关,那么它会自带额外的几个grpc接口,而我们使用的grpcurl也是基于这个原理而工作的。我们来看看它们一一做了些什么
我们可以看到,反射的服务,主要提供了一个反射服务,里面会有file_by_filename,list_services等方法。其中list_services可以列举出你这个ip+port下的grpc服务有哪些服务,核心的实现方法都在这:
为此本人熬了2天左右,终于完成了一个可以摆脱proto
的类似grpcurl的实现,在此感谢grpcurl提供的思路。(对着源码debug)
最终的实现效果如下:
只需要自己定义一个Stub(因为反射也是个grpc服务,所以我们还是得通过生成反射的stub去获取服务的信息)。
上面的res是获取服务列表并打印,与下面的调用没关系,实际上调用的方法只需要:
md = Stub.client(channel, "Hello", "Edit")
params = dict(data="李逍遥")
data = hello_pb2.Request(**params)
response = md(data)
print(response.message)
2
3
4
5
6
md是通过反射的客户端+服务名+方法名获取到方法,接着直接传入dict即可调用方法。
# 两级反转
为啥要做这个库,因为我确实没搜到类似的实现。就当我优化了一些版本,还没支持异步
,也没完善各种api的时候,我得意地想把我这个版本传到pypi帮助其他人。
关于命名,我想要它以后和requests一样好用,所以我毫不犹豫叫了grpc-requests,发现一直上传失败。
我在pypi搜索,结果发现一个韩国哥们早就实现了,而且做的还比我屌多了,我比克大魔王当时脸都绿了!!!
我下载了试用了一番,别人已经碉堡了,而且测下来也没发现啥问题。
所以我肝2天肝了个寂寞,不过把具体的api是熟悉
了一遍。所以大家如果有类似需求,直接用这个库就可以了!!!
(我还是咬着牙传了自己的项目到pypi)
# 这哥们说,如果你的服务开启了反射,你可以自动获取到方法等数据,否则可以继续用stub去调用。我看了这哥们的实现,代码确实写的好过我很多。
今天的内容就介绍到这里了,关于后续的想法,grpc也是可以根据文件获取到服务信息,唯一我们以后能做的就是根据proto生成接口文档。
(我想这个就算个卖点吧,各位有兴趣也可以自行实现哈!)