can declaratively obtain messages from the queue by polling the API, or passively from the queue by subscribing. Consuming news,
I recently read the relevant source code of the java-based client, and made a simple analysis.
The programming model pseudocode is as follows:
ConnectionFactory factory = new ConnectionFactory();
Connection conn = factory.newConnection();
Channel channel=conn.createChannel();
To create a Connection, you need to specify the physical address and port of MQ, which is a socket tcp physical connection, and Channel is a logical concept that supports the creation of multiple MQ channels on tcp connections.
The following are two consumption methods based on channels.
1. Subscribe subscription method
boolean autoAck = false; channel.basicConsume(queueName, autoAck, "myConsumerTag", new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String routingKey = envelope.getRoutingKey(); String contentType = properties.contentType; long deliveryTag = envelope.getDeliveryTag(); // (process the message components here ...) channel.basicAck(deliveryTag, false); } });
The subscription method is actually to register the consumer with the queue, and send the message of registering the consumer to the queue server through rpc. After receiving the message, the rabbitMQ Server judges that it is a subscription message according to the content type of the message,
so that when there is a message in the queue in MQ, it will The message is automatically sent out through the socket (long connection) channel.
See methods in ChannelN
public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, final Consumer callback) throws IOException { ...... rpc((Method) new Basic.Consume.Builder() .queue(queue) .consumerTag (consumerTag) .noLocal(noLocal) .noAck (autoAck) .exclusive(exclusive) .arguments(arguments) .build(), k); try { return k.getReply (); } catch(ShutdownSignalException ex) { throw wrap(ex); } }
The process of the Consumer receiving the message:
After the Connection is created, the MainLoop background thread will be started, the data packet (Frame) will be obtained from the socket (FrameHandler) in a loop, and the channel.handleFrame(Frame frame) will be called to process the message.
public void handleFrame(Frame frame) throws IOException { AMQCommand command = _command; if (command. handleFrame(frame)) { // protocol assemble the message _command = new AMQCommand(); // prepare for the next one handleCompleteInboundCommand(command);//Processing message consumption } } ChannelN.handleCompleteInboundCommand ---ChannelN.processAsync ----dispatcher.handleDelivery ---QueueingConsumer.handleDelivery ---this._queue.add(new Delivery(envelope, properties, body));//The message is finally put into the queue
Each Consumer has a BlockQueue, which is used to buffer the messages obtained from the socket.
Next, the Consumer object can call the api to obtain messages from the _queue cached by the client in turn and consume them. See QueueingConsumer.nextDelivery()
For this long connection method, the heartbeat function is not seen to prevent long connection. The connection fails due to network and other reasons.
2. The poll API method
ChannelN:
GetResponse basicGet(String queue, boolean autoAck)
This method is relatively simple, and directly obtains the messages in the queue from the MQ Server side through RPC
Reference : http://blog.csdn. net/liyantianmin/article/details/46696029