RpcController

简单介绍google protobuf rpc框架使用方法

2017年06月15日 23:16:36 Yi白 阅读数 4532

对google protobuf定义的基本rpc框架学习了一下

基本rpc定义

  • RpcController 
    • An RpcController mediates a single method call. The primary purpose of the controller is to provide a way to manipulate settings specific to the RPC implementation and to find out about RPC-level errors.
    • The methods provided by the RpcController interface are intended to be a “least common denominator” set of features which we expect all implementations to support. Specific implementations may provide more advanced features (e.g. deadline propagation). // 给出最少必须实现的基类
    • 分为servise-side方法和client-side方法两类,提供交互情况 
      • 在Client每次调用方法时,都需要传入一个RpcController,其作用是: 
        • Client端在发送请求前 
          • 控制请求的超时时间
          • 设置Request或者Response的压缩类型;
        • Client端在请求完成后 
          • 获取(成功/失败)状态,如果失败可获取错误信息,检查请求是否已发送至远端;
      • 在Server端在服务实现内: 
        • 获取client端的地址,设置失败标志;
    • 注意事项 
      • RpcController用于控制单次请求,因此每次RPC请求(无论同步还是异步)都需要一个RpcController,在本次请求完成前,其不得释放或者重用;
      • 请求完成后,该RpcController可以使用Reset()方法恢复初始状态以进行重用;
      • RpcController的不同接口有不同的使用时间范围,只有在规定的时间范围内使用,接口才能返回正确结果,否则行为是不确定的;
  • RpcChannel

    • Abstract interface for an RPC channel. An RpcChannel represents a communication line to a Service which can be used to call that Service’s methods. The Service may be running on another machine. Normally, you should not call an RpcChannel directly, but instead construct a stub Service wrapping it.
    • CallMethod必须定义,用来序列化反序列化数据和发送数据。RPC客户端需要实现google::protobuf::RpcChannel。主要实现RpcChannel::CallMethod接口。客户端调用任何一个RPC接口,最终都是调用到CallMethod。这个函数的典型实现就是将RPC调用参数序列化,然后投递给网络模块进行发送。
    • 自定义

          void CallMethod(const ::google::protobuf::MethodDescriptor* method,
                            ::google::protobuf::RpcController* controller,
                            const ::google::protobuf::Message* request,
                            ::google::protobuf::Message* response,
                            ::google::protobuf::Closure* done) {
              ...
              // 只是示例,总之这个地方是发送请求,可以看你是实现异步还是同步。。
              DataBufferOutputStream outputStream(...) // 取决于你使用的网络实现
              request->SerializeToZeroCopyStream(&outputStream);
              _connection->postData(outputStream.getData(), ...
              ...
          }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • Example

         RpcChannel* channel = new MyRpcChannel("remotehost.example.com:1234");
         MyService* service = new MyService::Stub(channel);
         service->MyMethod(request, &response, callback);
      • 1
      • 2
      • 3
  • Service

    • Abstract base interface for protocol-buffer-based RPC services. Services themselves are abstract interfaces (implemented either by servers or as stubs), but they subclass this base interface. The methods of this interface can be used to call the methods of the Service without knowing its exact type at compile time (analogous to Reflection).
    • server端

      • 服务端需实现所有的rpc调用方法 
           class MyServiceImpl : public MyService {
               // 实现proto中声明的方法
               virtual void Echo(::google::protobuf::RpcController* controller,
                   const EchoReqMsg* request,
                   EchoRespMsg* response,
                   ::google::protobuf::Closure* done) {
                   ...
                   done->Run();
                   // 注意调了done->Run()之后,所有的四个参数都不再能访问。
               }
           }
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
    • client端

      • stub代码为自动生成代码,其中依赖RpcChannel中的CallBack方法去实现远程方法调用

            void EchoService_Stub::Foo(::google::protobuf::RpcController* controller,
                                          const ::FooRequest* request,
                                          ::FooResponse* response,
                                          ::google::protobuf::Closure* done) {
                channel_->CallMethod(descriptor()->method(0),
                                   controller, request, response, done);
            }
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7

        示意图


扩展

  • 上面只是简单地交互,要想实现一个完整的rpc通信框架需要丰富很多内容 
    • proto定义 
      • 考虑一个连接多次方法调用,由于服务端并不知道客户端想要调用哪一个RPC接口 ,此时需要在通信时携带rpc端口标识
    • 需要框架实现(参考sofa-rpc功能) 
      • 内存管理:如读写缓冲区、request/response管理、message queue之类的。。。
      • 多任务调度??
      • 支持同步or异步调用
      • 多级超时设定,超时控制更灵活
      • 流量控制
      • 支持透明压缩传输,节省带宽
      • 连接管理 
        • 自动建立连接、自动重连
        • 空闲连接自动关闭
        • 连接探活
      • …… 

参考连接

介绍RCP的实现原理 目录 1. 前言 2 2. 基本概念 3 2.1. IDL 3 2.2. 代理(Proxy) 3 2.3. 存根(Stub) 4 3. 三要素 4 3.1. 网络通讯 4 3.2. 消息编解码 5 3.3. IDL编译器 5 4. flex和bison 5 4.1. 准备概念 5 4.1.1. 正则表达式(regex/regexp) 6 4.1.2. 符号∈ 6 4.1.3. 终结符/非终结符/产生式 6 4.1.4. 记号(Token) 6 4.1.5. 形式文法 7 4.1.6. 上下文无关文法(CFG) 7 4.1.7. BNF 8 4.1.8. 推导 8 4.1.9. 语法树 8 4.1.10. LL(k) 9 4.1.11. LR(k) 9 4.1.12. LALR(k) 9 4.1.13. GLR 9 4.1.14. 移进/归约 9 4.2. flex和bison文件格式 9 4.2.1. 定义部分 10 4.2.2. 规则部分 10 4.2.3. 用户子例程部分 10 4.3. flex基础 10 4.3.1. flex文件格式 11 4.3.2. 选项 11 4.3.3. 名字定义 11 4.3.4. 词法规则 12 4.3.5. 匹配规则 12 4.3.6. %option 13 4.3.7. 全局变量yytext 13 4.3.8. 全局变量yyval 13 4.3.9. 全局变量yyleng 13 4.3.10. 全局函数yylex 13 4.3.11. 全局函数yywrap 13 4.4. bison基础 14 4.4.1. bison文件格式 14 4.4.2. %union 14 4.4.3. %token 15 4.4.4. 全局函数yyerror() 15 4.4.5. 全局函数yyparse() 15 4.5. 例1:单词计数 15 4.5.1. 目的 15 4.5.2. flex词法文件wc.l 16 4.5.3. Makefile 16 4.6. 例2:表达式 17 4.6.1. 目的 17 4.6.2. flex词法exp.l 17 4.6.3. bison语法exp.y 17 4.6.4. Makefile 19 4.6.5. 代码集成 19 4.7. 例3:函数 20 4.7.1. 目的 20 4.7.2. func.h 20 4.7.3. func.c 21 4.7.4. IDL代码func.idl 22 4.7.5. flex词法func.l 22 4.7.6. bison语法func.y 24 4.7.7. Makefile 27 5. 进阶 27 5.1. 客户端函数实现 27 5.2. 服务端函数实现 28 5.2.1. Stub部分实现 28 5.2.2. 用户部分实现 29 6. 参考资料 29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值