Queue.declare is the application queue, first to the queue masterpiece processing, if the queue name is not specified randomly generated one, and then query whether the database queue has been created, if created, will request the queue to return
Handle_method (# ' queue.declare ' {queue =Queuenamebin, passive=false, durable=Durabledeclare, exclusive=Exclusivedeclare, Auto_delete=Autodelete, nowait=NoWait, Arguments= Args} =Declare, _, state= #ch {Virtual_host =Vhostpath, Conn_pid=Connpid, Queue_collector_pid= Collectorpid})Owner= CaseExclusivedeclare of true-Connpid; false-NoneEnd, durable= DurabledeclareAndAlso notExclusivedeclare, Actualnamebin= CaseQueuenamebin of<<>>rabbit_guid:binary (Rabbit_guid:gen_secure (),"Amq.gen"); Other-Check_name (' queue '), other)End, QueueName=rabbit_misc:r (Vhostpath, queue, Actualnamebin), check_configure_permitted (QueueName, state), percent find if the queue already exists CaseRabbit_amqqueue:with (QueueName, Fun(Q) OK =rabbit_amqqueue:assert_equivalence (Q, Durable, Autodelete, Args, Owner), Maybe_stat (NoWait, Q)End) of{OK, Messagecount, consumercount}-Return_queue_declare_ok (QueueName, NoWait, Messagecount, Consumercoun T, state); {error, Not_found}-Dlxkey= << "X-dead-letter-exchange" >>, CaseRabbit_misc:r_arg (Vhostpath, Exchange, Args, Dlxkey) ofundefined-OK; {error, {invalid_type, type}}-precondition_failed ("Invalid type ' ~s ' for arg ' ~s ' in ~s", [Type, Dlxkey, Rabbit_misc:rs (queuename)]); DLX-check_read_permitted (QueueName, State), check_write_permitted (DLX, state), OKEnd, CaseRabbit_amqqueue:declare (queuename, Durable, Autodelete, Args, Owner) of{new, #amqqueue {pid= Qpid}}%%We need to notify the reader within the channel %%process So, we can be sure there is no %%outstanding exclusive queues being declared as %%The connection shuts down.OK = CaseOwner ofNone-OK; _ -Rabbit_queue_collector:register (Collectorpid, Qpid) End, Return_queue_declare_ok (QueueName, NoWait,0, 0, state); {Existing, _q}-%%must has been created between the stat and the %%declare. Loop around again. Handle_method (Declare, none, state); {Absent, Q, Reason}-rabbit_misc:absent (Q, Reason); {owner_died, _q}-%%presumably our own days is numbered since the %%connection has died. Pretend the queue exists though, %%just so nothing fails.RETURN_QUEUE_DECLARE_OK (queuename, NoWait, 0, 0, State)End; {error, {absent, Q, Reason}}-rabbit_misc:absent (Q, Reason)End;
Rabbit_amqqueue.erl
where node () is to indicate the location of the master queue, which is the node that receives the request queue message
-
Select the primary node and send a message to the master node to create the queue process
Declare (queuename, durable, Autodelete, Args, Owner, Node)OK=check_declare_arguments (QueueName, Args), Q=Rabbit_queue_decorator:set (Rabbit_policy:set (#amqqueue {name=queuename, durable=Durable, Auto_delete=autodelete, Arguments=Args, Exclusive_owner=Owner, PID=None, Slave_pids=[], Sync_slave_pids=[], recoverable_slaves=[], Gm_pids=[], State=Live}), Node=Rabbit_mirror_queue_misc:initial_queue_node (Q, node), Gen_server2:call (rabbit_amqqueue_sup_sup:start_queue _process (Node, Q, declare), {init, new}, Infinity).
Rabbit_amqqueue_sup.erl
When you start Rabbit_amqp_process, Supervisor uses the maker to flag whether this process is first started, to differentiate between restarting the process and doing different things.
Start_link (Q, StartMode)%%What is the meaning of the existence of marker? Mark whether for the first startMarker = Spawn_link ( Fun()ReceiveStop-OKEnd End), Childspec={rabbit_amqqueue, {rabbit_prequeue, Start_link, [Q, StartMode, Marker]}, intrinsic, ?max_wait, worker, [Rabbit_amqqueue_process, Rabbit_mirror_queue_slave] }, {OK, suppid}= Supervisor2:start_link (?MODULE, []), {OK, qpid}=Supervisor2:start_child (Suppid, Childspec), unlink (Marker), Marker!stop, {OK, suppid, qpid}.
After that, the master node starts the Rabbit_amqp_process, uses the coordinator to complete the data Synchronization (GM), and the standby node initiates the Rabbit_mirror_queue_slave process, which uses the GM behaviour, So the process data can be synchronized with the Coordinator, and the state of the MQ nodes remains consistent.
Obtain the GM through coordinator to complete the reliable synchronization, and then obtain the standby node in the standby node to increase the mirror queue
INIT_WITH_EXISTING_BQ (Q = #amqqueue {name = QName}, BQ, BQS){OK, CPid}=Rabbit_mirror_queue_coordinator:start_link (Q, Undefined, sender_death_fun (), Depth_fun ()), GM =RABBIT_MIRROR_QUEUE_COORDINATOR:GET_GM (CPid), self=Self (), OK=Rabbit_misc:execute_mnesia_transaction ( Fun()[Q1= #amqqueue {Gm_pids =Gmpids}] =Mnesia:read ({rabbit_queue, QName}), OK=Rabbit_amqqueue:store_queue (Q1#amqqueue{gm_pids= [{GM, self} |Gmpids], state=Live}) End),
{_mnode, snodes} = Rabbit_mirror_queue_misc:suggested_queue_nodes (Q),
Add the mirror queue on all the standby nodes, that is, create the standby queue process
rabbit_mirror_queue_misc:add_mirrors (QName, Snodes, sync), #state {name=QName, GM=GM, Coordinator=CPid, Backing_queue=BQ, Backing_queue_state=BQS, Seen_status=dict:new (), confirmed=[], Known_senders=sets:new ()}.add_mirrors (QName, Nodes, SyncMode)-[Add_mirror (QName, Node, SyncMode)|| Node <-Nodes], OK. Add_mirror (QName, Mirrornode, SyncMode)- CaseRabbit_amqqueue:lookup (QName) of{OK, Q}-Rabbit_misc:with_exit_handler (Rabbit_misc:const (OK), Fun()SPid=rabbit_amqqueue_sup_sup:start_queue_process (Mirrornode, Q, slave), Log_info (QName,"Adding Mirror on node ~p: ~p~n", [Mirrornode, spid]), Rabbit_mirror_queue_slave:go (spid, syncmod e)End); {error, Not_found}= EEEnd.
Non-completion to be continued
The Queue.declare of Rabbitmq method