技术控

    今日:152| 主题:49194
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] grpc:google 官方的 rpc 框架

[复制链接]
【呆呆著看】 发表于 2016-10-16 16:46:45
155 2

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
protobuf是在项目中经常会用到的一个库,它提供了方便的工具和接口,可以对结构化数据进行序列化和反序列化,便于网络传输。
  其实,如果将一个函数调用用结构化数据表示出来,利用protobuf序列化后通过网络传递到远端,在远端进行反序列化解析,就自然地实现了rpc(Remote Procedure Call)的功能。
   protobuf中保留了关键字rpc,并且提供了一个RpcChannel的类,供开发者自己实现rpc框架。实现这个rpc框架,其实主要是实现RpcChannel::CallMethod这个接口。我们自己的项目中,就使用了一套自己实现的基于ansyncore的RpcChannel,而某度最近也开源了其基于protobuf的 rpc框架 ,网络部分是使用的Boost::Asio,有兴趣的读者可以自行前往其github wiki页面学习。
  那grpc呢,则是google自己基于protobuf(也是google自己开发的库)实现的一套rpc框架。这里使用一张官网的图,表示下其基础架构:
   
grpc:google 官方的 rpc 框架-1 (google,关键字,开发者,字符串,读者)

  一个简单的例子

  可能光说不练有点抽象,那么下面用一个例子说明下grpc的基本用法。
  说到网络相关的例子,简单而又实用的当属EchoServer了。
  定义一个EchoServer只需一个接口Echo,它接受一条字符串消息,并原样返回一条字符串消息。因此,echo_server.proto文件定义如下:
         [code]syntax = "proto3";package echo_server;service EchoServer{    rpc Echo (EchoRequest) returns (EchoReply) {}}message EchoRequest{    string msg = 1;}message EchoReply{    string msg = 1;}[/code]       首先,grpc使用protobuf3.x版本,因此需要在开头声明syntax=”proto3”,剩下的部分和c语言的语法很类似,基本上有了例子之后,照猫画虎很容易就可以写出来自己需要的proto文件。
  有了proto文件之后,需要使用protoc将其编译生成对应的py文件。这里grpc提供了一个grpc_tools的库,可以将这一过程程序化:
         [code]from grpc.tools import protocprotoc.main(    (        '',        '-I.',        '--python_out=.',        '--grpc_python_out=.',        './echo_server.proto',    ))[/code]       生成的echo_server_pb2.py文件中,就定义了我们实现这个EchoServer所需的Servicer类和Stub类。
  Server

  先看server的实现。
  首先,需要定义一个类,继承自xxxServicer(这里是EchoServerServicer),并重写其Echo方法。
         [code]class EchoServer(echo_server_pb2.EchoServerServicer):    def Echo(self, request, context):        return echo_server_pb2.EchoReply(msg='echo:%s' % request.msg)[/code]       可以看到,其中的request和return值,都是按照我们在proto文件中的定义生成的python类型,非常直观。
  如何将这个EchoServer类和rpc服务绑定在一起,也是有套路的:
         [code]server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))echo_server_pb2.add_EchoServerServicer_to_server(EchoServer(), server)server.add_insecure_port('[::]:50015')server.start()try:    while True:        time.sleep(60*60)except KeyboardInterrupt:    server.stop(0)[/code]       由于server.start()是一个非阻塞式调用,因此需要在后面用一个死循环来防止程序终止/GC导致rpc服务不可用。
  Client

  Client的实现就更简单了,只需通过ip和port创建一个channel,然后利用这个channel创建一个本地的Stub,然后就可以直接Stub.Echo调用远端的Echo方法了,Stub会帮你处理好一切其他事务(构造调用的结构化数据,序列化,网络传输等等)。
         [code]from __future__ import print_functionimport grpcimport echo_server_pb2import sysif sys.version_info.major == 3:    raw_input = inputelse:    raw_input = raw_inputdef run():    channel = grpc.insecure_channel('localhost:50015')    stub = echo_server_pb2.EchoServerStub(channel)    while True:        msg = raw_input('you say:')        reply = stub.Echo(echo_server_pb2.EchoRequest(msg=msg))        print(reply.msg)    passif __name__ == "__main__":    run()[/code]       这段代码中对print和raw_input这两个py2和py3不兼容的调用打了Monkey Patch,从而使得这段程序可以同时运行在py2和py3的环境中~
  总结

  至此,grpc的最基础的应用就说的差不多了。除了上面的阻塞式调用,grpc还提供了非阻塞式调用(future)。另外,对于传递的参数和返回值,grpc还支持流式参数(stream、yield)。具体的相关例子,有兴趣的读者可以前往grpc的官网查询。
  接下来,我将会使用grpc做一个message hub的应用,功能上应该可以替代目前项目中使用的hub(性能上就不指望替代了,毕竟当前hub使用c++实现的),当作一个练手的实际项目。敬请期待^_^
   完整代码详见 grpc
   转载请注明出处: http://blog.guoyb.com/2016/10/15/grpc/
     欢迎使用微信扫描下方二维码,关注我的微信公众号TechTalking,技术·生活·思考:

grpc:google 官方的 rpc 框架-2 (google,关键字,开发者,字符串,读者)

友荐云推荐




上一篇:备忘下:如何给chromium提交patch
下一篇:Data Science 101
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

Y|"_律_ 发表于 2016-10-17 02:34:24
OMG!介是啥东东!!!
回复 支持 反对

使用道具 举报

36999 发表于 2016-10-17 15:26:46
【呆呆著看】接下来收到的所有回帖都是我安排他们顶你的。我为人就两个字“低调”!你知道就行了!
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表