中间件thirft的Linux部署与运用

来源:互联网 发布:太原手机数据恢复 编辑:程序博客网 时间:2024/06/03 13:34
前一段时间一直在想一个问题,一般的web服务器是如何和当前我的C++服务器进行通讯的。
当然方法有很多,比如我现在正值使用的gsoap,对于远程web主机来说,我只要提供一个内网的IP,它们就可以像调用webServer那样直接调用。
但是也遇到过几起因为gsoap组件出现的诡异问题,最奇怪的是,机房服务器有几次存储挂掉居然是因为goap崩溃了?虽然系统管理员给我的日志以及解释很站不住脚。
不过鉴于越写越庞大,以及越来越难以维护的gsoap代码(这里有历史原因)。我还是想找一个gsoap的替换方案。替换当前的方式。
以前写过一些中间件组件的代码,但是都太庞大。别说用了,光部署就要折腾半天时间。有没有简单好用的,可以支持不同语言,不同服务之间的通讯呢?
这里强烈感谢7CAT。他给了我很大的支持,并推荐了thrift这个组件。
但是,从安装到最后达成我自己写的测试用例,还是废了一番周折的,走了一些弯路,但是最后的结果是值得的,达到了我的预期效果。

首先,thrift可以从官方网站下载。http://thrift.apache.org/
实际大小很小,大概也就3.3M,当前最新版本0.9.1


下载以后,在Linux下开始编译。
但是编译顺序远非它的说明文档里面的那样简洁。
如果按照它的说明文档编译,你会遇到各种错误,
比如,你要加入各种 ./configure --with-qt4=no 这样的限制条件,默认它会采用认为你有qt4,对于纯命令行的服务器而言,这个是无用的。
就算这样,你还是会遇到编译失败(例子代码无法编译)。查询说必须去下载它的git,git也下载了,错误依然。
是在是没办法,于是只好手动去编译它,不让它去编译自己的例子。
以下是编译步骤,按照这个步骤0.9.1会编译成功。
  1. 1、编译compiler,
  2. 2、编译lib\cpp
  3. 3、进tutoials\cpp里编译。
复制代码
首先进入compiler的cpp目录,去make
再去lib\cpp里面去make
最后编译它的教程tutoials\cpp

好了,组件编译好了,下面来写一个标准的idl吧,以前写过ice的idl文件,看到这样的语法很亲切的感觉。

  1. namespace cpp mytest
  2. namespace java mytest

  3. /* Tag数据结构体声明 */
  4. struct Tag {
  5.   1: required i32 ntag = 0,
  6.   2: required string strData = "",
  7. }

  8. /* 相应的Tag列表 */ 
  9. typedef list<Tag> vecTags

  10. /* 声明相关接口 */
  11. service WebInfo{
  12.         void GetWebInfo(1:vecTags objData),
  13. }
复制代码

一个简单的例子,一个GetWebInfo方法,获得一个vector容器,并把容器内的数据打印出来
idl文件写好了,记得保存在compiler/cpp目录下。存为文件名mytest.thrift

实现相关代码
  1. class CWebInfo : public WebInfoIf
  2. {
  3. public:
  4.                 CWebInfo() {} ;
  5.                 
  6.                 void GetWebInfo(const vecTags& objData)
  7.                 {
  8.                         printf("[GetWebInfo]Begin(%d).\n", (int)objData.size());
  9.                         for(int i = 0; i < (int)objData.size(); i++)
  10.                         {
  11.                                 printf("[Data]ntag=%d,strData=%s.\n", objData[i].ntag, objData[i].strData.c_str());
  12.                         }
  13.                         printf("[GetWebInfo]End.\n");
  14.                 }
  15. };
复制代码




然后在linux下编译,让它生成中间文件。
  1. ./thrift --gen cpp mytest.thrift
复制代码
如果程序没问题的话,会在当前目录上生成 一个gen-cpp文件夹。
这些都是你需要的中间文件,你把这些文件拷贝到你自己的工程目录下。
比如,我把这些文件拷贝到了我的idl目录下。
好了,东西都准备好了。
写一个server和client吧。
  1. #include <thrift/concurrency/ThreadManager.h>
  2. #include <thrift/concurrency/PosixThreadFactory.h>
  3. #include <thrift/protocol/TBinaryProtocol.h>
  4. #include <thrift/server/TSimpleServer.h>
  5. #include <thrift/server/TThreadPoolServer.h>
  6. #include <thrift/server/TThreadedServer.h>
  7. #include <thrift/transport/TServerSocket.h>
  8. #include <thrift/transport/TTransportUtils.h>

  9. #include <iostream>
  10. #include <stdexcept>
  11. #include <sstream>

  12. #include "./idl/WebInfo.h"

  13. using namespace std;
  14. using namespace apache::thrift;
  15. using namespace apache::thrift::protocol;
  16. using namespace apache::thrift::transport;
  17. using namespace apache::thrift::server;

  18. using namespace mytest;

  19. using namespace boost;

  20. class CWebInfo : public WebInfoIf
  21. {
  22. public:
  23.                 CWebInfo() {} ;
  24.                 
  25.                 void GetWebInfo(vecTags& _return)
  26.                 {
  27.                         printf("[GetWebInfo]Begin(%d).\n", (int)_return.size());
  28.                         for(int i = 0; i < (int)_return.size(); i++)
  29.                         {
  30.                                 printf("[Data]ntag=%d,strData=%s.\n", _return[i].ntag, _return[i].strData.c_str());
  31.                         }
  32.                         printf("[GetWebInfo]End.\n");
  33.                 }
  34. };

  35. int main(int argc, char **argv) 
  36. {
  37.   shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
  38.   shared_ptr<CWebInfo> handler(new CWebInfo());
  39.   shared_ptr<TProcessor> processor(new WebInfoProcessor(handler));
  40.   shared_ptr<TServerTransport> serverTransport(new TServerSocket(10090));
  41.   shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());

  42.   TSimpleServer server(processor,
  43.                        serverTransport,
  44.                        transportFactory,
  45.                        protocolFactory);

  46.   printf("Starting the server...\n");
  47.   server.serve();
  48.   printf("done.\n");
  49.   return 0;
  50. }
复制代码

然后再写一个客户端
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/time.h>

  4. #include <thrift/protocol/TBinaryProtocol.h>
  5. #include <thrift/transport/TSocket.h>
  6. #include <thrift/transport/TTransportUtils.h>

  7. #include "./idl/WebInfo.h"

  8. using namespace std;
  9. using namespace apache::thrift;
  10. using namespace apache::thrift::protocol;
  11. using namespace apache::thrift::transport;

  12. using namespace mytest;

  13. using namespace boost;

  14. int main(int argc, char** argv) {
  15.   shared_ptr<TTransport> socket(new TSocket("localhost", 10090));
  16.   shared_ptr<TTransport> transport(new TBufferedTransport(socket));
  17.   shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
  18.   WebInfoClient client(protocol);
  19.   
  20.   Tag objTag1;
  21.   Tag objTag2;
  22.   vecTags objvecTags;
  23.   
  24.   objTag1.ntag = 1;
  25.   objTag1.strData = "freeeyes";
  26.   
  27.   objTag2.ntag = 2;
  28.   objTag2.strData = "shiqiang";
  29.   
  30.   objvecTags.push_back(objTag1);
  31.   objvecTags.push_back(objTag2);
  32.   
  33.   //打开连接
  34.   transport->open();
  35.   
  36.   printf("[main]Client is Begin(%d).\n", objvecTags.size());
  37.   //连接远程方法
  38.   client.GetWebInfo(objvecTags);
  39.   printf("[main]Client is End.\n");
  40.   
  41.   //关闭连接
  42.   transport->close();
  43. }
复制代码

为了方便,再写两个make文件。
先写一个make.define,用于公共调用。
  1. # *****************************
  2. # 预定义
  3. # *****************************
  4. CC = g++
  5. AR = ar
  6. CFLAGS = -g -O2 -D__LINUX__
  7. #设置THRIFT_INCLUDE头文件路径和库文件位置
  8. THRIFT_INCLUDE = /home/m2mjk/src/thrift-0.9.1/lib/cpp/src
  9. THRIFT_LIB=/home/m2mjk/src/thrift-0.9.1/lib/cpp/.libs

  10. INCLUDES = -I./ -I../ -I/usr/include -I${ACE_ROOT} -I../include -I${THRIFT_INCLUDE}
  11. LIBS = -L/usr/lib64 -L/usr/lib -L/usr/local/lib64 -L./ -L${THRIFT_LIB}  -L../ -ldl -lthrift
  12. # *****************************
  13. # 变换规则
  14. # *****************************
  15. # Here are some rules for converting .cpp -> .o
  16. .SUFFIXES: .cpp .o
  17. .cpp.o:
  18.         @$(CC) -fPIC $(CFLAGS) ${INCLUDES} -c -g $*.cpp 
  19.         @echo '----- '$*.cpp' is compiled ok!'

  20. # Here are some rules for converting .c -> .o
  21. .SUFFIXES: .c .o
  22. .c.o:
  23.         @$(CC) $(CFLAGS) -c $*.c 
  24.         @echo '----- '$*.c' is compiled ok!'
复制代码

再写两个make 分别是makefile_server和makefile_client
  1. include makefile.define

  2. # 默认超作
  3. default:all

  4. # 主应用文件列表
  5. PATS = ./idl/mytest_constants.o \
  6.        ./idl/mytest_types.o \
  7.        ./idl/WebInfo.o \
  8.        ./myServer.o

  9.        
  10. OBJS = mytest_constants.o \
  11.        mytest_types.o \
  12.        WebInfo.o \
  13.        myServer.o
  14.        
  15.                         
  16. # 主应用程序
  17. APP_NAME = MytestServer

  18. all:$(APP_NAME) makefile_server

  19. $(APP_NAME):$(PATS)
  20.         $(CC) -rdynamic -o $(APP_NAME) $(OBJS) $(LIBS)

  21. # 清理
  22. clean:
  23.         rm -rf *.o $(APP_NAME)
  24.         
  25. cl:
  26.         rm -rf *.o 
复制代码
  1. include makefile.define

  2. # 默认超作
  3. default:all

  4. # 主应用文件列表
  5. PATS = ./idl/mytest_constants.o \
  6.        ./idl/mytest_types.o \
  7.        ./idl/WebInfo.o \
  8.        ./myClient.o

  9.        
  10. OBJS = mytest_constants.o \
  11.        mytest_types.o \
  12.        WebInfo.o \
  13.        myClient.o
  14.        
  15.                         
  16. # 主应用程序
  17. APP_NAME = MytestClient

  18. all:$(APP_NAME) makefile_client

  19. $(APP_NAME):$(PATS) 
  20.         $(CC) -rdynamic -o $(APP_NAME) $(OBJS) $(LIBS)

  21. # 清理
  22. clean:
  23.         rm -rf *.o $(APP_NAME)
  24.         
  25. cl:
  26.         rm -rf *.o 


复制代码

编译的时候, make -f makefile_server 和make -f makefile_client。
好了,编译一切顺利,运行。
输出结果:
(客户端输出)
-bash-4.1$ ./MytestClient
[main]Client is Begin(2).
[main]Client is End.

(服务端输出)
-bash-4.1$ ./MytestServer
Starting the server...
[GetWebInfo]Begin(2).
[Data]ntag=1,strData=freeeyes.
[Data]ntag=2,strData=shiqiang.
[GetWebInfo]End.


OK,全部达成。

此代码在Linux下测试通过。代码包如下。

http://www.acejoy.com/ace/thread-5802-1-1.html

0 0
原创粉丝点击