• Thrift初用小结


    thrift --gen  csharp  search.thrift

    thrift --gen java search.thrift

    Thrift是facebook的一个技术核心框架,07年四月开放源码,08年5月进入apache孵化器。

        简言之,开发者可以通过写一个.thrift文件,定义相应的数据结构和服务接口,该thrift文件会由Thrift相应的解释器解释生成指定的类型(C++,java等等)代码,然后用户在客户端和服务器端,分别在生成的代码里编写相应的服务接口函数,并做相应配置选择,就可以实现跨平台的rpc调用。

     

        这里给出一个使用的简单例子,之中牵扯到了一些编译方面的细节问题。

        定义数据结构的.thrift文件book.thrift:

    复制代码
    //book.thrift
    namespace cpp example
    struct Book_Info {
      1: i32 book_id,
      2: string book_name,
      3: string book_author,
      4: double book_price,
      5: string book_publisher,
    }
    复制代码

     

        定义rpc服务接口的rpc.thrift文件,定义了service类:

    复制代码
    //rpc.thrift
    namespace cpp example
    include "book.thrift"
    service BookServlet {
      bool Sender(1: list<book.Book_Info> books);
      oneway void Sender2(1: list<book.Book_Info> books);
    }
    复制代码

         调用thrift的编译器,将上面的两个thrift文件转化为对应语言的代码,这里我选了C++:

    thrift --gen cpp book.thrift
    thrift --gen cpp rpc.thrift

        然后会在当前目录下生成一个./gen-cpp文件夹,该文件夹里就是生成的相应的cpp文件,所生成的文件有以下几类[1]:

        对应的,对于本例,所生成的文件列表如下:

       其中的makefile不是thrift生成的文件,是我编译用的,主要关注其他文件。这个gen-cpp的文件客户端和服务器端都需要。

       服务器端:

         修改BookServlet_server.skeleton.cpp,作为服务器端服务响应:

    复制代码
    // This autogenerated skeleton file illustrates how to build a server.
    // You should copy it to another filename to avoid overwriting it.
    
    #include "BookServlet.h"
    #include <thrift/protocol/TBinaryProtocol.h>
    #include <thrift/server/TSimpleServer.h>
    #include <thrift/transport/TServerSocket.h>
    #include <thrift/transport/TBufferTransports.h>
    
    using namespace ::apache::thrift;
    using namespace ::apache::thrift::protocol;
    using namespace ::apache::thrift::transport;
    using namespace ::apache::thrift::server;
    
    using boost::shared_ptr;
    
    using namespace  ::example;
    
    class BookServletHandler : virtual public BookServletIf {
     public:
      BookServletHandler() {
        // Your initialization goes here
      }
    
      bool Sender(const std::vector< ::example::Book_Info> & books) {
        // Your implementation goes here
        std::vector< ::example::Book_Info>::const_iterator iter;
        for(iter=books.begin();iter!=books.end();iter++) {
          printf("books size: %d
    ",books.size());
          printf("send 1: %d, %s, %s
    ",(*iter).book_id,(*iter).book_name.c_str(),(*iter).book_author.c_str());
        }    
        return true;
      }
    
      void Sender2(const std::vector< ::example::Book_Info> & books) {
        // Your implementation goes here
        std::vector< ::example::Book_Info>::const_iterator iter;
        for(iter=books.begin();iter!=books.end();iter++) {
          printf("books size: %d
    ",books.size());
          printf("send 2: %d, %s, %s
    ",(*iter).book_id,(*iter).book_name.c_str(),(*iter).book_author.c_str());
        }
      }
    
    };
    
    int main(int argc, char **argv) {
      int port = 9090;
      shared_ptr<BookServletHandler> handler(new BookServletHandler());
      shared_ptr<TProcessor> processor(new BookServletProcessor(handler));
      shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
      shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
      shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
    
      TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
      server.serve();
      return 0;
    }
    复制代码

        监听端口9090,所做的事情其实就是将client传递过来的books参数的内容打印出来,来验证是否实现了数据传递。然后在服务器端用g++编译,thrift编译有点儿恶,一方面需要将各种库(boost,thrift等)加进来,另一方面有时候还会有一些uint_32没有定义什么的错误,还要加一些编译参数,如下给出一个可以编译通过的makefile模板,大家可以根据自己机器的程序路径和文件名做相应修改。thrift生成代码编译的makefile模板:

    复制代码
    BOOST_DIR = /usr/include/boost
    THRIFT_DIR = /usr/local/include/thrift/
    LIB_DIR = /usr/local/lib
    GEN_SRC = ./book_types.cpp ./rpc_types.cpp ./BookServlet.cpp ./book_constants.cpp ./rpc_constants.cpp
    default: server
    server: BookServlet_server.skeleton.cpp
        g++ -DHAVE_NETINET_IN_H -DHAVE_INTTYPES_H -o CppServer -I${THRIFT_DIR} -I${BOOST_DIR}  -I../gen-cpp -L${LIB_DIR} -lthrift BookServlet_server.skeleton.cpp ${GEN_SRC}
    clean:
        $(RM) -r CppServer
    复制代码

        编译通过后就在服务器端运行响应的程序./CppServer

        客户端

        客户端代码,thrift_cli.cpp,同样放在./gen-cpp文件夹下:

    复制代码
    #include "BookServlet.h"
    #include "book_types.h"
    #include <protocol/TBinaryProtocol.h>
    
    #include <transport/TSocket.h>
    
    #include <transport/TBufferTransports.h>
    
    
    #include <vector>
    
    using namespace std;
    
    
    using namespace apache::thrift;
    
    using namespace apache::thrift::protocol;
    
    using namespace apache::thrift::transport;
    
    using boost::shared_ptr;
    
    using namespace example;
    
    
     
    //other headers, using namespace
     
    int main(int argc, char** argv) {
     
      shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
     
      shared_ptr<TTransport> transport(new TBufferedTransport(socket));
     
      shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
     
      example::BookServletClient client(protocol);
     
    try {
     
      transport->open();
     
      vector<example::Book_Info> books;
    
      Book_Info ibook;
      ibook.book_id = 1324;
      ibook.book_name = "thrift";
      ibook.book_price = 22;
      ibook.book_publisher = "letv";
      ibook.book_author = "luis";
      books.push_back(ibook);
       
      ibook.book_id = 1024;
      books.push_back(ibook);
      
      client.Sender(books);
      client.Sender2(books);
     
      transport->close();
     
    } catch (TException &tx) {
     
      printf("iERRORs %s
    ", tx.what());
     
    }
     
    }
    复制代码

       由于我的服务器和客户端实在同一台机器上测的,所以访问localhost,这个客户端程序其实就是向books里加了两个数据,然后client.Sender()和client.Sender2()调用服务器端对应的函数。同样使用上面的makefile文件(修改一下文件名称)进行编译,然后运行./thrift_cli。

       运行结果

        服务器端接到请求,将客户端传递过来的数据对象books打印了出来,证明rpc成功:

        本文只是给了一个thrift简单能够run起来的应用示例,部分参考了[1]和[2],如果要深入地使用thrift,了解thrift的内部架构和实现就是必须的了。

  • 相关阅读:
    推送技术 --SignalR
    软件解耦
    xrBarCode 条形码的密度设置
    Javascript 中方法的重写
    数据库锁
    oracle instr,substr 截取字符串
    循环读取写入表
    Oracle For 循环,字符串拼接,查找
    iis,webservice 启用 acrobat.exe 打印
    iis,webservice 打印
  • 原文地址:https://www.cnblogs.com/zhwl/p/3492778.html
Copyright © 2020-2023  润新知