什么是rpc
RPC(Remote Procedure Call),远程过程调用,它把网络交互类比为client调用server上的函数。RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明调用机制,让使用者不必显式的区分本地调用和远程调用。
srpc特点
- 序列化方案用的是protobuf
- 服务器端采用workflow:每当有客户端调用时,服务端会创建一个特殊的任务,其基本工作和回调是分开的
- 代理模式
安装
protobuf的安装
git clone -b 3.20.x https://github.com/protocolbuffers/protobuf.git protobuf.3.20
cd protobuf.3.20
sh autogen.sh
./configure
make
make install
srpc的安装
安装srpc的前置条件是要先安装 protbuf ,之后再来安装 srpc
git clone --recursive https://github.com/sogou/srpc.git
cd srpc
make
make install
快速开始
proto文件编写
syntax = "proto3";
message EchoRequest {
string message = 1;
string name = 2;
};
message EchoResponse {
string message = 1;
};
service Example {
rpc Echo(EchoRequest) returns (EchoResponse);
};
生成srpc代码
protoc example.proto --cpp_out=./ --proto_path=./
srpc_generator protobuf ./example.proto ./
输出
从中可以看出主要是生成了./srpc_test.srpc.h
文件和 服务端文件./server.pb_skeleton.cc
和客户端文件./client.pb_skeleton.cc
[Generator Begin]
proto file: [/home/xf/projects/test/./srpc_test.proto]
Successfully parse service block [message] : EchoRequest
Successfully parse service block [message] : EchoResponse
Successfully parse service block [service] : Example
Successfully parse method:Echo req:EchoRequest resp:EchoResponse
finish parsing proto file: [/home/xf/projects/test/./srpc_test.proto]
[Generator] generate srpc files: ./srpc_test.srpc.h
[Generator Done]
[Generator] generate server files: ./server.pb_skeleton.cc, client files: ./client.pb_skeleton.cc
[Generator Done]
生成文件一窥
服务端代码
可以看出srpc
服务端还是很简单的,只需要继承Service
类重写Echo
方法即可
/*
* Server codes
* Generated by SRPC
*/
class Service : public srpc::RPCService
{
public:
// please implement these methods in server.cc
virtual void Echo(EchoRequest *request, EchoResponse *response,
srpc::RPCContext *ctx) = 0;
public:
Service();
};
客户端代码
客户端相对来说要多很多内容
Echo
同步调用async_Echo
异步调用create_Echo_task
通过workflow
的方式调用
/*
* Client codes
* Generated by SRPC
*/
using EchoDone = std::function<void (EchoResponse *, srpc::RPCContext *)>;
class SRPCClient : public srpc::SRPCClient
{
public:
void Echo(const EchoRequest *req, EchoDone done);
void Echo(const EchoRequest *req, EchoResponse *resp, srpc::RPCSyncContext *sync_ctx);
WFFuture<std::pair<EchoResponse, srpc::RPCSyncContext>> async_Echo(const EchoRequest *req);
public:
SRPCClient(const char *host, unsigned short port);
SRPCClient(const struct srpc::RPCClientParams *params);
public:
srpc::SRPCClientTask *create_Echo_task(EchoDone done);
};
还能看见srpc
除了提供workflow
的方式,还提供了http
,brpc
,trpc
,trpchttp
等方式调用
服务端示例代码
#include <stdio.h>
#include <signal.h>
#include "example.srpc.h"
using namespace srpc;
class ExampleServiceImpl : public Example::Service
{
public:
void Echo(EchoRequest *request, EchoResponse *response, RPCContext *ctx) override
{
response->set_message("Hi, " + request->name());
printf("get_req:\n%s\nset_resp:\n%s\n",
request->DebugString().c_str(), response->DebugString().c_str());
}
};
void sig_handler(int signo) { }
int main()
{
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
SRPCServer server_tcp;
SRPCHttpServer server_http;
ExampleServiceImpl impl;
server_tcp.add_service(&impl);
server_http.add_service(&impl);
server_tcp.start(1412);
server_http.start(8811);
getchar(); // press "Enter" to end.
server_http.stop();
server_tcp.stop();
return 0;
}
客户端示例代码
#include <stdio.h>
#include "example.srpc.h"
using namespace srpc;
int main()
{
Example::SRPCClient client("127.0.0.1", 1412);
EchoRequest req;
req.set_message("Hello, srpc!");
req.set_name("workflow");
client.Echo(&req, [](EchoResponse *response, RPCContext *ctx) {
if (ctx->success())
printf("%s\n", response->DebugString().c_str());
else
printf("status[%d] error[%d] errmsg:%s\n",
ctx->get_status_code(), ctx->get_error(), ctx->get_errmsg());
});
getchar(); // press "Enter" to end.
return 0;
}
编译示例
g++ -o server server.cc example.pb.cc -std=c++11 -lsrpc
g++ -o client client.cc example.pb.cc -std=c++11 -lsrpc
运行
./server
./client
#server
get_req:
message: "Hello, srpc!"
name: "workflow"
set_resp:
message: "Hi, workflow"
#client
message: "Hi, workflow"