FarelDB的RPC远程过程调用
1. 概念
RPC(Remote Procedure Call Protocol) 远程过程调用协议。RPC是一种通过网络从远程计算机程序上请求服务,不需要了解底层网络技术的协议。RPC主要作用就是不同的服务间方法调用就像本地调用一样便捷。
FarelDB提供的RPC功能进一步简化了开发者实现RPC的过程,将重心放在RPC提供的业务上,无需太多关注RPC的底层通讯。
2. FarelDB RPC架构图
FarelDBRPC整体架构图
上图中,左侧为RPC客户端,右侧为RPC服务器端,中间为FarelDB服务。
(1) 启动FarelDB服务
(2) RPC服务端连接上FarelDB服务后,启动RPC服务,将其提供的函数注册到FarelDB中。此时FarelDB的inner_db_sys数据库的inner_table_rpcs中会显示所有注册FarelDB的RPC函数。
(3) RPC客户端连接上FarelDB服务后,可直接调用inner_table_rpcs表中的RPC函数。
具体流程如下图所示
3. 相关API说明
(1)连接FarelDB服务 (connect)
(2)RPC服务器端 启动RPC(startRpcService)
(3)RPC服务器端 注册RPC函数(registRpcFunc)
(4)RPC客户端 调用RPC(callRpcFunc)
(5)RPC服务器端 关闭RPC调用通道 (closeCallRpcFuncChannel)
(6)RPC服务器端 停止RPC服务(stopRpcService)
(7)RPC服务器端 注销已经注册的RPC函数(unregistRpcFunc)
(8)RPC服务器端 注销所有已经注册的RPC函数(unregistAllRpcFunc)
(1)连接FarelDB服务 (connect)
RPC服务端连接上FarelDB服务,以便后续过程的调用
见FarelDB 连接服务器
(2)RPC服务器端,启动RPC(startRpcService)
在RPC服务端启动端口监听,等他其他客户端程序的连接。
函数原型
tuple<int, std::string> startRpcService(std::string host, int port) |
---|
输入参数说明
输入参数 | 描述 | 可选 |
---|---|---|
host | RPC服务端主机IP地址 | 否 |
port | RPC服务使用的端口号 | 否 |
返回参数说明
tuple<int, std::string>
调用正常返回
返回参数 | 值 | 含义 |
---|---|---|
int | 0 | 调用成功,正常返回 |
string | 空字符串 | 调用成功 返回空字符串 |
调用异常返回
返回参数 | 值 | 含义 |
---|---|---|
int | 大于0的数值 | 调用错误,返回错误代码 |
string | 非空字符串 | 调用错误,返回 错误信息字符串 |
(3)RPC服务器端,注册RPC函数(registRpcFunc)
将对外公开的RPC函数在FarelDB上注册,成功注册后,可在FarelDB的inner_db_sys库的inner_table_rpcs表格中显示。
函数原型
FarelDbRpcRes* registRpcFunc(std::string rpcName, std::function< std::vector<FarelDbRpcData*>(std::vector<FarelDbRpcData*>&)> rpcFunc) |
---|
输入参数说明
输入参数 | 描述 | 可选 |
---|---|---|
rpcName | 注册到FarelDB中的RPC函数名 | 否 |
rpcFunc | 被调用的RPC函数名 | 否 |
返回参数说明
FarelDbRpcRes
调用成功返回
返回参数 | 值 | 含义 |
---|---|---|
FarelDbRpcRes->errorInfos.size() | 0 | 调用成功,无错误信息 |
调用异常返回
返回参数 | 值 | 含义 |
---|---|---|
FarelDbRpcRes->errorInfos.size() | 大于0 | 调用失败,errorInfos对象数组包含1个或多个错误信息 |
FarelDbRpcRes->errorInfos[0]->resCode | 大于0的数值 | 调用失败,返回错误代码 |
FarelDbRpcRes->errorInfos[0]->resInfo | 非空字符串 | 调用失败,返回错误信息字符串 |
(4)RPC客户端,调用RPC(callRpcFunc)
成功注册的RPC程序,可以被其他客户端调用执行,
函数原型
FarelDbRpcRes* callRpcFunc(std::string rpcName, std::vector<FarelDbRpcData*>& datas) |
---|
输入参数说明
输入参数 | 描述 | 可选 |
---|---|---|
rpcName | 注册到FarelDB中的RPC函数名 | 否 |
datas | RPC函数调用所需的参数 | 否 |
返回参数说明
FarelDbRpcRes
调用成功返回
返回参数 | 值 | 含义 |
---|---|---|
FarelDbRpcRes->errorInfos.size() | 0 | 调用成功,无错误信息 |
调用异常返回
返回参数 | 值 | 含义 |
---|---|---|
FarelDbRpcRes->errorInfos.size() | 大于0 | 调用失败,errorInfos对象数组包含1个或多个错误信息 |
FarelDbRpcRes->errorInfos[0]->resCode | 大于0的数值 | 调用失败,返回错误代码 |
FarelDbRpcRes->errorInfos[0]->resInfo | 非空字符串 | 调用失败,返回错误信息字符串 |
(5)RPC服务器端 关闭RPC调用通道 (closeCallRpcFuncChannel)
关闭RPC的通道后,TCP的连接保持,但注册的函数已不可用。
函数原型
void closeCallRpcFuncChannel(std::string rpcName) |
---|
输入参数说明
输入参数 | 描述 | 可选 |
---|---|---|
rpcName | 注册到FarelDB中的RPC函数名 | 否 |
返回参数说明
void 无返回值
(6)RPC服务器端 停止RPC服务(stopRpcService)
停止RPC服务端的监听程序,RPC客户端程序将无法连到此RPC服务。
函数原型
void stopRpcService() |
---|
输入参数说明
无
返回参数说明
无
(7)RPC服务器端 注销已经注册的RPC函数(unregistRpcFunc)
将此函数从FarelDB服务中移除,其他程序无法调用此函数。
函数原型
FarelDbRpcRes* unregistRpcFunc(std::string rpcName) |
---|
输入参数说明
输入参数 | 描述 | 可选 |
---|---|---|
rpcName | 注册到FarelDB中的RPC函数名 | 否 |
返回参数说明
FarelDbRpcRes
调用成功返回
返回参数 | 值 | 含义 |
---|---|---|
FarelDbRpcRes->errorInfos.size() | 0 | 调用成功,无错误信息 |
调用异常返回
返回参数 | 值 | 含义 |
---|---|---|
FarelDbRpcRes->errorInfos.size() | 大于0 | 调用失败,errorInfos对象数组包含1个或多个错误信息 |
FarelDbRpcRes->errorInfos[0]->resCode | 大于0的数值 | 调用失败,返回错误代码 |
FarelDbRpcRes->errorInfos[0]->resInfo | 非空字符串 | 调用失败,返回错误信息字符串 |
(8)RPC服务器端 注销所有已经注册的RPC函数(unregistAllRpcFunc)
注销当前RPC服务器端的所有RPC函数。
函数原型
void unregistAllRpcFunc() |
---|
输入参数说明
无
返回参数说明
无
4.样例代码
#include <iostream>
#include <functional>
#include <memory>
#include "fareldb_connection.h"
using namespace std;
using namespace fareldb_connection;
//全局链接对象
FarelDbConnection g_connFarelDB;
string g_FarelDB_server_IP = "127.0.0.1"; //需要连接的FarelDB服务端IP地址
int g_FarelDB_server_Port = 6800; //需要连接的FarelDB服务端端口号
string g_FarelDB_server_UserName = ""; //需要连接的FarelDB服务端端的连接用户名
string g_FarelDB_server_Passward = ""; //需要连接的FarelDB服务端端的连接用密码
std::vector<FarelDbRpcData*> rpcSumFunction(std::vector<FarelDbRpcData*>& paraIn)
{
//RPC调用返回信息对象
vector<FarelDbRpcData*> rpcReturn;
string errorCode = "0";
string errorInfo = "";
rpcReturn.clear();
if (paraIn.size() < 2)
{
string errorCode = "-9999";
string errorInfo = "Parameter is not enough, the rpc function 'sum(int a, int b)' needs two parameters in.";
printf("\n %s \n", errorInfo.c_str());
//组装成Json格式字符串返回错误信息
string val = "{";
val = val + "\"errorCode\":" + errorCode + "," + "\"errorInfo\":\"" + errorInfo + "\"";
val = val + ",\"rows\":[[0]]";
val = val + "}";
rpcReturn.push_back(new FarelDbRpcData(val));
}
else
{
int a = atoi(paraIn[0]->data);
int b = atoi(paraIn[1]->data);
//组装成Json格式字符串返回错误信息
string val = "";
val.append("{ \"errorCode\": 0 ,\"errorInfo\": \"\",\"res\":[[");
val.append(to_string(a + b));
val.append("]]}");
rpcReturn.push_back(new FarelDbRpcData(val));
}
return rpcReturn;
}
bool ConnectFarelDB()
{
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
//@note:获取连接库版本号
std::string ver = g_connFarelDB.getConnectionVersion();
//@note:获取连接库版本信息
std::string verT = g_connFarelDB.getConnectionReleaseTime();
//@note: 与Fareldb服务端连接,获取连接服务句柄
tuple<int, string> resConn = g_connFarelDB.connect(g_FarelDB_server_IP, g_FarelDB_server_Port, g_FarelDB_server_UserName, g_FarelDB_server_Passward);
if (0 != get<0>(resConn))
{
//连接失败
printf("连接 %s:%d 失败,错误代码:%d : 错误信息:%s\n", g_FarelDB_server_IP.c_str(), g_FarelDB_server_Port, get<0>(resConn), get<1>(resConn).c_str());
continue;
}
else
{
//连接成功
printf("连接 %s:%d 成功,链接库版本号:%s, 发布日期: %s \n", g_FarelDB_server_IP, g_FarelDB_server_Port, ver.c_str(), verT.c_str());
}
//- hisQuery 192.168.56.1 6800 usr psw 192.168.56.104 7001
//注册一个rpc服务端,以提供rpc服务
string rpc_server_IP = "127.0.0.10"; //提供RPC服务的服务端的IP地址
int rpc_server_Port = 7000; //提供RPC服务的服务端的端口号
string rpc_server_Function = "sum_a_b"; //提供RPC服务的服务端的服务名称,本例子提供一个传入两个数字,返回两个数字相加的求和函数,
//启动rpc服务
tuple<int, string> rpcRes = g_connFarelDB.startRpcService(rpc_server_IP, rpc_server_Port);
//启动rpc服务失败
if (0 != get<0>(rpcRes))
{
printf("启动rpc服务 %s:%d 调用失败,错误代码:%d : 错误信息:%s\n", rpc_server_IP.c_str(), rpc_server_Port, get<0>(rpcRes), get<1>(rpcRes).c_str());
return false;
}
//启动rpc服务成功
printf("成功连接 FarelDB实时库: %s:%d \n", rpc_server_IP.c_str(), rpc_server_Port);
//注册rpc函数
FarelDbRpcRes* rpcRegistor = g_connFarelDB.registRpcFunc(rpc_server_Function, rpcSumFunction);
if (rpcRegistor->errorInfos.size() > 0)
{
printf("rpc注册函数失败,错误代码:%d ; 错误信息: %s \n", rpcRegistor->errorInfos[0]->resCode, rpcRegistor->errorInfos[0]->resInfo.c_str());
return false;
}
else
{
printf("成功注册rpc函数: %s,等待被调用.\n", rpc_server_Function.c_str());
}
while(true) //让RPC服务端一直运行等待连接
std::this_thread::sleep_for(std::chrono::seconds(10));
}//end while(true)
}
//断连后回调重连
void onDisconnectFromFarelDBServerFunction(std::string disconnectInfo)
{
printf("\n------与FarelDB实时库服务端连接异常断开,开始重新建立连接FarelDB实时库服务端------\n");
ConnectFarelDB();
}
void rpcDemo()
{
//定义和FarelDB服务端断开连接后的回调函数
std::function<void(std::string)> funCallback = onDisconnectFromFarelDBServerFunction;
//设置连接断开时通知的回调函数,注意,必须在connect之前设置
g_connFarelDB.onDisconnectFromServer(funCallback);
ConnectFarelDB();
}
int main()
{
rpcDemo();
return 0;
}