Tars - Cpp开发
本节主要介绍Tars Cpp服务开发和编译时需要的开发环境。
参考资料
编译包依赖下载
yum install glibc-devel gcc gcc-c++ bison flex
yum install zlib-devel
yum -y install libatomic
##cmake 需要单独安装3.0以上版本
1
2
3
4
2
3
4
下载项目源码
cd /home/klc/tars/
git clone https://github.com/TarsCloud/TarsCpp.git --recursive
cd ./TarsCpp/
git submodule update --init ##下载过程可能有些文件下载失败,可以进入TarsCpp文件夹后继续下载
mkdir build
cd build
cmake ..
make
make install
#gcc9.1需要修改的地方
ln -sf /usr/local/lib64/libstdc++.so.6.0.26 /lib64/libstdc++.so.6
直接把/lib64/libstdc++.so.6.0.19 移到其他路径下,创建上述软链接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
TarsCPP 快速入门
创建服务
cd /usr/local/tars/cpp/script/
./cmake_tars_server.sh TestApp HelloServer Hello
1
2
2
命令执行后,会在当前目录的/HelloServer/src 目录下,生成下面文件:
HelloServer.h HelloServer.cpp Hello.tars HelloImp.h HelloImp.cpp CMakeLists.txt
1
编译服务
cd ./HelloServer/build/
cmake ..
make -j4
1
2
3
2
3
服务实现
cd build
cmake ..
make -j4
make HelloServer-tar
make HelloServer-upload
1
2
3
4
5
2
3
4
5
重新make cleanall;make;make tar,会重新生成HelloServer.tgz发布包。
客户端同步/异步调用服务
mkdir -p /home/tarsproto/TestApp/HelloServer
make HelloServer-release
cd /home/tarsproto/
mkdir TestHelloClient
cd ./TestHelloClient/
touch main.cpp
touch makefile
make
./TestHelloClient
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
创建计算服务:
cd /usr/local/tars/cpp/script/
./cmake_tars_server.sh TestCalcApp CalcServer Calc
cd /usr/local/tars/cpp/script/CalcServer/build/
cmake ..
make -j4
make -j4
make CalcServer-tar
make cleanall;make;make tar
mkdir -p /home/tarsproto/TestCalcApp/CalcServer
make CalcServer-release
cd /home/tarsproto/
mkdir -p TestCalcClient
cd ./TestCalcClient/
touch main.cpp
touch makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
同步与异步主要代码:
int iRet = prx->testHello(sReq, sRsp);
cout<<"iRet:"<<iRet<<" sReq:"<<sReq<<" sRsp:"<<sRsp<<endl;
HelloPrxCallbackPtr cb = new HelloCallBack();
prx->async_testHello(cb, sReq);
cout<<" sReq:"<<sReq<<endl;
void HelloServer::initialize()
{
//initialize application here:
//...
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".HelloObj");
}
服务框架中有全局的结构ServerConfig,它记录了服务的基本信息。
ServerConfig的成员变量都是静态的,在服务框架初始化时会自动从服务配置文件中初始化这些参数。
例如,在web界面——运维管理——服务部署下面,设置需要部署服务的一些信息,应用、服务名称、Obj等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
基于对象的接口处理
所谓基于对象接口的处理表示该命令接口是针对服务中的对象的。
例如针对CalcImp对象,这个时候如果发送一个命令给服务,则每个线程中的CalcImp的命令接口都会被执行一次,并且执行这些接口的过程和执行HelloImp的自身的接口是互斥的(即线程安全的)。
假设CalcImp有成员变量my_str,需要发送命令通知每个CalcImp对象将_hello修改为自定义的值,步骤如下:
在CalcImp中增加处理函数
bool CalcImp::setStr(const std::string& command, const std::string& params, std::string& result)
{
TLOGDEBUG("CalcImp::setStr:"<<params<<endl);
my_str = params;
return true;
}
bool CalcImp::showStr(const std::string& command, const std::string& params, std::string& result)
{
TLOGDEBUG("CalcImp::showStr:"<<my_str<<endl);
return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
在CalcImp的初始化中注册函数:
void CalcImp::initialize()
{
//initialize servant here:
//...
//注册处理函数:
TARS_ADD_ADMIN_CMD_NORMAL("SETSTRING", CalcImp::setStr);
TARS_ADD_ADMIN_CMD_NORMAL("SHOWSTRING", CalcImp::showStr);
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
注意事项
/usr/local/tars/cpp/script/cmake_tars_server.sh [App] [Server] [Servant]
##会生成所需代码框架
采用tars2cpp工具自动生成c++文件:/usr/local/tars/cpp/tools/tars2cpp Hello.tars会生成Hello.h文件,里面包含客户端和服务端的代码( 编译时会自动处理)。
即客户端和服务器都需要Hello.h
服务端:HelloImp是Servant的接口实现类,需要用户实现Hello.tars所定义的接口
客户端:引用Hello.h头文件,调用接口的函数来测试调用是否正常。
生成的Hello.h中包含多种代理的类定义 和 服务提供者的定义
HelloPrxCallback /* callback of async proxy for client */
HelloCoroPrxCallback /* callback of coroutine async proxy for client */
HelloProxy /* proxy for client */
Hello /* servant for server */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
实际使用时,通过 通信器 Communicator 拿到代理对应的服务信息,然后进行调用。
Communicator comm;
try
{
HelloPrx prx;
comm.stringToProxy("TestApp.HelloServer.HelloObj@tcp -h 172.25.0.3 -p 20001" , prx);
try
{
string sReq("hello world");
string sRsp("");
int iRet = prx->testHello(sReq, sRsp);
cout<<"iRet:"<<iRet<<" sReq:"<<sReq<<" sRsp:"<<sRsp<<endl;
}
catch(exception &ex)
{
cerr << "ex:" << ex.what() << endl;
}
catch(...)
{
cerr << "unknown exception." << endl;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25