之前学习了怎么去使用work queue来把比较耗时的任务分散给多个worker。
但是,如果我们想在远程的机器上的一个函数并等待它返回结果,我们应该怎么办呢?这就是另外一种模式了,它被称为RPC(Remote procedure call)。
本中我们来实现怎么用RabbitMQ来构建一个RPC系统:一个client(客户端)和一个可扩展的RPC server(服务端)。这里我们来模拟一个返回斐波拉契数的RPC服务。
1、Client端接口
为了说明一个RPC服务时怎么工作的,我们来创建一个简单的client类。这里来实现一个名字为call的方法来发送RPC请求,并发生阻塞,直到接收到回复:
FibonacciRpcClient fibonacciRpc = new FibonacciRpcClient();
String result = fibonacciRpc.call("4");
System.out.println( "fib(4) is " + result);
RPC注意事项:
虽然RPC是一种常用的模式,但它也有一些缺陷。当无法确定使用本地调用还是使用RPC时,问题就出来了。有的时候不确定程序的运行环境,这样来做会给程序的调试增加了一定的复杂度。使用RPC并不能够让代码变得更简洁,滥用的话只会让代码变得更不方便维护。
伴随着上边的问题,咱们来看看下边的建议:
- 确定能很明显的分辨的出哪些调用是本地调用,哪些是远程调用。
- 完善系统的文档。清楚的标记出,模块间的依赖关系。
- 处理错误情况。当RPC服务挂了之后,客户端应该怎么去处理呢?
- 当有疑问时避免使用RPC。如果可以的话,你可以使用异步管道(不用RPC-阻塞),结果被异步推送到下一个计算环节。
2、回调队列(Callback queue)
一般用RabbitMQ来实现RPC是很简单的。客户端发送一个请求消息然后服务器端回应一个响应消息。为了接收服务端的响应消息,我们需要在请求中发送一个callback queue地址。我们也可以使用一个默认的queue(Java客户端独有的)。如下:
callbackQueueName = channel.queueDeclare().getQueue();
//绑定callback queue
BasicProperties props = new BasicProperties.Builder().replyTo(callbackQueueName).build();
channel.basicPublish("", "rpc_queue", props, message.getBytes());
// ... then code to read a response message from the callback_queue ...
消息属性:
AMQP协议在发送消息时,预定义了14个属性连同消息一起发送出去。很