rabbitmq-RPC模式
使用条件:需要通知远程计算机运行功能并等待返回运行结果。这个过程是阻塞的。
原理:
当客户端启动时,它创建一个匿名独占回调队列。并提供名字为call的函数,这个call会发送RPC请求并且阻塞知道收到RPC运算的结果。
首先提供官方更为详细的地址:http://www.rabbitmq.com/tutorials/tutorial-six-java.html
下面是java详细代码及参数功能说明
client端代码(消息发送和返回结果接收)
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
/**
* @Description: rabbitmq的RPC模式客户端
*
* @author zhanbian
* @date 2017年6月23日 上午11:03:03
*/
public class RpcClient {
private Connection connection;
private Channel channel;
private String requestQueueName = "rpc_queue";
private String replyQueueName;
public RpcClient() throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");//设置服务地址
factory.setPort(5672);//设置端口
factory.setUsername("admin");//用户名和密码
factory.setPassword("admin123456");
connection = factory.newConnection();//创建一个连接
channel = connection.createChannel();//创建了一个连接的通道
replyQueueName = channel.queueDeclare().getQueue();//声明回调队列
System.out.println(replyQueueName);
}
//请求返回
public String call(String message) throws UnsupportedEncodingException, IOException, InterruptedException{
String corrId = UUID.randomUUID().toString();
//此处为返回的核心
AMQP.BasicProperties props = new AMQP.BasicProperties
.Builder()
.correlationId(corrId)//队列的唯一值认证
.replyTo(replyQueueName)//回调队列
.build();
//发送消息
channel.basicPublish("", requestQueueName, props, message.getBytes("utf8"));
//用于存放数据的阻塞队列
final BlockingQueue<String> response = new ArrayBlockingQueue<String>(1);
//接收返回数据
channel.basicConsume(replyQueueName, true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
if(properties.getCorrelationId().equals(corrId)){
response.offer(new String(body, "utf8"));
}
}
});
return response.take();
}
//关闭连接
public void close() throws IOException{
if(connection!=null){
this.connection.close();
}
}
public static void main(String[] args){
RpcClient rc = null;
try {
rc = new RpcClient();
System.out.println("发送消息");
String response = rc.call("发送消息|");
System.out.println(response);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(rc!=null){
rc.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
server端代码(消息接收和结果返回)
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
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.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
/**
* @Description: rabbitmq的RPC模式服务端
* 和消费者代码差不多,多了一个消息返回
* @author zhanbian
* @date 2017年6月23日 上午11:07:25
*/
public class RpcServer {
private static final String RPC_QUEUE_NAME = "rpc_queue";
private Connection connection;
private Channel channel;
public RpcServer() throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");//设置服务地址
factory.setPort(5672);//设置端口
factory.setUsername("admin");
factory.setPassword("admin123456");
connection = factory.newConnection();//创建一个连接
channel = connection.createChannel();//创建了一个连接的通道
channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
channel.basicQos(1);
System.out.println(" [x] Awaiting RPC requests");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
AMQP.BasicProperties props = new AMQP.BasicProperties
.Builder()
.correlationId(properties.getCorrelationId())
.build();
String response = "";
try {
String message = new String(body,"UTF-8");
System.out.println(" [.] fib(" + message + ")");
response = fib(message);
} catch (RuntimeException e) {
e.printStackTrace();
} finally {
channel.basicPublish( "", properties.getReplyTo(), props, response.getBytes("UTF-8"));
channel.basicAck(envelope.getDeliveryTag(), false);//手动确认消息已接收
}
}
};
channel.basicConsume(RPC_QUEUE_NAME, false, consumer);//想要自动确认接收改为true同事屏蔽basicAck
}
//接收到消息处理的具体方法
private static String fib(String message) {
message +="加了点内容返回";
return message;
}
public static void main(String[] args) {
try {
new RpcServer();
} catch (Exception e) {
e.printStackTrace();
}
}
}
fib()方法是对接收结果处理的过程
注意服务的队列要相同
至此客户端和服务端的内容都已完成,修改host,用户,密码可直接运行