(我觉得后两种模式的文档较少,需要一些教程类型的介绍,因此是本文的动机。) 为了轻松地遵循本教程,您对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