zoukankan      html  css  js  c++  java
  • Thrift教程初级篇——thrift安装环境变量配置第一个实例

    前言:                    

    因为项目需要跨语言,c++客户端,web服务端,远程调用等需求,所以用到了RPC框架Thrift,刚开始有点虚,第一次接触RPC框架,后来没想到Thrift开发方便上手快,而且性能和稳定性也不错,项目也顺利完成。所以给各位小白们,“科普”一下如何使用Thrift完成自己的远程调用。

    1.什么是RPC:                     

    平时开发的服务,大多都是本地调用,如果说需要依赖他人服务了,而且他人的服务在远端,那怎么调用呢?

    RPC能够游刃有余的解决这样的问题。首先来研究一下什么RPC

    RPC(remote produce call),远程过程调用协议。它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。

    看下面这张图:

    一次远程的调用经历了一下10个步骤:

    1.调用客户端以本地方式调用远程服务

    2.client stub将请求(方法和参数)组装成网络消息

    3.client stub找得到服务器地址,将消息传送到远程主机

    4.server stub得到传送过来的请求,进行解码

    5.server stub 调用本地服务,处理请求

    6.本地服务处理请求,并将处理结果返回给server stub

    7.server stub将请求处理结果组装成网络消息

    8.server stub找到客户端地址,将请求处理结果传送给客户端

    9.client stub 接收到请求处理结果,进行解码

    10.客户端最终接收到请求处理结果

    RPC框架的目的就是将2-9步骤封装起来,对使用者透明,客户端只需要执行第一步调用接口,然后就能够得到结果。这样是不是很方便,而且省去了很多麻烦。

    通过对RPC的初步了解,那接下来就开始不如Thrift的大门吧

    2.What is Thrift?                                                

    ThriftFacebook公司开发的一款开源的RPC框架,对于一般的RPC框架来说,通过IDL语言定义接口(Interface description language),Thrift也采用了这样的做法,并通过一个编译器生成不同语言的代码(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, SmalltalkOCaml,并由生成的代码负责RPC协议层和传输层的实现。

    Thrift协议栈:

    第一部分(Your Code):

    简单总结:开发者的业务逻辑代码

    第二部分(ServiceClient

    Thrift自动生成的代码,包含ProcessorTserverServiceClient

    TServer负责接收Client的请求,并将请求转发到Processor进行处理。TServer主要任务就是高效的接受Client的请求,特别是在高并发请求的情况下快速完成请求。

    Processor(或者TProcessor)负责对Client的请求做出相应,包括RPC请求转发,调用参数解析和用户逻辑调用,返回值写回等处理步骤。Processor是服务器端从Thrift框架转入用户逻辑的关键流程。Processor同时也负责向Message结构中写入数据或者读出数据。

    ServiceClient就是客户端,包含可以调用的请求方法和发送客户端请求

    第三部分:

    TProtocol主要负责结构化数据组装成Message,或者从Message结构中读出结构化数据。TProtocol将一个有类型的数据转化为字节流以交给TTransport进行传输,或者从TTransport中读取一定长度的字节数据转化为特定类型的数据。如int32会被TBinaryProtocol Encode为一个四字节的字节数据,或者TBinaryProtocolTTransport中取出四个字节的数据Decodeint32

    第四部门:

    TTransport负责以字节流方式发送和接收Message,是底层IO模块在Thrift框架中的实现,每一个底层IO模块都会有一个对应TTransport来负责Thrift的字节流(Byte Stream)数据在该IO模块上的传输。例如TSocket对应Socket传输,TFileTransport对应文件传输。

    第五部分:

    底层IO模块,负责实际的数据传输,包括Socket,文件,或者压缩数据流等。

    通过这个协议栈,可以得出结论,使用Thrift只需要做三件事:

    1.通过IDL定义数据结构和服务

    2.利用代码生成工具生成代码

    3.编写你的业务逻辑

    接下来我们就按照这个三步走开发一个简单的HelloWorld级别的客户端与服务端

    3.How to use Thrift?                                                

    首先要做的就是下载并配置Thrift,附上链接:http://thrift.apache.org/download

    现在版本都是0.10.0,

    下载好之后将名字改成“thrift.exe”

    我的电脑操作系统是Windows,属于在Windows情况下配置。

    thrift.exe放在Thrift文件夹下:

    配置环境变量:

     

    配置完成之后,打开dos窗口,输入”thrifx -version”:

    接下来执行三步走策略:

     

    第一步:通过IDL定义数据结构和服务                

    从最简单的HelloWorld开始,编写HelloWorld.thrift,内容如下:

    namespace java service.server
    service HelloWorld{
        string sendString(1:string para)
    }

    随便放在一个文件夹下,我这里放在E:softwareThrift,

     第二步:利用代码生成工具生成代码                                   

    进入HelloWorld.thrift所在目录,执行

    执行完成,你会发现没有任何提示,记得有位大神说过,没有任何提示就是好事。

    这时候发现在当前目录下多了一个gen-java的目录,里面有Thrift生成的HelloWorld.java

    OK,前两步已经完成,还是很简单的吧。

    第三步:编写你的业务逻辑                       

    创建一个Gradle管理的Java项目,bulid.gradle中添加相关的依赖,将gen-java中的HelloWorld.java拷贝到IDE的java项目中(注意包名,地址对应)。

    (喜欢用Maven的朋友可以用Maven构建)

    dependencies {
    	compile "org.apache.thrift:libthrift:0.9.2"
    	compile "org.slf4j:slf4j-log4j12:1.7.5"
    }
    

     创建HelloWorldServiceImpl实现HelloWorld.Iface接口,这个就是主要的业务逻辑。

    package service.impl;
    
    import org.apache.thrift.TException;
    import service.server.HelloWorld;
    
    /**
     * 服务端实现
     * 
     * @author tang
     */
    public class HelloWorldServiceImpl implements HelloWorld.Iface {
    
    	@Override
    	public String sendString(String para) throws TException {
    		System.out.println("接收到服务端传来的参数: " + para);
    		String result = "服务端成功收到消息";
    		return result;
    	}
    
    }
    

     接着,创建服务端实现代码,命名为HelloWorldServiceServer,把HelloWoeldServiceImpl作为一个具体的处理器传递给Thrift服务器:

    package service.server;
    
    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 tang
     */
    import service.impl.HelloWorldServiceImpl;
    
    public class HelloWorldServiceServer {
    
    	public static void main(String[] args) throws TTransportException {
    		System.out.println("服务端开启");
    
    		// 关联处理器
    		TProcessor tProcessor = new HelloWorld.Processor<HelloWorld.Iface>(new HelloWorldServiceImpl());
    
    		// 设置服务端口为 8080
    		TServerSocket serverSocket = new TServerSocket(8080);
    
    		// 简单的单线程服务模型
    		TServer.Args tArgs = new TServer.Args(serverSocket);
    		tArgs.processor(tProcessor);
    		// 设置协议工厂为 TBinaryProtocol.Factory
    		tArgs.protocolFactory(new TBinaryProtocol.Factory());
    		TServer server = new TSimpleServer(tArgs);
    		// 启动服务
    		server.serve();
    	}
    
    }
    

     最后,再写一个客户端HelloWorldClient.java:

    package client;
    
    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 service.server.HelloWorld;
    
    /**
     * 客户端
     * 
     * @author tang
     */
    public class HelloWorldClient {
    
    	public static void main(String[] args) {
    		System.out.println("客户端启动....");
    		TTransport transport = null;
    		try {
    			// 设置调用的服务地址为本地,端口为8080,超时设置为30秒
    			transport = new TSocket("localhost", 8080, 30000);
    			// 协议要和服务端一致
    			TProtocol protocol = new TBinaryProtocol(transport);
    			HelloWorld.Client client = new HelloWorld.Client(protocol);
    			transport.open();
    			// 调用接口方法
    			String result = client.sendString("Hello World!");
    			System.out.println(result);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (null != transport) {
    				transport.close();
    			}
    		}
    	}
    
    }
    

     这个是project结构图:

    这里有一些Thrift自带的警告,不用去管他(有点违背Effective java中的原则)。。。。。

    最后的最后:测试                                                                                            

    启动服务端,然后再启动客户端,这是服务端会收到来自客户端的消息:“HelloWorld”

    客户端收到服务端的反馈:

    好了,到这里,Thrift的第一个实例就结束了,总的来说Thrift还是很好用的,有些的不好的地方欢迎批评斧正!

    参考文章:

     http://www.blogjava.net/ldwblog/archive/2014/12/03/421011.html

  • 相关阅读:
    2018.11.5 Nescafe26 T1 小猫爬山
    2018.10.30 NOIp模拟赛T2 数字对
    2018.10.30 NOIp模拟赛 T1 改造二叉树
    2018/7/16 YMOI模拟 NOIP2013D2T3华容道
    数据结构实验
    我的第一个博客
    题解 P5035 【金坷垃】
    题解 P5036 【随机生成树】
    题解 P5037 【抓捕】
    题解 P1328 【生活大爆炸版石头剪刀布】
  • 原文地址:https://www.cnblogs.com/superfj/p/7359266.html
Copyright © 2011-2022 走看看