Thrift学习

已转移

使用经验

client端

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;

public class HelloClientDemo {

    public static final String SERVER_IP = "localhost";
    public static final int SERVER_PORT = 8090;
    public static final int TIMEOUT = 30000;

    public void startClient(String userName) {
        TTransport transport = null;
        try {
            transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
            // 协议要和服务端一致
            TProtocol protocol = new TBinaryProtocol(transport);
            // TProtocol protocol = new TCompactProtocol(transport);
            // TProtocol protocol = new TJSONProtocol(transport);
HelloWorldService.Client client = new HelloWorldService.Client(
                    protocol);
            transport.open();
            String result = client.sayHello(userName);
            System.out.println("Thrify client result =: " + result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        HelloClientDemo client = new HelloClientDemo();
        client.startClient("Michael");

    }

}

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;

public class HelloServerDemo {
    public static final int SERVER_PORT = 18090;

    public void startServer() {
        try {
            System.out.println("HelloWorld TSimpleServer start ....");

            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(
                    new HelloWorldImpl());
            // HelloWorldService.Processor&lt;HelloWorldService.Iface&gt; tprocessor =
            // new HelloWorldService.Processor&lt;HelloWorldService.Iface&gt;(
            // new HelloWorldImpl());

            // 简单的单线程服务模型,一般用于测试
            TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
            TServer.Args tArgs = new TServer.Args(serverTransport);
            tArgs.processor(tprocessor);
            tArgs.protocolFactory(new TBinaryProtocol.Factory());
            // tArgs.protocolFactory(new TCompactProtocol.Factory());
            // tArgs.protocolFactory(new TJSONProtocol.Factory());
            TServer server = new TSimpleServer(tArgs);
            server.serve();

        } catch (Exception e) {
            System.out.println("Server start error!!!");
            e.printStackTrace();
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        HelloServerDemo server = new HelloServerDemo();
        server.startServer();
    }
}

Thrift的主要组件
Transport:传输组件,类似与Java中的IO流、socket

Protocol:提供协议和编解码的组件

Process:服务端处理请求的组件

ServiceClient:客户端组件,与Process对应

Server:服务端组件,提供了异步、同步、半异步半同步的实现
这里写图片描述
Thrift框架的远程过程调用的工作过程如下:
(2) Thrift生成的特定语言的接口文件中包括客户端部分和服务器部分;
(3)客户端通过接口文件中的客户端部分生成一个Client对象,这个客户端对象中包含所有接口函数的存根实现,然后用户代码就可以通过这个Client对象来调用thrift文件中的那些接口函数了,但是,客户端调用接口函数时实际上调用的是接口函数的本地存根实现
(4)接口函数的存根实现将调用请求发送给thrift服务器端,然后thrift服务器根据调用的函数名和函数参数,调用实际的实现函数来完成具体的操作
(5)Thrift服务器在完成处理之后,将函数的返回值发送给调用的Client对象;
(6) Thrift的Client对象将函数的返回值再交付给用户的调用函数
  更详细的过程
  (1). client代码像普通函数调用一样调用client stub函数,这个调用是本地调用,调用参数会和平常函数调用一样进行返回地址和调用参数压栈操作;
  (2). client stub会把调用参数和其它信息(比如调用方法名、调用属性等,可以称为metadata)进行打包封装成message,然后通过系统调用发送该message,这个打包的过程是个序列化的过程;
  (3). client寻求到服务端的地址,然后通过本地操作系统经由某种协议,将上述message发送给server端;
  (4). server端的操作系统接收message后将其传递给server stub;
  (5). server stub将message解包,得到原始传递过来的各项调用参数,解包的过程是反序列化的过程;
  (6). server stub调用server端的本地函数,然后将得到的结果按照上述类似的步骤反向传递给client作为结果返回。当然整个过程也可能不那么顺利,那么也应该产生合适的状态码、异常信息作为返回。
 所以RPC实际是通过client stub和server stub起到一个代理的作用,将client的请求转发到server端去操作,并将操作得到的结果回传,因为传递是跨进程、跨主机的,所以必须进行序列化和反序列化的过程来保证消息的正确性

基于java注解的thrift
注解说明
service <-> @ThriftService
struct <-> @ThriftStruct
struct 属性 <-> @ThriftField
enum <-> @ThriftEnumValue
method<->ThriftMethod
constuctor↔ThriftConstructor
field ↔ ThriftField
枚举类型可以直接传输
需要配置 thrift-publish-beans.xml服务端,常用 thrift-client-beans.xml 客户端没有webapp 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
thrift-generator 是通过 Java 的接口生成 thrift 文件的工具。例子:public interface ICommonUserService {     public User login(int id, String name);     public User getUserById(long id);     public boolean saveUser(User user);     public List getUserIds(long id);      public Map getUserByIds(List ids);     public Map<String, List> getUsersByName(List names);     public Map<Long, List> getGroupUsers(List names, List userList, List lns, long ll);     public List testCase1(Map num1, List num2, List num3, long num4, String num5); } public class ThriftStructBuilderTest {     private ThriftFileBuilder fileBuilder = new ThriftFileBuilder();     @Test     public void toOutputstream() throws Exception {         this.fileBuilder.buildToOutputStream(ICommonUserService.class, System.out);     } }执行代码:mvn test -Dtest=com.sohu.thrift.generator.builder.ThriftStructBuilderTest之后控制台输出如下:namespace java com.sohu.thrift.generator.test.thrift     enum Status {             NORMAL = 0,             BLOCKED = 1     }     struct Account {             1:i32 id,             2:string name     }     struct User {             1:i32 id,             2:string name,             3:bool sex,             4:Status status,             5:list ids,             6:Account account     }     service ICommonUserService {             User login(1:i32 arg0,2:string arg1),             map<string, list> getUsersByName(1:list arg0),             bool saveUser(1:User arg0),             map getUserByIds(1:list arg0),             list getUserIds(1:i64 arg0),             map<i64, list> getGroupUsers(1:list arg0,2:list arg1,3:list arg2,4:i64 arg3),             User getUserById(1:i64 arg0),             list testCase1(1:map arg0,2:list arg1,3:list arg2,4:i64 arg3,5:string arg4)     }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值