Apache Thrift快速入门教程

本文深入探讨了Thrift,一种跨语言的RPC框架,详细介绍了如何以不同模式(包括阻塞、非阻塞和异步)创建和服务Thrift服务及客户端。通过具体的代码示例,演示了在Java环境中如何实现算术服务,涵盖了从服务定义到客户端调用的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Thrift是一种跨语言RPC框架,最初是在Facebook上开发的,现在作为Apache项目开源。 这篇文章将描述如何以不同的模式(例如阻塞,非阻塞和异步)编写Thrift服务和客户端。

(我觉得后两种模式的文档较少,需要一些教程类型的介绍,因此是本文的动机。) 为了轻松地遵循本教程,您对Thrift体系结构(由传输,协议和处理器组成)有基本的了解是有益的。 (可以在[1]上找到好的论文)。 在这里,我将使用Thrift 0.7版和Thrift的Java绑定。

节俭安装
可以在http://wiki.apache.org/thrift/ThriftInstallation中找到安装说明。

总结Ubuntu安装步骤。

1.安装所需的依赖项。
$ sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libevent-dev automake libtool flex bison pkg-config g ++ libssl-dev
2.转到安装根目录。 3. $ ./configure 4. $ make 5.成为超级用户并 $进行安装

现在让我们继续创建服务并使用它。

服务定义

此处定义了具有简单算术运算的服务。 请注意,使用typedef指令为基本类型i64和i32声明备用名称。 在名为“ 算术.thrift ”的文件中添加以下内容。

namespace java tutorial.arithmetic.gen  // define namespace for java code

typedef i64 long
typedef i32 int
service ArithmeticService {  // defines simple arithmetic service
long add(1:int num1, 2:int num2),
long multiply(1:int num1, 2:int num2),
}

代码将在“ tutorial.arithmetic.gen ”包下生成。

现在,使用以下命令行生成Java代码。

$ thrift –gen java算术.thrift

将生成源tutorial.arithmetic.gen.ArithmeticService.java

封锁模式

让我们创建一个阻塞模式的服务器和一个使用服务的客户端。

首先,我们需要使用生成的服务框架来实现服务。 要实现的接口是ArithmeticService.Iface。

public class ArithmeticServiceImpl implements ArithmeticService.Iface {

    public long add(int num1, int num2) throws TException {
        return num1 + num2;
    }

    public long multiply(int num1, int num2) throws TException {
        return num1 * num2;
    }

}

现在,让我们创建Thrift服务器,该服务器将请求此服务。 请记住,这是一台阻塞服务器,因此执行I / O的服务器线程将等待。

public class Server {

    private void start() {
        try {
            TServerSocket serverTransport = new TServerSocket(7911);

            ArithmeticService.Processor processor = new ArithmeticService.Processor(new ArithmeticServiceImpl());

            TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).
                    processor(processor));
            System.out.println("Starting server on port 7911 ...");
            server.serve();
        } catch (TTransportException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Server srv = new Server();
        srv.start();
    }

}

这里使用了TThreadPoolServer实现,该实现将利用线程池来处理传入的请求。

现在让我们编写客户端。

public class ArithmeticClient {

    private void invoke() {
        TTransport transport;
        try {
            transport = new TSocket("localhost", 7911);

            TProtocol protocol = new TBinaryProtocol(transport);

            ArithmeticService.Client client = new ArithmeticService.Client(protocol);
            transport.open();

            long addResult = client.add(100, 200);
            System.out.println("Add result: " + addResult);
            long multiplyResult = client.multiply(20, 40);
            System.out.println("Multiply result: " + multiplyResult);

            transport.close();
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ArithmeticClient c = new ArithmeticClient();
        c.invoke();

    }
}

TBinaryProtocol用于对服务器和客户端之间传输的数据进行编码。 现在启动服务器,并使用客户端调用服务以生成结果。

非阻塞模式
现在让我们创建一个非阻塞服务器,该服务器在下面使用Java非阻塞I / O。 我们可以使用与以前相同的服务实现(ArithmeticServiceImpl)。

public class NonblockingServer {

    private void start() {
        try {
            TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(7911);
            ArithmeticService.Processor processor = new ArithmeticService.Processor(new ArithmeticServiceImpl());

            TServer server = new TNonblockingServer(new TNonblockingServer.Args(serverTransport).
                    processor(processor));
            System.out.println("Starting server on port 7911 ...");
            server.serve();
        } catch (TTransportException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NonblockingServer srv = new NonblockingServer();
        srv.start();
    }
}

在这里,使用TNonblockingServerSocket封装了ServerSocketChannel。

非阻塞客户端的代码如下。

public class NonblockingClient {

    private void invoke() {
        TTransport transport;
        try {
            transport = new TFramedTransport(new TSocket("localhost", 7911));
            TProtocol protocol = new TBinaryProtocol(transport);

            ArithmeticService.Client client = new ArithmeticService.Client(protocol);
            transport.open();

            long addResult = client.add(100, 200);
            System.out.println("Add result: " + addResult);
            long multiplyResult = client.multiply(20, 40);
            System.out.println("Multiply result: " + multiplyResult);

            transport.close();
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NonblockingClient c = new NonblockingClient();
        c.invoke();
    }

}

注意使用TFramedTransport包装正常的TSocket传输。 非阻塞服务器要求客户端使用TFramedTransport,它将对通过网络发送的数据进行框架化。 启动服务器并使用客户端发送请求。 您将看到与以前相同的结果,这次使用非阻止模式。

异步模式

我们可以编写异步客户端来调用Thrift服务。 需要注册一个回调,该回调将在请求成功完成时被调用。 阻塞模式服务器在异步客户端上不起作用(方法调用返回的响应为空)(可能是因为我们在客户端使用TNonblockingSocket。请参见ArithmeticService.AsyncClient的构造。因此这可能是正确的行为)。 非阻塞模式服务器似乎可以正常工作。 因此,您可以将早期版本的非阻塞服务器与下面显示的客户端一起使用。

public class AsyncClient {

    private void invoke() {
        try {
            ArithmeticService.AsyncClient client = new ArithmeticService.
                    AsyncClient(new TBinaryProtocol.Factory(), new TAsyncClientManager(),
                                new TNonblockingSocket("localhost", 7911));

            client.add(200, 400, new AddMethodCallback());

            client = new ArithmeticService.
                    AsyncClient(new TBinaryProtocol.Factory(), new TAsyncClientManager(),
                                new TNonblockingSocket("localhost", 7911));
            client.multiply(20, 50, new MultiplyMethodCallback());

        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        AsyncClient c = new AsyncClient();
        c.invoke();

    }

    class AddMethodCallback
            implements AsyncMethodCallback<ArithmeticService.AsyncClient.add_call> {

        public void onComplete(ArithmeticService.AsyncClient.add_call add_call) {
            try {
                long result = add_call.getResult();
                System.out.println("Add from server: " + result);
            } catch (TException e) {
                e.printStackTrace();
            }
        }

        public void onError(Exception e) {
            System.out.println("Error : ");
            e.printStackTrace();
        }

    }

    class MultiplyMethodCallback
            implements AsyncMethodCallback<ArithmeticService.AsyncClient.multiply_call> {

        public void onComplete(ArithmeticService.AsyncClient.multiply_call multiply_call) {
            try {
                long result = multiply_call.getResult();
                System.out.println("Multiply from server: " + result);
            } catch (TException e) {
                e.printStackTrace();
            }
        }

        public void onError(Exception e) {
            System.out.println("Error : ");
            e.printStackTrace();
        }

    }

}

已经定义了两个回调,分别与服务的每个操作相对应。 请注意,这两个调用使用了两个客户端实例。 每个调用都需要一个单独的客户端实例,否则客户端将因以下异常而失败

线程“ main ”中的异常java.lang.IllegalStateException:客户端当前正在执行另一种方法:tutorial.arithmetic.gen.ArithmeticService $ AsyncClient $ add_call

因此,本文以不同的操作模式总结了我在Thrift上的快速入门。 希望有人会觉得有用。 如有任何建议或更正,请随时发表评论。

[1] http://thrift.apache.org/static/thrift-20070401.pdf

参考:来自JCG合作伙伴的 Apache Thrift快速入门教程   Source Open博客中的Buddhika Chamith。


翻译自: https://www.javacodegeeks.com/2012/03/apache-thrift-quickstart-tutorial.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值