RabbitMQ之交換器和隊列

    交換器和隊列是MQ中high-level層面的構建模塊,應用程序需確保在使用它們的時候就已經存在了,在使用之前需要先聲明它們。以下源碼是基於spring-amqp-1.7.7.RELEASE.jar的源碼分析

  1. 交換機源碼分析:
public abstract class AbstractExchange extends AbstractDeclarable implements Exchange {
    private final String name;
    private final boolean durable;
    private final boolean autoDelete;
    private final Map<String, Object> arguments;
    private volatile boolean delayed;
    private boolean internal;

    public AbstractExchange(String name) {
        this(name, true, false);
    }

    public AbstractExchange(String name, boolean durable, boolean autoDelete) {
        this(name, durable, autoDelete, (Map)null);
    }

    public AbstractExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments) {
        this.name = name;
        this.durable = durable;
        this.autoDelete = autoDelete;
        if (arguments != null) {
            this.arguments = arguments;
        } else {
            this.arguments = new HashMap();
        }
    }
}

FanoutExchange,DirectExchange和TopicExchange等交換機都繼承AbstractExchange,它們交換機的聲明都最終調用得是AbstractExchange的構造方法,各個參數的含義:

  • name:交換器(交換機)的名稱;
  • durable:設置是否持久化,默認值是true,表示持久化,反之非持久化。持久化可以將交換器存盤,在服務器重啓的時候不會丟失相關信息;
  • autoDelete:設置是否自動刪除,默認值false,表示不自動刪除。自動刪除的前提是至少有一個隊列或者交換器與這個交換器綁定,之後所有與這個交換器綁定的隊列或者交換器都與此解綁。不能理解爲:當與此交換器連接的客戶端都斷開時,RabbitMQ會自動刪除本交換器。
  • arguments:其他一些結構化參數;
  • internal:設置是否是內置的,如果設置爲true,則表示是內置的交換器,客戶端程序無法直接發送消息到這個交換器中,只能通過交換器路由到交換器這種方式。
  1. 隊列源碼分析:
public class Queue extends AbstractDeclarable {
    private final String name;
    private final boolean durable;
    private final boolean exclusive;
    private final boolean autoDelete;
    private final Map<String, Object> arguments;

    public Queue(String name) {
        this(name, true, false, false);
    }

    public Queue(String name, boolean durable) {
        this(name, durable, false, false, (Map)null);
    }

    public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete) {
        this(name, durable, exclusive, autoDelete, (Map)null);
    }

    public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) {
        Assert.notNull(name, "'name' cannot be null");
        this.name = name;
        this.durable = durable;
        this.exclusive = exclusive;
        this.autoDelete = autoDelete;
        this.arguments = arguments;
    }
}

隊列有很多重載的構造方法,但他們底層都調用了最下面的那個,參數分析:

  • name:隊列名稱;
  • durable : 設置是否持久化,默認值爲true表示持久化,持久化的隊列會存盤,在服務器重啓的時候可以保證不丟失相關信息;
  • exclusive:設置是否排他,默認不排他。如果一個隊列被聲明爲排他隊列,該隊列僅對首次聲明它的連接可見,並在連接斷開時自動刪除。這裏需要注意三點:1,排他隊列是基於連接可見的,同一個連接的不同信道是可以同時訪問同一連接創建的排他隊列;2,”首次“是指如果一個連接已經聲明瞭一個排他隊列,其他連接是不允許建立同名的排他隊列的,這個與普通隊列不同;3,即使該隊列是持久化的,一旦連接關閉或者客戶端退出,該排他隊列都會被自動刪除,這種隊列適用於一個客戶端同時發送和讀取消息的應用場景。
  • autoDelete:設置爲是否自動刪除,默認值false,爲true則設置隊列爲自動刪除。自動刪除的前提是:至少有一個消費者連接到這個隊列,之後所有與這個隊列連接的消費者都斷開時,纔會自動刪除。
  • arguments:設置隊列的其他一些參數。
  1. 隊列的綁定
	@Bean
    public Binding bindingSelectOrderExchange(Queue queryByOrderIdQueue, DirectExchange directExchange){
        /**
         * 綁定隊列query.by到指定交換機,並指定路由key
         */
        return BindingBuilder.bind(queryByOrderIdQueue).to(directExchange).with("query.by.orderId");
    }

源碼如下:

public final class BindingBuilder {
    private BindingBuilder() {
    }
	//1,綁定隊列
    public static BindingBuilder.DestinationConfigurer bind(Queue queue) {
        return new BindingBuilder.DestinationConfigurer(queue.getName(), DestinationType.QUEUE);
    }

	public static final class DirectExchangeRoutingKeyConfigurer extends BindingBuilder.AbstractRoutingKeyConfigurer<DirectExchange> {
        private DirectExchangeRoutingKeyConfigurer(BindingBuilder.DestinationConfigurer destination, DirectExchange exchange) {
            super(destination, exchange.getName(), null);
        }
		//2,指定路由key
        public Binding with(String routingKey) {
            return new Binding(this.destination.name, this.destination.type, this.exchange, routingKey, Collections.emptyMap());
        }

        public Binding with(Enum<?> routingKeyEnum) {
            return new Binding(this.destination.name, this.destination.type, this.exchange, routingKeyEnum.toString(), Collections.emptyMap());
        }

        public Binding withQueueName() {
            return new Binding(this.destination.name, this.destination.type, this.exchange, this.destination.name, Collections.emptyMap());
        }
    }

	public static final class DestinationConfigurer {
	        protected final String name;
	        protected final DestinationType type;
	
	        private DestinationConfigurer(String name, DestinationType type) {
	            this.name = name;
	            this.type = type;
	        }
	
	        public Binding to(FanoutExchange exchange) {
	            return new Binding(this.name, this.type, exchange.getName(), "", new HashMap());
	        }
	
	        public BindingBuilder.HeadersExchangeMapConfigurer to(HeadersExchange exchange) {
	            return new BindingBuilder.HeadersExchangeMapConfigurer(this, exchange);
	        }
			//3,綁定到DirectExchange交換機
	        public BindingBuilder.DirectExchangeRoutingKeyConfigurer to(DirectExchange exchange) {
	            return new BindingBuilder.DirectExchangeRoutingKeyConfigurer(this, exchange);
	        }
	
	        public BindingBuilder.TopicExchangeRoutingKeyConfigurer to(TopicExchange exchange) {
	            return new BindingBuilder.TopicExchangeRoutingKeyConfigurer(this, exchange);
	        }
	
	        public BindingBuilder.GenericExchangeRoutingKeyConfigurer to(Exchange exchange) {
	            return new BindingBuilder.GenericExchangeRoutingKeyConfigurer(this, exchange);
	        }
	    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章