• 【thrift】thrift入门初探--thrift安装及java入门实例


     转载:https://www.cnblogs.com/fingerboy/p/6424248.html

    公司的一些平台服务框架底层封装了thrift提供服务,最近项目不是很紧,于是研究了一下,刚刚入门,理解得不深,写这篇博文来整理一下思路.

    什么是thrift?

      简单来说,是Facebook公布的一款开源跨语言的RPC框架.

      那么问题来了.

      什么是RPC框架?

        RPC全称为Remote Procedure Call,意为远程过程调用.

        假设有两台服务器A,B.A服务器上部署着一个应用a,B服务器上部署着一个应用b,现在a希望能够调用b应用的某个函数(方法),但是二者不在同一个进程内,不能直接调用,就需要通过网络传输,在AB服务器之间建一条网络传输通道,a把参数传过去,b接收到参数调用自己的方法,得到结果,再通过网络传回给a,简单讲就是A通过网络来调用B的过程.这个过程要涉及的东西很多,比如多线程,Socket,序列化反序列化,网络I/O,很复杂,于是牛掰的程序员把这些封装起来做成一套框架,供大家使用,就是RPC框架.       

      thrift的跨语言特型

        thrift通过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,这些内容写在以.thrift结尾的文件中,然后通过特殊的编译器来生成不同语言的代码,以满足不同需要的开发者,比如java开发者,就可以生成java代码,c++开发者可以生成c++代码,生成的代码中不但包含目标语言的接口定义,方法,数据类型,还包含有RPC协议层和传输层的实现代码.

      thrift的协议栈结构

    thrift是一种c/s的架构体系.在最上层是用户自行实现的业务逻辑代码.第二层是由thrift编译器自动生成的代码,主要用于结构化数据的解析,发送和接收。TServer主要任务是高效的接受客户端请求,并将请求转发给Processor处理。Processor负责对客户端的请求做出响应,包括RPC请求转发,调用参数解析和用户逻辑调用,返回值写回等处理。从TProtocol以下部分是thirft的传输协议和底层I/O通信。TProtocol是用于数据类型解析的,将结构化数据转化为字节流给TTransport进行传输。TTransport是与底层数据传输密切相关的传输层,负责以字节流方式接收和发送消息体,不关注是什么数据类型。底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。

    MAC OS下thrift的下载与安装

      我的电脑是mac,第一次安装也碰到了一些问题,所以有必要记录一下.

      首先,在官网下载安装包http://thrift.apache.org/download 目前官网是0.10.0版本.下载完之后解压到想要安装的目录.

      进入根目录:

    step1:cd thrift-0.10.0
    step2:./configure
    step3:make
    step4:make install

       如果执行make install的时候碰到权限问题,mac请按如下步骤解决

    google了后,发现果然如我的所料….  新系统有个叫sip的机制。 你暂时不能直接在终端进行 csrutil disable 会出现错误提示,引导你去mac osx的恢复模式进行操作。 
    
    由于El Capitan引入了SIP机制(System Integrity Protection),默认下系统启用SIP系统完整性保护机制,无论是对于硬盘还是运行时的进程限制对系统目录的写操作。 这也是我们安装ipython失败的原因….
    
    
    现在的解决办法是取消SIP机制,具体做法是:
    
    重启电脑,按住Command+R(直到出现苹果标志)进入Recovery Mode(恢复模式)
    左上角菜单里找到实用工具 -> 终端
    输入csrutil disable回车
    重启Mac即可
    如果想重新启动SIP机制重复上述步骤改用csrutil enable即可
    
    我们现在再看看sip的状态, 这样再安装ipython、gevent再也不会提示无法写入的权限提示了/
    

      

     

     安装的时候,第二步出现了问题,提示:

    Bison version 2.5 or higher must be installed on the system!

      原因是Bison版本过低,mac默认安装的版本是2.3,因此需要安装最新版的Bison,命令行输入:brew install bison安装最新版bison,如果你的命令行反馈:Command not found,很可能是因为你没装homebrew,命令行输入:

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

      等待安装完homebrew就可以安装bison了,最新版本3.0.4安装完以后,执行第二步,发现依然提示上面那个警告,原因是因为它读取的仍然是默认的bison,于是找到系统安装的bison目录,我的mac是

    /Library/Developer/CommandLineTools/usr/bin/bison,解决方法也比较简单,可以先将这个目录下的bison名字改一下,再将最新版的bison复制进来,于是,在bin目录下,执行命令:

    sudo mv bison bison111

    sudo cp /usr/local/opt/bison/bin/bison  /Library/Developer/CommandLineTools/usr/bin/

      现在,再按照上面的步骤进行下去,就可以正确安装thrift了

    进入thrift大门的第一个java小实例

       1,创建一个服务Hello,创建文件Hello.thrift,代码如下:

    namespace java service.demo
    service Hello{
        string helloString(1:string para)
    }

      这里定义了一个名为helloString的方法,入参和返回值都是一个string类型的参数.

       2,终端进入Hello.thrift所在目录,执行命令:

    thrift -r -gen java Hello.thrift

      发现在当前目录下多了一个gen-java的目录,里面的有一个Hello.java的文件.这个java文件包含Hello服务的接口定义Hello.Iface,以及服务调用的底层通信细节,包括客户端的调用逻辑Hello.Client以及服务端的处理逻辑Hello.Processor,

       3,创建一个Maven管理的Java项目,pom.xml中添加相关的依赖,并将Hello.java文件复制到项目中:

    复制代码
        <dependency>
          <groupId>org.apache.thrift</groupId>
          <artifactId>libthrift</artifactId>
          <version>0.10.0</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.7.5</version>
        </dependency>
    复制代码

           4,创建HelloServiceImpl实现Hello.Iface接口:

    复制代码
    package service.demo;
    import org.apache.thrift.TException;
    /**
     * @author yogo.wang
     * @date 2017/02/21-下午2:13.
     */
    public class HelloServiceImpl implements Hello.Iface {
        public String helloString(String para) throws TException {
            return "result:"+para;
        }
    }
    复制代码

      5,创建服务端实现代码HelloServiceServer,把HelloServiceImpl作为一个具体的处理器传递给Thrift服务器:

    复制代码
    package service.demo;
    import org.apache.thrift.TProcessor;
    import org.apache.thrift.protocol.TBinaryProtocol;
    import org.apache.thrift.server.TServer;
    import org.apache.thrift.server.TSimpleServer;
    import org.apache.thrift.transport.TServerSocket;
    import org.apache.thrift.transport.TTransportException;
    
    /**
     * @author yogo.wang
     * @date 2017/02/21-下午2:15.
     */
    public class HelloServiceServer {
        /**
         * 启动thrift服务器
         * @param args
         */
        public static void main(String[] args) {
            try {
                System.out.println("服务端开启....");
                TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl());
                // 简单的单线程服务模型
                TServerSocket serverTransport = new TServerSocket(9898);
                TServer.Args tArgs = new TServer.Args(serverTransport);
                tArgs.processor(tprocessor);
                tArgs.protocolFactory(new TBinaryProtocol.Factory());
                TServer server = new TSimpleServer(tArgs);
                server.serve();
                }catch (TTransportException e) {
                e.printStackTrace();
            }
        }
    }
    复制代码

      6,创建客户端实现代码HelloServiceClient,调用Hello.client访问服务端的逻辑实现:

    复制代码
    package service.demo;
    
    import org.apache.thrift.TException;
    import org.apache.thrift.protocol.TBinaryProtocol;
    import org.apache.thrift.protocol.TProtocol;
    import org.apache.thrift.transport.TSocket;
    import org.apache.thrift.transport.TTransport;
    import org.apache.thrift.transport.TTransportException;
    
    /**
     * @author yogo.wang
     * @date 2017/02/21-下午2:35.
     */
    public class HelloServiceClient {
    
        public static void main(String[] args) {
            System.out.println("客户端启动....");
            TTransport transport = null;
            try {
                transport = new TSocket("localhost", 9898, 30000);
                // 协议要和服务端一致
                TProtocol protocol = new TBinaryProtocol(transport);
                Hello.Client client = new Hello.Client(protocol);
                transport.open();
                String result = client.helloString("哈哈");
                System.out.println(result);
            } catch (TTransportException e) {
                e.printStackTrace();
            } catch (TException e) {
                e.printStackTrace();
            } finally {
                if (null != transport) {
                    transport.close();
                }
            }
        }
    }
    复制代码

      全部工作完成后,下面来测试一下,先执行服务端main方法,在执行客户端main方法,会在客户端控制台打印出:result:哈哈.

  • 相关阅读:
    028 Android 旋转动画+病毒查杀效果+自定义样式的ProgressBar
    027 Android 可扩展的listview:ExpandableListView的使用案例
    026 Android 带不同类型条目的listview(纯文本类型的条目,图片+文字类型的条目)+读取内存空间、手机进程信息+常驻悬浮框
    025 Android 带进度条的对话框(ProgressDialog)
    024 Android 自定义样式对话框(AlertDialog)
    023 Android 自定义Toast控件
    Cordova-安装Cordova过程详细解
    Symfony3 查询搜索功能DQL语句like查询
    迭代式开发使用方法总结
    require.js vs browserify
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/8504977.html
Copyright © 2020-2023  润新知