Spring RabbitMQ Channel理解

Stella981
• 阅读 998

概述


AMQP协议中,有channel的概念,在RabbitMq中,channel表示逻辑连接或者叫虚拟连接,是棣属于TCP连接的。一个TCP连接里可以创建多个channel,在Rabbit MQ里,消息的发送和接收都是基于channel的。 Spring RabbitMQ 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时指定缓存的模式。

connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL);
connectionFactory.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住了,如下图: Spring RabbitMQ Channel理解 作者也提到,当流量很大的时候,使用CacheMode.CONNECTION的模式,可以提高发送效率。关于这两种模式的性能问题,也可以看一下在stackoverflow的讨论,Spring CachingConnectionFactory limiting channels & causing Thread Blocking;


channel的监控


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

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

如果通道打开操作的速率始终高于通道关闭操作的速率,那就可能发生channel泄露了。如下图: Spring RabbitMQ Channel理解

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


原文链接


Spring RabbitMQ Channel理解

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
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
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这