作者:woshishuia小姐 | 来源:互联网 | 2023-08-25 14:36
三种路由模式rabbitMq有三种交换机路由模式https:my.oschina.nethuangcongmin12blog885345任何发送到TopicExchange的消息
三种路由模式
rabbitMq有三种交换机路由模式 https://my.oschina.net/huangcongmin12/blog/885345
任何发送到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,则会抛弃此消息。
数据结构
每一个队列有一个consumer来维护
consumer的数据结构是
queue: 消息
queues:队列
源码
接受消息
private boolean doReceiveAndExecute(BlockingQueueConsumer consumer) throws Throwable { //NOSONARChannel channel = consumer.getChannel();for (int i = 0; i //取出消息出来,consumer是一个封装,对所有连接信息,channel的封装logger.trace("Waiting for message from consumer.");Message message = consumer.nextMessage(this.receiveTimeout);if (message == null) {break;}try {executeListener(channel, message);}catch (ImmediateAcknowledgeAmqpException e) {if (this.logger.isDebugEnabled()) {this.logger.debug("User requested ack for failed delivery: "+ message.getMessageProperties().getDeliveryTag());}break;}catch (Throwable ex) { //NOSONARif (causeChainHasImmediateAcknowledgeAmqpException(ex)) {if (this.logger.isDebugEnabled()) {this.logger.debug("User requested ack for failed delivery: "+ message.getMessageProperties().getDeliveryTag());}break;}if (this.transactionManager != null) {if (this.transactionAttribute.rollbackOn(ex)) {RabbitResourceHolder resourceHolder = (RabbitResourceHolder) TransactionSynchronizationManager.getResource(getConnectionFactory());if (resourceHolder != null) {consumer.clearDeliveryTags();}else {/** If we don't actually have a transaction, we have to roll back* manually. See prepareHolderForRollback().*/consumer.rollbackOnExceptionIfNecessary(ex);}throw ex; // encompassing transaction will handle the rollback.}else {if (this.logger.isDebugEnabled()) {this.logger.debug("No rollback for " + ex);}break;}}else {consumer.rollbackOnExceptionIfNecessary(ex);throw ex;}}}return consumer.commitIfNecessary(isChannelLocallyTransacted(channel));}
consumer处理消息投递
@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)throws IOException {if (logger.isDebugEnabled()) {logger.debug("Storing delivery for consumerTag: '"+ consumerTag + "' with deliveryTag: '" + envelope.getDeliveryTag() + "' in "+ BlockingQueueConsumer.this);}try {if (BlockingQueueConsumer.this.abortStarted > 0) {if (!BlockingQueueConsumer.this.queue.offer(new Delivery(consumerTag, envelope, properties, body),BlockingQueueConsumer.this.shutdownTimeout, TimeUnit.MILLISECONDS)) {RabbitUtils.setPhysicalCloseRequired(getChannel(), true);// Defensive - should never happenBlockingQueueConsumer.this.queue.clear();getChannel().basicNack(envelope.getDeliveryTag(), true, true);getChannel().basicCancel(consumerTag);try {getChannel().close();}catch (TimeoutException e) {// no-op}}}else {BlockingQueueConsumer.this.queue.put(new Delivery(consumerTag, envelope, properties, body));}}catch (InterruptedException e) {Thread.currentThread().interrupt();}}