消息中间件 - 原生Java客户端进行消息通信(Topic模式)(二十)
原创
©著作权归作者所有:来自51CTO博客作者日薪灬越亿的原创作品,请联系作者获取转载授权,否则将追究法律责任
通过使用“*”和“#”,使来自不同源头的消息到达同一个队列,”.”将路由键分为了几个标识符,“*”匹配1个,“#”匹配一个或多个。例如日志处理:
假设有交换器log-exchange,
日志级别有error,info,warning,
应用模块有user,order,email,
服务器有 A、B、C、D
路由键的规则为 服务器+“.”+日志级别+“.”+应用模块名,如:A. info .email。
1、要关注A服务器发送的所有应用错误的消息,怎么做?
声明队列名称为“a-app-error-queue”并绑定到交换器上:channel. queueBind (‘a-app-error-queue’,’logs-change’,’A.error.*’)
2、关注B服务器发送的的所有日志,怎么办?
声明队列名称为“b-all-queue”并绑定到交换器上:channel. queueBind (b-all-queue’,’logs-change’,’ B.#’)或channel. queueBind (b-all-queue’,’logs-change’,’ B.*.*’)
3、关注所有服务器发送的email的所有日志,怎么办?
声明队列名称为“email-all-queue”并绑定到交换器上:channel. queueBind (email -all-queue’,’logs-change’,’ *.*.emal’)
4、想要接收所有日志:channel->queue_bind(‘all-log’,’logs-change’,’#’)
生产者:
public class TopicProducer {
public final static String EXCHANGE_NAME = "topic_logs";
public static void main(String[] args)
throws IOException, TimeoutException {
/**
* 创建连接连接到RabbitMQ
*/
ConnectionFactory factory = new ConnectionFactory();
// 设置MabbitMQ所在主机ip或者主机名
factory.setHost("127.0.0.1");
// 创建一个连接
Connection connection = factory.newConnection();
// 创建一个信道
Channel channel = connection.createChannel();
// 指定转发
channel.exchangeDeclare(EXCHANGE_NAME,
BuiltinExchangeType.TOPIC);
/*日志消息,路由键最终格式类似于:info.order.B*/
String[] severities={"error","info","warning"};
for(int i=0;i<3;i++){
String[] modules={"user","order","email"};
for(int j=0;j<3;j++){
String[] servers={"A","B","C"};
for(int k=0;k<3;k++){
// 发送的消息
String message = "Hello Topic_["+i+","+j+","+k+"]";
String routeKey = severities[i%3]+"."+modules[j%3]
+"."+servers[k%3];
channel.basicPublish(EXCHANGE_NAME,routeKey,
null, message.getBytes());
System.out.println(" [x] Sent '" + routeKey +":'"
+ message + "'");
}
}
}
// 关闭频道和连接
channel.close();
connection.close();
}
}
消费者(ServerB的全部消息):
public class ServerBAllConsumer {
public static void main(String[] argv) throws IOException,
InterruptedException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
// 打开连接和创建频道,与发送端一样
Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();
channel.exchangeDeclare(TopicProducer.EXCHANGE_NAME,
BuiltinExchangeType.TOPIC);
// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"#.B");
System.out.println(" [*] Waiting for messages:");
// 创建队列消费者
final Consumer consumerA = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" AllConsumer Received "
+ envelope.getRoutingKey()
+ "':'" + message + "'");
}
};
channel.basicConsume(queueName, true, consumerA);
}
}
消费者(ServerA的ERROR消息):
// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"error.*.A");
System.out.println(" [*] Waiting for messages:");
消费者(所有的ERROR消息):
// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"error.#");
System.out.println(" [*] Waiting for messages:");
消费者(所有的EMAIl消息):
// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"*.email.*");
System.out.println(" [*] Waiting for messages:");
消费者(所有的消息):
// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"#");
System.out.println(" [*] Waiting for messages:");