首页 > 代码库 > RPC简介与Thrift框架
RPC简介与Thrift框架
RPC,全称是remote process call,远程过程调用,简单来讲就是调用部署在另一台服务器上的服务或者被部署在另一台服务器上的服务调用。由于各服务部署在不同机器,服务间的调用免不了网络通信过程,服务消费方每调用一个服务都要写一坨网络通信相关的代码,不仅复杂而且极易出错。如果有一种方式能让我们像调用本地服务一样调用远程服务,而不用关心网络通信这些细节,那么将大大提高生产力。这就需要一些RPC框架了,如阿里巴巴的hsf、dubbo(开源)、Facebook的thrift(开源)、Google grpc(开源)、Twitter的finagle(开源)等。以下是一个RPC调用的通信流程图:
1)服务消费方(client)以本地调用方式调用服务;
2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3)client stub找到服务地址,并将消息发送到服务端;
4)server stub收到消息后进行解码;
5)server stub根据解码结果调用本地的服务;
6)本地服务执行并将结果返回给server stub;
7)server stub将返回结果打包成消息并发送至消费方;
8)client stub接收到消息,并进行解码;
9)服务消费方得到最终结果。
RPC框架就是把2~8步封装起来。
Thrift框架简单使用示例:
我们想在一个服务器上部署一个服务,很简单,就是传入用户名的时候,返回欢迎信息。
我们首先需要写一个thrift文件,其实就是个service定义文件,内容如下:
namespace java com.kou.testservice Hello{ string sayHello(1:string username)}
namespace指定包名,service是接口的关键字,Hello是service名,sayHello是方法名。文件名无所谓,但为了方便管理,最好和接口同名。
之后,再下载thrift的代码生成工具thrift-xxx.exe,放到和thrift文件同一目录下,然后在该目录中在命令行窗口执行
thrift --gen <language> <Thrift filename>
language是要生成的代码语言,thrift支持多种语言。
具体就是thrift --gen java Hello.thrift,执行之后就会在当前目录中产生一个名叫gen-java的文件夹,把文件夹中的代码文件拷贝到服务端web应用对应的包中。简单看一下这个文件,会发现原来的service名现在变成了类名,原来的sayHello方法跑到了Hello类的内部接口Iface中。
服务端发布RPC服务:
需要在服务端实现这个接口,所以新建一个类,实现Iface接口,重写其sayHello方法,代码如下:
import org.apache.thrift.TException;import com.kou.test.Hello.Iface;public class HelloImpl implements Iface { @Override public String sayHello(String username) throws TException { return "hello," + username; }}
如何启动服务呢,新建一个类,创建启动方法即可。
启动服务代码如下(不用记,套路基本固定):
public class HelloThriftServer { @SuppressWarnings({ "rawtypes", "unchecked" }) public void startServer() { try { TServer.Args tArgs = new TServer.Args(new TServerSocket(8090)); TProcessor tprocessor = new Hello.Processor(new HelloImpl()); tArgs.processor(tprocessor); tArgs.protocolFactory(new TBinaryProtocol.Factory()); TServer server = new TSimpleServer(tArgs); server.serve(); } catch (Exception e) { e.printStackTrace(); } }}
至此,服务端代码已完成,可以部署了。我们在此应用中配置一个监听器,当应用一启动的时候就调用HelloThriftServer实例的startServer()方法开启服务,待客户端调用。
监听器代码如下:
import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import com.kou.test.HelloThriftServer;/** * Application Lifecycle Listener implementation class ThriftListener * */public class ThriftListener implements ServletContextListener { /** * Default constructor. */ public ThriftListener() { // TODO Auto-generated constructor stub } @Override public void contextDestroyed(ServletContextEvent arg0) { // TODO Auto-generated method stub } @Override public void contextInitialized(ServletContextEvent arg0) { new HelloThriftServer().startServer(); }}
把应用部署到Tomcat中之后即可以接受客户端的调用了。至此,RPC服务发布完成了。
客户端调用:
客户端调用服务端的服务,只需知道服务端的ip和端口就好了(我们在上面的服务端代码中指定了端口是8090)。
客户端和服务端一样,都需要上面用thrift代码生成工具生成的java文件,复制到客户端web应用对应的包中,然后新建一个类,写调用服务的方法,代码如下(不用记,套路基本固定):
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 com.kou.test.Hello.Client;public class HelloThriftClient { public void invokeHelloThrift(String userName) { TTransport tTransport = null; try { // 服务端的ip和端口 tTransport = new TSocket("192.168.153.128", 8090, 30000); TProtocol protocol = new TBinaryProtocol(tTransport); Client client = new Client(protocol); tTransport.open(); // 调用接口方法 String str = client.sayHello(userName); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } finally { if (null != tTransport) { tTransport.close(); } } } /** * @param args */ public static void main(String[] args) { new HelloThriftClient().startClient("寇胜瑞"); }}
此时,客户端应用就可以用invokeHelloThrift()方法来调用RPC服务了。这里我们通过简单的main方法来测试是否可以成功调用。
RPC简介与Thrift框架