结合上一篇文章接着往下写。
路由 routing
日志系统,将error的日志信息发送到一个队列,进行保存到logs文件中。将error info warning的日志信息发送到另一个队列,进行控制台打印操作。这里可是通过 绑定秘钥 路由秘钥参数来配置。
再上一个技术发布订阅,添加一点限制,是消费者只能订阅一部分消息。
例如,我们只能将关键错误消息定向到日志文件,同时仍然能够在控制台上打印所有日志消息
绑定可以采用routingKey参数,为了避免与basic_Publish 参数混淆,将其称之为绑定秘钥
channel.queueBind(queueName, exchangeName, "severityError");
绑定秘钥的含义取决于交换机的类型,上一篇中使用的fanout类型交换机忽略了绑定秘钥。
直接交换机 direct
Exchange fanout(扇出交换机),它没有给我们太大灵活性,它只能进行无意识的广播。
Exchange direct(直接交换机),直接交换背后的路由算法很简单,消息进入队列,其绑定秘钥和路由秘钥完全匹配(匹配不上的消息被丢弃)
多个绑定
使用相同的绑定秘钥绑定多个队列是完全合法的。
贴代码
生产者代码
public class Routingsend {
final static String EXCHANGE_NAME = "direct_logs";
static ConnectionUtil connUtil = new ConnectionUtil();
public static void main(String[] args) throws Exception {
Connection conn = connUtil.getConn();
Channel channel = conn.createChannel();
//声明交换机 指定direct直连类型
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
String message = "Exchange type direct, test routing";
//定义路由秘钥 error
String severity = "error";
//发布到交换机
channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());
System.out.println("绑定秘钥:"+severity+", 消息:"+message);
//定义路由秘钥 info
String severity2 = "info";
//发布到交换机
channel.basicPublish(EXCHANGE_NAME, severity2, null, message.getBytes());
System.out.println("绑定秘钥:"+severity2+", 消息:"+message);
//定义路由秘钥 warning
String severity3 = "warning";
//发布到交换机
channel.basicPublish(EXCHANGE_NAME, severity3, null, message.getBytes());
System.out.println("绑定秘钥:"+severity3+", 消息:"+message);
// 关闭通道和连接
channel.close();
conn.close();
}
}
消费者1 代码,用来将error的日志信息发送到一个队列,进行保存到logs文件中
public class RoutingReceiver1 {
final static String EXCHANG_NAME = "direct_logs";
static ConnectionUtil connUtil = new ConnectionUtil();
public static void main(String[] args) throws Exception {
Connection conn = connUtil.getConn();
Channel channel = conn.createChannel();
//声明交换机 指定direct直连类型
channel.exchangeDeclare(EXCHANG_NAME, "direct");
//获取临时队列名称
String queneName = channel.queueDeclare().getQueue();
//绑定队列 error为绑定秘钥,其绑定秘钥和路由秘钥完全匹
channel.queueBind(queneName, EXCHANG_NAME, "error");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("路由秘钥:"+delivery.getEnvelope().getRoutingKey()+",接受消息: '" + message + "'");
};
channel.basicConsume(queneName, true, deliverCallback, consumerTag -> {});
}
}
消费者2 代码,将error info warning的日志信息发送到另一个队列,进行控制台打印操作
public class RoutingReceiver2 {
final static String EXCHANG_NAME = "direct_logs";
static ConnectionUtil connUtil = new ConnectionUtil();
public static void main(String[] args) throws Exception {
Connection conn = connUtil.getConn();
Channel channel = conn.createChannel();
//声明交换机 指定direct直连类型
channel.exchangeDeclare(EXCHANG_NAME, "direct");
//获取临时队列名称
String queneName = channel.queueDeclare().getQueue();
//绑定队列 绑定多个
channel.queueBind(queneName, EXCHANG_NAME, "info");
//使用相同的绑定秘钥绑定多个队列是完全合法的,上面也用这个绑定秘钥
channel.queueBind(queneName, EXCHANG_NAME, "error");
channel.queueBind(queneName, EXCHANG_NAME, "warning");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("路由秘钥:"+delivery.getEnvelope().getRoutingKey()+",接受消息: '" + message + "'");
};
channel.basicConsume(queneName, true, deliverCallback, consumerTag -> {});
}
}