zoukankan      html  css  js  c++  java
  • 【通信框架】Apache的开源通信框架thrift概述

    在阅读的过程中有不论什么问题。欢迎一起交流

    邮箱:1494713801@qq.com   

    QQ:1494713801

     

    一、作用

         Thrift("Scalable Cross-Language Services Implementation”)最早是Facebook的项目,后来Facebook提供给Apache作为开源项目。

         普通情况下的跨机器的通信框架都是跨软件平台的(Linux,windows), 而Thrift最特别之处在于它是跨语言的:比如,你能够用差点儿全部流行语言(C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript等等)来实现通讯过程,这样做的优点就是你不用为编程语言发愁。假设server端与client都须要编写,选择你最拿手或项目规定的语言,就能够生成一个通讯框架;假设编写一个server端程序,定义好通讯规则(在Thrift中是.thrift文件)后,你所採用的server端实现语言不会影响到client,以后使用的人能够採用其它编程语言来实现client。

    二、Thrift组成

         Thrift事实上应分成三个部分,一个叫做Thrift代码生成器。一个叫做Thrift应用框架(库),最后一个是它生成的代码。Thrift应用的基本流程例如以下图所看到的。

    从上图,要生成一个Thrift应用,需用下面文件:

    1. 一个.thrift文件:该文件是通信接口的定义。最基本的是信息流的格式。
    2. 编程语言:这个无需解释。
    3. Thrift代码生成器(Thrift compiler,翻译成代码生成器似乎更合适):这个东西是安装thrift过程中生成的,它能够产生若干符合你约定通信格式的代码。

    4. Thrift应用框架库:这个东西也是在安装过程中产生的。

    5. 其它第三方支撑库:对C++来说,最主要是boost.thread、libevent,log4cxx等,依照执行的模式。生成的代码中可能需用调用这些库。

    三、Thrift的安装及使用

    1、安装

    安装版本号为:Thrift v0.9.1

    系统版本号:Ubuntu 14.04 64位

    基本安装环境:

    • g++ 4.2
    • boost 1.53.0
    • libssl-dev

    Thrift的编译器即代码生成器是由C++编写的,所以须要g++来进行编译安装,且Thrift源代码中用到了boost库中相关实现。比如shared_ptr,所以要事先安装boost库。

    Thrift通信过程中使用ssl对数据进行安全包括,假设为安装该库,会在configure时出现 configure: error: "Error: libcrypto required."

    Thrift提供了。TThreadSever, TThreadPoolServer, TNonblockingServer四种server框架。TSimpleServer以单一主线程堵塞的方式进行事件处理。TThreadPoolServer以多线程堵塞的方式提供服务。TNonblockingServer以多线程非堵塞方式工作。 TNonblockingServer服务模型的使用须要事先安装libevent。libevent-dev库,libevent是异步事件处理的程序库,其包括我们经常使用的poll,select,epoll等异步处理函数。

    安装步骤:

    $./configure
    $make
    #sudo make install

    configure的结果最后一部分例如以下,当中 Build TNonblockingServer .. : yes的结果对于使用异步的server模型是必须的。

    anonymalias@anonymalias-Rev-1-0:~/download/thrift-0.9.1$./configure
    ......
    thrift 0.9.1
    
    Building C++ Library ......... : yes
    Building C (GLib) Library .... : no
    Building Java Library ........ : no
    Building C# Library .......... : no
    Building Python Library ...... : yes
    Building Ruby Library ........ : no
    Building Haskell Library ..... : no
    Building Perl Library ........ : no
    Building PHP Library ......... : no
    Building Erlang Library ...... : no
    Building Go Library .......... : no
    Building D Library ........... : no
    
    C++ Library:
      Build TZlibTransport ...... : yes
      Build TNonblockingServer .. : yes
      Build TQTcpServer (Qt) .... : no
    
    Python Library:
      Using Python .............. : /usr/bin/python
    
    If something is missing that you think should be present,
    please skim the output of configure to find the missing
    component.  Details are present in config.log.

    在本人电脑上make的时候会出现以下的bug,
    ar: .libs/ThriftTest_constants.o: No such file or directory

    不知道Makefile怎样生成的,导致上面这个编译文件路径有问题,解决方法有以下两种:

    method1:
    解决办法时直接从Github(git://git.apache.org/thrift.git)上git clone 源代码。先执行./bootstrap.sh。在依照configure安装。
    
    method2:
    能够将已经编译的test/cpp/*.o拷贝到test/cpp/.libs后,继续编译就能够了
    cp test/cpp/*.o test/cpp/.libs/

    2、使用

    1. thrift生成代码

    创建Thrift文件:G: est hriftdemoHello.thrift ,内容例如以下:

    1 namespace java com.micmiu.thrift.demo
    2  
    3 service  HelloWorldService {
    4   string sayHello(1:string username)
    5 }

    文件夹结构例如以下:

    G:	est	hrift>tree /F
    卷 other 的目录 PATH 列表
    卷序列号为 D238-BE47
    G:.
        demoHello.thrift
        demouser.thrift
        thrift-0.8.0.exe
    
    没有子目录

    thrift-0.8.0.exe 是官网提供的windows下编译工具。运用这个工具生成相关代码:

    1 thrift-0.8.0.exe -r -gen java ./demoHello.thrift

    生成后的文件夹结构例如以下:

    G:	est	hrift>tree /F
    卷 other 的目录 PATH 列表
    卷序列号为 D238-BE47
    G:.
    │  demoHello.thrift
    │  demouser.thrift
    │  thrift-0.8.0.exe
    │
    └─gen-java
        └─com
            └─micmiu
                └─thrift
                    └─demo
                            HelloWorldService.java

    2. 实现接口Iface

    java代码:HelloWorldImpl.java

    1 package com.micmiu.thrift.demo;
    2  
    3 import org.apache.thrift.TException;
    4  
    5 /**
    7  *
    8  * @author Michael
    9  *
    10  */
    11 public classHelloWorldImplimplementsHelloWorldService.Iface {
    12  
    13     publicHelloWorldImpl() {
    14     }
    15  
    16     @Override
    17     publicString sayHello(String username)throwsTException {
    18         return"Hi,"+ username +" welcome to my blog www.micmiu.com";
    19     }
    20  
    21 }

    3.TSimpleServer服务端

    简单的单线程服务模型,一般用于測试。

    编写服务端server代码:HelloServerDemo.java

    1 package com.micmiu.thrift.demo;
    2  
    3 import org.apache.thrift.TProcessor;
    4 import org.apache.thrift.protocol.TBinaryProtocol;
    5 import org.apache.thrift.protocol.TCompactProtocol;
    6 import org.apache.thrift.protocol.TJSONProtocol;
    7 import org.apache.thrift.protocol.TSimpleJSONProtocol;
    8 import org.apache.thrift.server.TServer;
    9 import org.apache.thrift.server.TSimpleServer;
    10 import org.apache.thrift.transport.TServerSocket;
    11  
    12 /**
    14  *
    15  * @author Michael
    16  *
    17  */
    18 public classHelloServerDemo {
    19     publicstaticfinalint SERVER_PORT = 8090;
    20  
    21     publicvoidstartServer() {
    22         try{
    23             System.out.println("HelloWorld TSimpleServer start ....");
    24  
    25             TProcessor tprocessor =newHelloWorldService.Processor<HelloWorldService.Iface>(
    26                     newHelloWorldImpl());
    27             // HelloWorldService.Processor<HelloWorldService.Iface> tprocessor =
    28             // new HelloWorldService.Processor<HelloWorldService.Iface>(
    29             // new HelloWorldImpl());
    30  
    31             // 简单的单线程服务模型。一般用于測试
    32             TServerSocket serverTransport =newTServerSocket(SERVER_PORT);
    33             TServer.Args tArgs =newTServer.Args(serverTransport);
    34             tArgs.processor(tprocessor);
    35             tArgs.protocolFactory(newTBinaryProtocol.Factory());
    36             // tArgs.protocolFactory(new TCompactProtocol.Factory());
    37             // tArgs.protocolFactory(new TJSONProtocol.Factory());
    38             TServer server =newTSimpleServer(tArgs);
    39             server.serve();
    40  
    41         } catch (Exception e) {
    42             System.out.println("Server start error!!!");
    43             e.printStackTrace();
    44         }
    45     }
    46  
    47     /**
    48      * @param args
    49      */
    50     publicstaticvoidmain(String[] args) {
    51         HelloServerDemo server =newHelloServerDemo();
    52         server.startServer();
    53     }
    54  
    55 }

    编写clientClient代码:HelloClientDemo.java

    1 package com.micmiu.thrift.demo;
    2  
    3 import org.apache.thrift.TException;
    4 import org.apache.thrift.protocol.TBinaryProtocol;
    5 import org.apache.thrift.protocol.TCompactProtocol;
    6 import org.apache.thrift.protocol.TJSONProtocol;
    7 import org.apache.thrift.protocol.TProtocol;
    8 import org.apache.thrift.transport.TSocket;
    9 import org.apache.thrift.transport.TTransport;
    10 import org.apache.thrift.transport.TTransportException;
    11  
    12 /**
    14  *
    15  * @author Michael
    16  *
    17  */
    18 public classHelloClientDemo {
    19  
    20     publicstaticfinalString SERVER_IP = "localhost";
    21     publicstaticfinalint SERVER_PORT = 8090;
    22     publicstaticfinalint TIMEOUT = 30000;
    23  
    24     /**
    25      *
    26      * @param userName
    27      */
    28     publicvoidstartClient(String userName) {
    29         TTransport transport =null;
    30         try{
    31             transport =newTSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
    32             // 协议要和服务端一致
    33             TProtocol protocol =newTBinaryProtocol(transport);
    34             // TProtocol protocol = new TCompactProtocol(transport);
    35             // TProtocol protocol = new TJSONProtocol(transport);
    36             HelloWorldService.Client client =newHelloWorldService.Client(
    37                     protocol);
    38             transport.open();
    39             String result = client.sayHello(userName);
    40             System.out.println("Thrify client result =: "+ result);
    41         } catch (TTransportException e) {
    42             e.printStackTrace();
    43         } catch (TException e) {
    44             e.printStackTrace();
    45         } finally {
    46             if(null!= transport) {
    47                 transport.close();
    48             }
    49         }
    50     }
    51  
    52     /**
    53      * @param args
    54      */
    55     publicstaticvoidmain(String[] args) {
    56         HelloClientDemo client =newHelloClientDemo();
    57         client.startClient("Michael");
    58  
    59     }
    60  
    61 }

    先执行服务端程序。日志例如以下:

    HelloWorld TSimpleServer start ....

    再执行client调用程序。日志例如以下:

    Thrify client result =: Hi,Michael welcome to my blog www.micmiu.com

    測试成功,和预期的返回信息一致。

     

    參考: http://blog.csdn.net/guxch/article/details/12157151

                  http://blog.csdn.net/anonymalias/article/details/26154405

                  http://www.micmiu.com/soa/rpc/thrift-sample/

  • 相关阅读:
    【数据结构】树的DFS序&欧拉序
    Codeforces 1335E2
    Codeforces 1335E1
    Codeforces 1338A/1339C
    【数据结构】ST算法
    Codeforces 1334C
    Codeforces 1333D
    Codeforces 1333C
    python中的socket编程实例与查看端口占用
    java中打印数组
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5106224.html
Copyright © 2011-2022 走看看