Spring RabbitMQ Channel理解

概述


AMQP协议中,有channel的概念,在RabbitMq中,channel表示逻辑连接或者叫虚拟连接,是棣属于TCP连接的。一个TCP连接里可以创建多个channel,在Rabbit MQ里,消息的发送和接收都是基于channel的。 collection和channel的关系

有了TCP连接后,还需要channel的原因如下:

  • 创建和销毁TCP连接很耗时;
  • 打开太多TCP连接,耗操作系统资源,并发量大到一定程度,系统的吞吐量会降低;
  • 使用一个collectionchannel的方式,可以提升连接的利用率。

因此采用多个channel多路复用一个TCP连接的方式才比较合理。


channel线程不安全


channel不是线程安全的,线程并发的去访问同一个channel会出问题。这里有几种处理方式:

  1. 全局公用一个channel且使用全局锁,让操作channel排队.这种明显性能是不行的;
  2. 一个线程对应创建一个新的channel,但是要处理好一个连接能支撑的最大channel数量;
  3. 一个线程对应一个channel,但是是从channel池子拿的,不是每次都创建新的.一旦一个线程完成了一个channel的使用,它将返回到池中,从而使该channel可用于另一个线程。

量不大的话,使用第二种方式就可以了。量大的话,建议使用第三种方式,毕竟创建和销毁channel也是耗时耗资源的.在spring amqp中,提供了一个缓存channel的方案。可以在创建CachingConnectionFactory时指定缓存的模式。

1connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL); 2connectionFactory.setChannelCacheSize(25);

上面的两行代码,表示channel共用唯一的一个连接,且缓存了25个channel,注意这里的25个并不是说,这个连接里只能最多创建25个channel,而是说最多缓存25个channel。举个例子,假设并发发送100条消息,在CachingConnectionFactory.CacheMode.CHANNEL模式下,瞬间会创建100个channel的,然后往缓存里放25个channel,当流量下去了,刚刚创建的多余的channel会自动关闭掉的,缓存里只保留25个。

使用这种方式的话,要注意缓存的channel数量,不能太小,不然流量一大,仍然会造成频繁关闭channel的情况。当然我们也不能说有多少并发,就创建多少个channel,还是要限制一下,这个时候可以使用:

connectionFactory.setChannelCheckoutTimeout(1000);

ChannelCheckoutTimeout的值大于0的时候,ChannelCacheSize的值就是最大的channel数量了,一旦从缓存中获取不到channel,等待ChannelCheckoutTimeout毫秒后,如果还是获取不到的,就会抛AmqpTimeoutException 了。

我们也可以自己实现channel pool,但是不太建议怎么做,毕竟spring amqp还是相当成熟的,直接使用就可以了。


CacheMode.CHANNEL模式性能


如上文所述,采用了CacheMode.CHANNEL的模式的话,就是一线程一channel形式,且这些channel共享了同一个连接,也即是共享同一个socket。当并发量一大的时候,可能导致同一时刻,多个线程都想往这个socket上写数据。为了避免这种情况,只能加锁,让拿不到锁的线程block住。在老外写的Using spring-rabbit under high throughput一文中,也提到了这点,并做了压力测试,并发10个线程发送1000000条消息,结果线程被block住了,如下图: 在这里插入图片描述 作者也提到,当流量很大的时候,使用CacheMode.CONNECTION的模式,可以提高发送效率。关于这两种模式的性能问题,也可以看一下在stackoverflow的讨论,Spring CachingConnectionFactory limiting channels & causing Thread Blocking;


channel的监控


RabbitMQ Admin UI提供了一个监控channel的界面,我们主要关注两点:

  • channel有没有可能泄露,打开了channel,却没有关闭channel;
  • 打开channel和关闭channel的速率。

如果通道打开操作的速率始终高于通道关闭操作的速率,那就可能发生channel泄露了。如下图: 在这里插入图片描述

如果打开和关闭channel的速率都很高,也值得观察一下。因为可能是没有缓存channel了。当流量继续增大的时候,可能会出现吞吐量上不去的情况,如下图: 在这里插入图片描述


原文链接


Spring RabbitMQ Channel理解

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )