RPC implementation based on protobuf

Source: Internet
Author: User

You can refer to the article "echo service implementation" using Google protobuf rpc. The details are not described in this article.

Google protobuf is only responsible for the packaging and package of messages, and does not include RPC implementation, but contains the RPC definition. Suppose there is the following RPC definition:

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

So what do I need to do at least to implement this RPC? To sum up, you need to complete the following steps:

Client

RPC client implementationgoogle::protobuf::RpcChannel. Main ImplementationRpcChannel::CallMethodInterface. When the client calls any RPC interfaceCallMethod. A typical implementation of this function is to serialize the RPC call parameters and deliver them to the network module for sending.

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 (...) // depending on your network implementation request-> serializetozerocopystream (& outputstream); _ connection-> postdata (outputstream. getdata (),......}
Server

The server first needs to implement the RPC interface to directly implementMyServiceInterface defined in:

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

Based on the above, we can see that the server does not know which RPC interface the client wants to call. The server receives network messages and callsMyServiceImpl::EchoThere is still a long way to go.

The solution is to add the RPC Interface ID to the network message. This identifier can be directly carried with the service name and method name, but this implementation causes the network message to be too large. Another implementation is to generate a hash value based on service name and method name. because there are not many interfaces, it is easier to find a string hash algorithm that basically does not conflict with each other.

Either way, the server must establish a RPC ing between the RPC Interface ID and the protobuf service object.

Here we provide the third method: the option-based method.

In protobuf, the option mechanism is similar to this mechanism: Service & method is regarded as an object and has many attributes, including built-in attributes and user extensions. You can use the option extension. Each attribute has a value. Protobuf provides interfaces for accessing services and methods.

First, extend the attributes of Service & method. The following defines the keys of these attributes:

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

When the application layer defines service & method, you can specify the value of the above 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;        }        ...    }

The above is equivalent to that in the entire application, each service is assigned a unique ID, and the method in a single service also has a unique ID.

Then, you can use protobuf to retrieve the preceding attribute values:

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));        ...    }

ConsideringserviceId methodIdCan be directly packaged into a 32-bit integer:

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

Then, the value can be sent as part of the network message header.

Of course, the server needs to establish a service ing between the id value and the 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); // calculate the ing value _ rpccallmap [rpccode] = make_pair (rpcservice, pmethoddes); // creates a ing} return true ;}

After receiving the RPC call, the server extracts the id value and then_rpcCallMapTo obtain the corresponding service and method, and finally call:

Google: protobuf: Message * response = _ pservice-> getresponseprototype (_ pmethoddes ). new (); // closure rpcserverclosure * pclosure = new (nothrow) rpcserverclosure (_ channelid, _ pconnection, _ preqmsg, presmsg, _ messagecodec, _ version) for the response ); rpccontroller * pcontroller = pclosure-> getrpccontroller ();... // The callmethod generated by protobuf will automatically call the echo interface _ pservice-> callmethod (_ pmethoddes, pcontroller, _ preqmsg, presmsg, pclosure );
Reference
  • Implement echo service using Google protobuf RPC
  • Protobuf extensions
  • Protobuf Service
  • Protobuf options

Address: http://codemacro.com/2014/08/31/protobuf-rpc/
Written by Kevin Lynx posted athttp: // codemacro.com

RPC implementation based on protobuf

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.