In our last blog post, we used direct exchange instead of fanout exchange. This time, let's look at topic exchange.
Introduction to Topic Exchange
Topic exchange is similar to direct exchange in that it matches routing key and binding key, but topic exchange can set multiple criteria for routing key.
direct routers are similar to exact queries in sql statements; topic routers are somewhat similar to fuzzy queries in sql statements.
Do you remember? We are in the " RabbitMQ Introduction: Publish/Subscribe > The classification of exchange is introduced.
Direct: Delivery is based entirely on key. For example, when routing key is set to "abc" at binding time, messages submitted by clients will only be delivered to the queue if key is set to "abc". Topic: The key is delivered after pattern matching. Symbol "" matches one or more words. Symbol "*" matches exactly one word. For example, "abc. " matches "abc.def.ghi", "abc. *" only matches "abc.def". Fanout: No key is required. It takes a broadcast mode, and when a message comes in, it is delivered to all queues bound to the switch. Headers: We can ignore it.
Below is the working model given by the official website (P for producer, X for exhange, red Q for queue, C for consumer):
Let's analyze this model.
It sends messages to describe animals. Routing keys have three words: <speed>. <color>. <species>. The first word describes speed, the second describes color, and the third describes species.
There are three binding keys, Q1 binding key is *. orange. * (focus on all animals with orange color); Q2 binding key has two, namely *. *. rabbit (focus on all rabbits) and lazy. # (focus on all animals with lazy speed).
Therefore, messages with the routing key quick.orange.rabbit will be sent to Q1 and Q2, messages with the routing key quick.orange.fox will be sent to Q1, and messages with the routing key lazy.brown.fox will be sent to Q2. The message with the routing key lazy.pink.rabbit will be sent to Q2, but note that it only reaches Q2 once, although it matches two binding keys. Messages with the routing key quick.brown.fox will be discarded because they do not match any binding key.
What if someone shakes four words like lazy.orange.male.rabbit? Because it matches lazy. #, it will be sent to Q2.
Code examples
Now let's look at the code.
- Producer
public class LogTopicSender { // exchange Name public static String EXCHANGE_NAME = "topicExchange"; public static void main(String[] args) { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = null; Channel channel = null; try { // 1.Create connections and channels connection = factory.newConnection(); channel = connection.createChannel(); // 2.Statement for channels topic Type exchange channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC); // 3.Send a message to the specified exchange,Queue specified as empty,from exchange Determine which queues to send depending on the situation String routingKey = "info"; // String routingKey = "log4j.error"; // String routingKey = "logback.error"; // String routingKey = "log4j.warn"; String msg = " hello rabbitmq, I am " + routingKey; channel.basicPublish(EXCHANGE_NAME, routingKey, null, msg.getBytes()); System.out.println("product send a msg: " + msg); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } finally { // 4.Close connection if (connection != null) { try { connection.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
- Consumer
public class LogTopicReciver { public static void main(String[] args) { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = null; Channel channel = null; try { // 1.Create connections and channels connection = factory.newConnection(); channel = connection.createChannel(); // 2.Statement for channels topic Type exchange channel.exchangeDeclare(LogTopicSender.EXCHANGE_NAME, BuiltinExchangeType.TOPIC); // 3.Create queues with random names String queueName = channel.queueDeclare().getQueue(); // 4.establish exchange Binding relationship with queues String[] bindingKeys = { "#" }; // String[] bindingKeys = { "log4j.*", "#.error" }; // String[] bindingKeys = { "*.error" }; // String[] bindingKeys = { "log4j.warn" }; for (int i = 0; i < bindingKeys.length; i++) { channel.queueBind(queueName, LogTopicSender.EXCHANGE_NAME, bindingKeys[i]); System.out.println(" **** LogTopicReciver keep alive ,waiting for " + bindingKeys[i]); } // 5.Generate and monitor consumers through callbacks Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, com.rabbitmq.client.AMQP.BasicProperties properties, byte[] body) throws IOException { // Get the message content and process it String msg = new String(body, "UTF-8"); System.out.println("*********** LogTopicReciver" + " get message :[" + msg + "]"); } }; // 6.Consumer News channel.basicConsume(queueName, true, consumer); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } } }
- Start consumers as consumers 1
- Change String[] bindingKeys = {""}; to String[] bindingKeys = {"log4j. *", "#. error"}; / String[] bindingKeys = {"*. error"}; / String[] bindingKeys = {"log4j. warn}; and then start as Consumer 2, Consumer 3, and Consumer 4.
- Start four producers, routing key is String routing key = info; String routing key = log4j. error; String routing key = logback. error; String routing key = log4j. warn;
- Observing console log
Producer: product send a msg: hello rabbitmq, I am info product send a msg: hello rabbitmq, I am log4j.error product send a msg: hello rabbitmq, I am logback.error product send a msg: hello rabbitmq, I am log4j.warn //Consumer 1: **** LogTopicReciver keep alive ,waiting for # *********** LogTopicReciver get message :[ hello rabbitmq, I am info] *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.error] *********** LogTopicReciver get message :[ hello rabbitmq, I am logback.error] *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.warn] //Consumer 2: **** LogTopicReciver keep alive ,waiting for log4j.* **** LogTopicReciver keep alive ,waiting for #.error *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.error]
*********** LogTopicReciver get message :[ hello rabbitmq, I am logback.error] *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.warn] //Consumer 3: **** LogTopicReciver keep alive ,waiting for *.error *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.error] *********** LogTopicReciver get message :[ hello rabbitmq, I am logback.error] //Consumer 4: **** LogTopicReciver keep alive ,waiting for log4j.warn *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.warn] - Watch RabbitMQ Management Page