RabbitMQ使用场景练习:RPC(七)

[list][*][b]RPC,同步消息[/b][/list]
RabbitMQ默认的consumer为异步监听,RPC应用需要实现consumer的同步,可以使用QueueingConsumer(继承与DefaultConsumer,定义了一个堵塞队列LinkedBlockingQueue)实现同步
实际上就是服务端、客户端各定义一个消息队列,相互发送消息,客户端发送消息后同步等待结果返回

[list]
[*][b]注意要点[/b]
[/list]
[i]发送消息时指定回复队列、corrId[/i]:
//发送消息,指定回复消息所在队列
BasicProperties props=new BasicProperties.Builder().correlationId(corrId).replyTo(queueName).build();
channel.basicPublish("", "rpc_queue", props, SerializationUtils.serialize(mes));

[i]监听队列,等待服务端反馈(堵塞)[/i]:
 //监听队列,接收服务端回复消息
while(true){
QueueingConsumer.Delivery delivery=consumer.nextDelivery();//堵塞
//do something
break;
}

[i]服务端接收消息处理后回写处理结果[/i]:
channel.basicPublish("", properties.getReplyTo() ,new BasicProperties.Builder().correlationId(properties.getCorrelationId()).build(), 
SerializationUtils.serialize("response:"+mes));

[i]服务端开启手动应答[/i]:
//关闭自动应答机制,默认开启;这时候需要手动进行应该
channel.basicConsume("rpc_queue", false, consumer);
channel.basicAck(envelope.getDeliveryTag(), false);

[i]限制服务端最大处理量[/i]:
channel.basicQos(1);

[list]
[*][b]RPC服务端[/b]
[/list]
package com.demo.mq.rabbitmq.example06;

import java.io.IOException;
import java.io.Serializable;

import org.apache.commons.lang3.SerializationUtils;

import com.demo.mq.rabbitmq.MqManager;
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.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

/**
* RPC服务端
* @author sheungxin
*
*/
public class RPCServer{

/**
* RPC服务端,声明一个服务处理队列,接收消息处理后,把结果回写给客户端
* 需要开启手动应答机制,确保服务执行完成
* @param object 消息主体
* @throws IOException
*/
public static void sendAToB(Serializable object) throws Exception{
Connection conn=MqManager.newConnection();
Channel channel=conn.createChannel();
channel.queueDeclare("rpc_queue", false, false, false, null);
channel.basicQos(1);

Consumer consumer=new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body) throws IOException{
String mes=SerializationUtils.deserialize(body);
System.out.println(envelope.getRoutingKey()+":Received :'"+mes+"' done");
//接收到消息后,向发送方回写消息:指定发送方所在队列(properties.getReplyTo())、correlationId
channel.basicPublish("", properties.getReplyTo() ,
new BasicProperties.Builder().correlationId(properties.getCorrelationId()).build(),
SerializationUtils.serialize("response:"+mes));
channel.basicAck(envelope.getDeliveryTag(), false);
}
};
//关闭自动应答机制,默认开启;这时候需要手动进行应该
channel.basicConsume("rpc_queue", false, consumer);
System.out.println("*********8");
}

public static void main(String[] args) throws Exception {
sendAToB("Hello World !");
}
}

[list]
[*][b]RPC客户端[/b]
[/list]
package com.demo.mq.rabbitmq.example06;

import java.util.UUID;

import org.apache.commons.lang3.SerializationUtils;

import com.demo.mq.rabbitmq.MqManager;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;

/**
* RPC客户端
* @author sheungxin
*
*/
@SuppressWarnings("deprecation")
public class RPCClient {

/**
* RPC客户端:向服务端处理队列发送消息,发送时指定correlationId、回复队列名称,同时在回复队列上建立consumer,进行监听接收回复消息
* @param mes
* @throws Exception
*/
public static String call(String mes) throws Exception{
String response=null;
Connection conn=MqManager.newConnection();
Channel channel=conn.createChannel();
//创建一个临时队列,用于接收回复消息
String queueName=channel.queueDeclare().getQueue();
QueueingConsumer consumer=new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer);

String corrId=UUID.randomUUID().toString();
//发送消息,指定回复消息所在队列
BasicProperties props=new BasicProperties.Builder().correlationId(corrId).replyTo(queueName).build();
channel.basicPublish("", "rpc_queue", props, SerializationUtils.serialize(mes));

//监听队列,接收服务端回复消息
while(true){
QueueingConsumer.Delivery delivery=consumer.nextDelivery();
if(delivery.getProperties().getCorrelationId().equals(corrId)){
response=SerializationUtils.deserialize(delivery.getBody());
break;
}
}
return response;
}

public static void main(String[] args) throws Exception {
System.out.println(call("hello world"));
System.out.println("waiting for rpc is over");
}

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值