RPC
/* Routing Model /->(Request repQueue=123 cid=abc) [...](request Queue) \ RPCClient RPCServer <-\(Reply correlation_id=abc) [...](reply Queue:123) / */
远程过程调用的应用场景也很广,我们来看看如何用rabbitmq实现rpc编程
RemoteService rs = new RemoteService();
String result = rs.speak("2012"); //block until the answer is received
System.out.println("Goodbye " + result);
关于RPC的一点看法,尽管它是一种常用的编程模型,却饱受批评,开发人员没法知道自己调用的程序是本地程序还是远程程序,可能会造成很多困惑,增加调试的复杂程度。(可以考虑使用异步流水线替代阻塞调用)
callback queue
客户端将消息和响应队列信息一并发给服务器端
RPCClient.java
package test;
import java.io.IOException;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.ShutdownSignalException;
public class RPCClient {
private Connection connection;
private Channel channel;
public RPCClient() throws IOException{
// 创建一个连接连接服务器
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
connection = factory.newConnection();
channel = connection.createChannel();
}
public void close() throws IOException{
channel.close();
connection.close();
}
public String call(String message) throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException {
String response;
String replyQueueName = channel.queueDeclare().getQueue();
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(replyQueueName, true, consumer);
String corrId = java.util.UUID.randomUUID().toString();
BasicProperties props = new BasicProperties.Builder().correlationId(corrId).replyTo(replyQueueName).build();
channel.basicPublish("", "request_queue", props, message.getBytes());
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
if(delivery.getProperties().getCorrelationId().equals(corrId)){
response = new String(delivery.getBody());
break;
}
}
return response;
}
public static void main(String[] args) throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException {
RPCClient client = new RPCClient();
String res = new String(client.call("test"));
System.out.println(res);
client.close();
}
}
RPCServer.java
package test;
import java.io.IOException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ShutdownSignalException;
import com.rabbitmq.client.AMQP.BasicProperties;
public class RPCServer {
public static void main(String[] args) throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException {
// 创建一个连接接收数据
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("request_queue", false, false, false, null);
channel.basicQos(1);
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume("request_queue", false, consumer);
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
BasicProperties props = delivery.getProperties();
BasicProperties replyProps = new BasicProperties.Builder().correlationId(props.getCorrelationId()).replyTo(props.getCorrelationId()).build();
String response = new String("Hello" + new String(delivery.getBody()));
channel.basicPublish("", props.getReplyTo(), replyProps, response.getBytes());
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
分别运行RPCClient和RPCServer,可以得到结果hellotest