Rabbitmq之交換機

生產者將消息發送到消息系統的時候,不是直接發送到隊列,而是發送到交換機,由交換機路由到相應的隊列

交換機有三種路由模式

1.direct

交換機通過一個routing key和隊列綁定,當生產者生產消息的時候指定一個routing key,當綁定隊列的routing key和生產者發送的routing key一致,那麼交換機就會把消息發送到這個隊列

public class ConnectionUtil {

	public static String QUEUE_NAME = "testQueue";

	public static String EXCHANGE_NAME = "testExchange";
	public static Connection getConnection() throws Exception{
		ConnectionFactory factory = new ConnectionFactory();

		//設置服務端所在地址
		factory.setHost("127.0.0.1");
		//設置端口號
		factory.setPort(5672);
		//設置用戶名
		factory.setUsername("helloWorld");
		//設置密碼
		factory.setPassword("helloWorld");
		//設置虛擬地址
		factory.setVirtualHost("testHost");

		return factory.newConnection();
	}
}
public class Send {

	public static void main(String[] args) throws Exception{
		//獲取連接
		Connection connection = ConnectionUtil.getConnection();

		Channel channel = connection.createChannel();
		//聲明隊列
		channel.queueDeclare("testQueue1",false,false,false,null);
		channel.queueDeclare("testQueue2",false,false,false,null);
		channel.queueDeclare("testQueue3",false,false,false,null);
		//聲明交換機
		channel.exchangeDelete(ConnectionUtil.EXCHANGE_NAME);
		channel.exchangeDeclare(ConnectionUtil.EXCHANGE_NAME,BuiltinExchangeType.DIRECT);

		//交換機和隊列綁定
		channel.queueBind("testQueue1",ConnectionUtil.EXCHANGE_NAME,"info.user");
		channel.queueBind("testQueue2",ConnectionUtil.EXCHANGE_NAME,"warning.user");
		channel.queueBind("testQueue3",ConnectionUtil.EXCHANGE_NAME,"error.user");

		channel.basicPublish(ConnectionUtil.EXCHANGE_NAME,"info.user",null,"helloWorld".getBytes());

		System.out.println("發送的信息爲:helloWorld");
		channel.close();
		connection.close();

	}
}

 消息只會發送到與交換機綁定並且routing key一致的隊列

 下面三個消費者分別和三個隊列綁定,只有第一個消費者可以拉取到消息進行消費

public class Recv1 {

	public static void main(String[] args) throws Exception{
		Connection connection = ConnectionUtil.getConnection();
		final Channel channel = connection.createChannel();
		DefaultConsumer deliverCallback = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope,
									   AMQP.BasicProperties properties, byte[] body) throws IOException {
				System.out.println(new String(body, "UTF-8"));

			}
		};
		channel.basicConsume("testQueue1",true, deliverCallback);
	}
}

 

public class Recv2 {

	public static void main(String[] args) throws Exception{
		Connection connection = ConnectionUtil.getConnection();
		final Channel channel = connection.createChannel();
		DefaultConsumer deliverCallback = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope,
									   AMQP.BasicProperties properties, byte[] body) throws IOException {
				System.out.println(new String(body, "UTF-8"));

			}
		};
		channel.basicConsume("testQueue2",true, deliverCallback);
	}
}
public class Recv3 {

	public static void main(String[] args) throws Exception{
		Connection connection = ConnectionUtil.getConnection();
		final Channel channel = connection.createChannel();
		DefaultConsumer deliverCallback = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope,
									   AMQP.BasicProperties properties, byte[] body) throws IOException {
				System.out.println(new String(body, "UTF-8"));

			}
		};
		channel.basicConsume("testQueue3",true, deliverCallback);
	}
}

 2.fanout

這種類型的交換機路由規則很簡單,只要跟這種交換機綁定的隊列,交換機就會把消息發送到隊列

public class Send {

	public static void main(String[] args) throws Exception{
		//獲取連接
		Connection connection = ConnectionUtil.getConnection();

		Channel channel = connection.createChannel();
		//聲明隊列
		channel.queueDeclare("testQueue1",false,false,false,null);
		channel.queueDeclare("testQueue2",false,false,false,null);
		channel.queueDeclare("testQueue3",false,false,false,null);
		//聲明交換機
		channel.exchangeDelete(ConnectionUtil.EXCHANGE_NAME);
		channel.exchangeDeclare(ConnectionUtil.EXCHANGE_NAME,BuiltinExchangeType.FANOUT);

		//交換機和隊列綁定
		channel.queueBind("testQueue1",ConnectionUtil.EXCHANGE_NAME,"");
		channel.queueBind("testQueue2",ConnectionUtil.EXCHANGE_NAME,"");
		channel.queueBind("testQueue3",ConnectionUtil.EXCHANGE_NAME,"");

		channel.basicPublish(ConnectionUtil.EXCHANGE_NAME,"",null,"helloWorld".getBytes());

		System.out.println("發送的信息爲:helloWorld");
		channel.close();
		connection.close();

	}
}

可以看到和交換機綁定的三個隊列都有一條消息 

 

3.topic

Topic Exchange – 將路由鍵和某模式進行匹配。此時隊列需要綁定要一個模式上。符號“#”匹配一個或多個詞,符號“*”匹配不多不少一個詞。因此“audit.#”能夠匹配到“audit.irs.corporate”,但是“audit.*” 只會匹配到“audit.irs”

任何發送到Topic Exchange的消息都會被轉發到所有關心RouteKey中指定話題的Queue上

1.這種模式較爲複雜,簡單來說,就是每個隊列都有其關心的主題,所有的消息都帶有一個“標題”(RouteKey),Exchange會將消息轉發到所有關注主題能與

RouteKey模糊匹配的隊列。

2.這種模式需要RouteKey,也需要提前綁定Exchange與Queue。

3.在進行綁定時,要提供一個該隊列關心的主題,如“#.log.#”表示該隊列關心所有涉及log的消息(一個RouteKey爲”MQ.log.error”的消息會被轉發到該隊列)。

4.“#”表示0個或若干個關鍵字,“*”表示一個關鍵字。如“log.*”能與“log.warn”匹配,無法與“log.warn.timeout”匹配;但是“log.#”能與上述兩者匹配。

5.同樣,如果Exchange沒有發現能夠與RouteKey匹配的Queue,則會拋棄此消息。

public class Send {

	public static void main(String[] args) throws Exception{
		//獲取連接
		Connection connection = ConnectionUtil.getConnection();

		Channel channel = connection.createChannel();
		//聲明隊列
		channel.queueDeclare("testQueue1",false,false,false,null);
		channel.queueDeclare("testQueue2",false,false,false,null);
		channel.queueDeclare("testQueue3",false,false,false,null);
		//聲明交換機
		channel.exchangeDelete(ConnectionUtil.EXCHANGE_NAME);
		channel.exchangeDeclare(ConnectionUtil.EXCHANGE_NAME,BuiltinExchangeType.TOPIC);

		//交換機和隊列綁定
		channel.queueBind("testQueue1",ConnectionUtil.EXCHANGE_NAME,"info.*");
		channel.queueBind("testQueue2",ConnectionUtil.EXCHANGE_NAME,"warning.*");
		channel.queueBind("testQueue3",ConnectionUtil.EXCHANGE_NAME,"error.*");

		channel.basicPublish(ConnectionUtil.EXCHANGE_NAME,"info.user",null,"helloWorld".getBytes());

		System.out.println("發送的信息爲:helloWorld");
		channel.close();
		connection.close();

	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章