According to the Google Protocol Buffers documentation under 'Defining Services' they say,
it's also possible to use protocol buffers with your own RPC implementation.
To my understanding, Protocol Buffers does not implement RPC natively. Instead, they provide a series of abstract interfaces that must be implemented by the user (Thats me!). So I want to implement these abstract interfaces utilizing ZeroMQ for network communication.
I'm trying to create an RPC implementation using ZeroMQ because the project i'm working on already implements ZeroMQ for basic messaging (Hence why I'm not using gRPC, as the documentation recommends).
After reading through the proto documentation thoroughly, i found that I have to implement the abstract interfaces RpcChannel and RpcController for my own implementation.
I've constructed a minimalized example of where I'm currently at with my RPC Implementation
.proto file: Omitted SearchRequest and SearchResponse schema for brevity
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
SearchServiceImpl.h:
class SearchServiceImpl : public SearchService {
public:
void Search(google::protobuf::RpcController *controller,
const SearchRequest *request,
SearchResponse *response,
google::protobuf::Closure *done) override {
// Static function that processes the request and gets the result
SearchResponse res = GetSearchResult(request);
// Call the callback function
if (done != NULL) {
done->Run();
}
}
}
};
MyRPCController.h:
class MyRPCController : public google::protobuf::RpcController {
public:
MyRPCController();
void Reset() override;
bool Failed() const override;
std::string ErrorText() const override;
void StartCancel() override;
void SetFailed(const std::string &reason) override;
bool IsCanceled() const override;
void NotifyOnCancel(google::protobuf::Closure *callback) override;
private:
bool failed_;
std::string message_;
};
MyRPCController.cpp - Based off of this
void MyRPCController::Reset() { failed_ = false; }
bool MyRPCController::Failed() const { return failed_; }
std::string MyRPCController::ErrorText() const { return message_; }
void MyRPCController::StartCancel() { }
void MyRPCController::SetFailed(const std::string &reason) {
failed_ = true;
message_ = reason;
}
bool MyRPCController::IsCanceled() const { return false; }
void MyRPCController::NotifyOnCancel(google::protobuf::Closure *callback) { }
MyRPCController::ChiRpcController() : RpcController() { Reset(); }
MyRpcChannel.h:
class MyRPCChannel: public google::protobuf::RpcChannel {
public:
void CallMethod(const google::protobuf::MethodDescriptor *method, google::protobuf::RpcController *controller,
const google::protobuf::Message *request, google::protobuf::Message *response,
google::protobuf::Closure *done) override;
};
Questions I have with my example thus far:
- Where do I fit ZeroMQ into this?
- It seems like it should be going into RPCChannel, because in the examples i see (See 3rd code block here), they pass a string that has the ports to bind to (i.e.
MyRpcChannel channel("rpc:hostname:1234/myservice");
)
- It seems like it should be going into RPCChannel, because in the examples i see (See 3rd code block here), they pass a string that has the ports to bind to (i.e.
- I'm concerned with my RPCController implementation, it seems too simple. Should more be going here?
- How do i implement RPCChannel, it seems very similar to the SearchServiceImpl. The 1 virtual function in these classes has a very similar method signature, except it's generic.
Here's some other Stack Overflow questions I came across that had some helpful information on the topic:
- Protobuf-Net: implementing server, rpc controller and rpc channel - This is where i found the example for the RPCController implementation.
- Using Protocol Buffers for implementing RPC in ZeroMQ - This answer is interesting because in the top answer, is seems that they're recommending against using Protobufs built in RPC formatting for the .proto file.
- I also noticed this same notion in this file, in a repository called libpbrpc which seemed like a good source for example code
- Can I/Should I be using an existing implementation such as RPCZ?
Thank you for your help. I hope I gave enough information and was clear in what I'm looking for. Please let me know if something is unclear or lacking in information. I'd be happy to edit the question accordingly.