青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

loop_in_codes

低調做技術__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

基于protobuf的RPC實現

可以對照使用google protobuf RPC實現echo service一文看,細節本文不再描述。

google protobuf只負責消息的打包和解包,并不包含RPC的實現,但其包含了RPC的定義。假設有下面的RPC定義:

service MyService {
        rpc Echo(EchoReqMsg) returns(EchoRespMsg) 
    }

那么要實現這個RPC需要最少做哪些事?總結起來需要完成以下幾步:

客戶端

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(), ...
        ...
    }

服務端

服務端首先需要實現RPC接口,直接實現MyService中定義的接口:

class MyServiceImpl : public MyService {
        virtual void Echo(::google::protobuf::RpcController* controller,
            const EchoReqMsg* request,
            EchoRespMsg* response,
            ::google::protobuf::Closure* done) {
            ...
            done->Run();
        }
    }

標示service&method

基于以上,可以看出服務端根本不知道客戶端想要調用哪一個RPC接口。從服務器接收到網絡消息,到調用到MyServiceImpl::Echo還有很大一段距離。

解決方法就是在網絡消息中帶上RPC接口標識。這個標識可以直接帶上service name和method name,但這種實現導致網絡消息太大。另一種實現是基于service name和method name生成一個哈希值,因為接口不會太多,所以較容易找到基本不沖突的字符串哈希算法。

無論哪種方法,服務器是肯定需要建立RPC接口標識到protobuf service對象的映射的。

這里提供第三種方法:基于option的方法。

protobuf中option機制類似于這樣一種機制:service&method被視為一個對象,其有很多屬性,屬性包含內置的,以及用戶擴展的。用戶擴展的就是option。每一個屬性有一個值。protobuf提供訪問service&method這些屬性的接口。

首先擴展service&method的屬性,以下定義這些屬性的key:

extend google.protobuf.ServiceOptions {
      required uint32 global_service_id = 1000; 
    }
    extend google.protobuf.MethodOptions {
      required uint32 local_method_id = 1000;
    }

應用層定義service&method時可以指定以上key的值:

service MyService
    {
        option (arpc.global_service_id) = 2302; 

        rpc Echo(EchoReqMsg) returns(EchoRespMsg) 
        {
            option (arpc.local_method_id) = 1;
        }
        rpc Echo_2(EchoReqMsg) returns(EchoRespMsg) 
        {
            option (arpc.local_method_id) = 2;
        }
        ...
    }

以上相當于在整個應用中,每個service都被賦予了唯一的id,單個service中的method也有唯一的id。

然后可以通過protobuf取出以上屬性值:

void CallMethod(const ::google::protobuf::MethodDescriptor* method,
                  ::google::protobuf::RpcController* controller,
                  const ::google::protobuf::Message* request,
                  ::google::protobuf::Message* response,
                  ::google::protobuf::Closure* done) {
        ...
        google::protobuf::ServiceDescriptor *service = method->service();
        uint32_t serviceId = (uint32_t)(service->options().GetExtension(global_service_id));
        uint32_t methodId = (uint32_t)(method->options().GetExtension(local_method_id));
        ...
    }

考慮到serviceId methodId的范圍,可以直接打包到一個32位整數里:

uint32_t ret = (serviceId << 16) | methodId;

然后就可以把這個值作為網絡消息頭的一部分發送。

當然服務器端是需要建立這個標識值到service的映射的:

bool MyRPCServer::registerService(google::protobuf::Service *rpcService) {
        const google::protobuf::ServiceDescriptor = rpcService->GetDescriptor();
        int methodCnt = pSerDes->method_count();

        for (int i = 0; i < methodCnt; i++) {
            google::protobuf::MethodDescriptor *pMethodDes = pSerDes->method(i);
            uint32_t rpcCode = PacketCodeBuilder()(pMethodDes); // 計算出映射值
            _rpcCallMap[rpcCode] = make_pair(rpcService, pMethodDes); // 建立映射
        }
        return true;
    }

服務端收到RPC調用后,取出這個標識值,然后再從_rpcCallMap中取出對應的service和method,最后進行調用:

google::protobuf::Message* response = _pService->GetResponsePrototype(_pMethodDes).New();
    // 用于回應的closure
    RPCServerClosure *pClosure = new (nothrow) RPCServerClosure( 
            _channelId, _pConnection, _pReqMsg, pResMsg, _messageCodec, _version);
    RPCController *pController = pClosure->GetRpcController();
    ...
    // protobuf 生成的CallMethod,會自動調用到Echo接口
    _pService->CallMethod(_pMethodDes, pController, _pReqMsg, pResMsg, pClosure);

參考

posted on 2014-08-31 19:40 Kevin Lynx 閱讀(6682) 評論(0)  編輯 收藏 引用 所屬分類: c/c++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            午夜在线不卡| 一本色道久久综合亚洲二区三区| 国产精品草莓在线免费观看| 亚洲综合色激情五月| 亚洲高清免费在线| 久久aⅴ国产紧身牛仔裤| 国产精品久久午夜| 国产精品分类| 欧美视频一区二区三区四区| 欧美精品一区在线播放| 麻豆国产精品va在线观看不卡 | 亚洲激情视频在线| 国产精品影片在线观看| 欧美日韩在线免费| 欧美视频一区| 国产精品午夜在线| 国产精品免费视频观看| 国产精品视频99| 国产精品一区免费在线观看| 久久综合亚州| 欧美成人免费网| 欧美黄污视频| 欧美肉体xxxx裸体137大胆| 国产精品二区在线| 一区二区三区久久久| 亚洲精美视频| 毛片av中文字幕一区二区| 久久久精品一区| 久热国产精品| 亚洲成人直播| 亚洲精品日韩在线观看| 一本不卡影院| 欧美一区二区三区喷汁尤物| 久久精品国产成人| 久久亚洲精品欧美| 欧美精品一区二区三区四区| 国产精品盗摄久久久| 欧美日本中文字幕| 国产精品久久久久久久久久免费看| 国产精品乱码一区二三区小蝌蚪 | 亚洲制服欧美中文字幕中文字幕| 午夜精品国产| 嫩草国产精品入口| 夜夜精品视频| 久久天天躁夜夜躁狠狠躁2022| 欧美.日韩.国产.一区.二区| 国产精品国产精品国产专区不蜜| 国产亚洲精品aa| 国产一区二区三区在线免费观看| 亚洲日本免费| 久久大逼视频| 亚洲精品老司机| 久久国产一区二区| 欧美亚洲第一页| 亚洲黄色在线| 久久福利一区| 99精品国产高清一区二区| 久久久欧美一区二区| 国产精品v欧美精品v日韩精品| 欧美小视频在线观看| 亚洲成色www8888| 亚洲一区二区三区色| 欧美高清视频在线观看| 亚洲欧美精品suv| 欧美日韩视频在线一区二区| 激情伊人五月天久久综合| 在线亚洲精品| 亚洲第一精品夜夜躁人人躁| 久久综合婷婷| 日韩一区二区精品| 欧美 日韩 国产 一区| 国产一区二区三区无遮挡| 亚洲网友自拍| 亚洲精品视频免费观看| 亚洲欧美日韩一区二区三区在线| 欧美日本中文字幕| 欧美福利一区二区| 亚洲一区二区免费看| 噜噜噜在线观看免费视频日韩| 亚洲午夜视频在线观看| 欧美激情在线有限公司| 91久久久久久久久久久久久| 欧美 日韩 国产 一区| 久久日韩精品| 亚洲国产高清在线| 久久www成人_看片免费不卡| 亚洲手机视频| 国产精品久久久久三级| 亚洲一区二区三区精品视频| 亚洲黄色一区| 美女国产精品| 99精品久久久| 亚洲欧美日本日韩| 在线观看一区视频| 亚洲欧洲精品一区二区三区| 国产精品v亚洲精品v日韩精品| 欧美一区二区视频免费观看| 久久精品人人做人人综合| 在线欧美不卡| 亚洲天堂久久| 一区二区三区在线不卡| 99精品欧美一区| 久久久99国产精品免费| 欧美成人激情在线| 久久aⅴ国产欧美74aaa| 免费在线观看日韩欧美| 午夜视频一区| 亚洲免费在线精品一区| 亚洲欧洲免费视频| 亚洲免费影院| 99精品欧美一区二区蜜桃免费| 欧美亚洲在线观看| 99re6这里只有精品| 欧美在线高清| 亚洲影院色在线观看免费| 欧美成人精品在线视频| 老巨人导航500精品| 国产精品青草综合久久久久99| 亚洲国产精品尤物yw在线观看| 国产一区二区精品在线观看| 99精品免费| 亚洲美女色禁图| 久久久国产成人精品| 欧美一区二区三区四区视频| 欧美日韩精品综合在线| 亚洲激情在线观看视频免费| 亚洲国产美国国产综合一区二区| 欧美一区二区精品| 亚洲欧美日韩天堂| 欧美日韩一区二区欧美激情| 亚洲国产欧美在线人成| 亚洲大胆女人| 久久精品国产清高在天天线| 久久精品国产69国产精品亚洲| 国产精品欧美一区二区三区奶水| 99在线|亚洲一区二区| 一区二区三区国产精华| 欧美精品导航| 亚洲精品美女91| 亚洲精品在线免费| 久久久噜噜噜| 黑人巨大精品欧美黑白配亚洲| 香蕉久久夜色精品国产使用方法| 欧美成人情趣视频| 久久久福利视频| 伊人久久噜噜噜躁狠狠躁| 久久久久久久久久久一区| 欧美亚洲三区| 国产精品亚洲精品| 在线一区欧美| 亚洲神马久久| 欧美日韩免费网站| 一本色道久久综合狠狠躁篇怎么玩| 久久精品视频播放| 久久亚洲午夜电影| 激情五月综合色婷婷一区二区| 久久久蜜桃一区二区人| 久久国产日韩| 亚洲国内精品在线| 亚洲第一搞黄网站| 亚洲视频播放| 欧美日韩国产成人在线91| 亚洲乱码国产乱码精品精| 亚洲欧美福利一区二区| 国产精品女主播一区二区三区| 亚洲视频在线视频| 性欧美18~19sex高清播放| 欧美超级免费视 在线| 亚洲黄色免费网站| 欧美日韩情趣电影| 亚洲一级网站| 欧美亚洲一区二区在线| 国产欧美午夜| 久久久精品国产99久久精品芒果| 久久久亚洲人| 亚洲国产精品成人一区二区| 欧美国产成人精品| 一本色道久久88综合亚洲精品ⅰ| 亚洲图片欧美日产| 欧美电影免费观看高清完整版| 最新日韩在线| 亚洲欧美久久久久一区二区三区| 国产精品嫩草99a| 一本久道综合久久精品| 香蕉免费一区二区三区在线观看| 一区在线播放视频| 欧美交受高潮1| 午夜伦欧美伦电影理论片| 美女日韩欧美| 亚洲激情在线播放| 欧美视频官网| 久久三级福利| 国产精品99久久久久久久久久久久| 久久综合给合| 在线亚洲观看| 狠狠色伊人亚洲综合网站色| 欧美激情va永久在线播放| 久久国产精品久久w女人spa| 亚洲第一中文字幕| 亚久久调教视频|