不管是官方还是能搜到的文章,使用MQ的基本思路都是这样:

        static void Main(string[] args)
{
//通过工厂建立连接
using (IConnection connection = factory.CreateConnection())
{
//通过连接创建会话,这里还有可能是Channel
using (ISession session = connection.CreateSession())
{
while (true)或者一个for 循环发送100万个消息
{
//创建一个msg
string message = "Hello World";
//发送
xxx.Send(message);
}
}
}
}

那么问题来了:

这个"Hello World"怎么传进去?如何对外提供服务?

然后会发现有些客户端SDK是这么处理的:

       public static void SendMsg()
{
MQAPI("Hello World");
} private static void MQAPI(string message)
{
IConnectionFactory factory;
//通过工厂建立连接
using (IConnection connection = factory.CreateConnection())
{
//通过连接创建Session会话
using (ISession session = connection.CreateSession())
{
//创建一个msg
string message = message; //发送
xxx.Send(message);
}
}
}

去公开一个接口调用SendMsg吧。

看起来似乎解决了这个问题,但是实际测试下会吓一跳:后者的QPS仅为前者的40%左右,这是不能容忍的。

那么接下来大家肯定会从SQLConnection的经验得出一个解决方案:

将connection抽出来,那么session或者Channel呢?

我们通过研究RabbitMQ的链接客户端和服务端链接过程(这个过程较为复杂,写了几遍都删了)得出如下结论:

  1. 先建立Connection链接,这个链接就是一个TCP链接,Producer和Consumer都是通过TCP连接到RabbitMQ Server 的。经过connection.start -> connection.start_ok -> connection.secure -> connection.secure_ok -> connection.tune -> connection.tune_ok(这时rabbit会建立一个心跳进程)-> connection.open -> connection.open_ok后,客户端与rabbit之间就认为已经建立 了连接。
  2. 再建立Channels: 虚拟连接。它建立在上述的TCP连接中。数据流动都是在Channel中进行的。也就是说,一般情况是程序起始建立TCP连接,第二步就是建立这个Channel。可以多路复用,1~65535为可用的channel编号,channel的索引不为0时(0是全局链接),rabbit认为这些数据从属于某个 channel。如果该channel进程不 存在,则会创建一个channel进程,并由此进程负责该channel上 的所有数据。根据AMQP协议,经过channel.open -> channel.open_ok后,客户端就可以开始在该channel上发送数据了。

那么,建立和关闭TCP连接是有代价的,频繁的建立关闭TCP连接对于系统的性能有很大的影响,而且TCP的连接数也有限制,这也限制了系统处理 高并发的能力。但是,在TCP连接中建立 Channel是没有上述代价的。对于Producer或者Consumer来说,可以并发的使用多个 Channel进行 Publish或者Receive。

然而我研究了RabbitMQ.Client代码之后发现其并未维护一个连接池:

                if (AutomaticRecoveryEnabled)
{
var autorecoveringConnection = new AutorecoveringConnection(this, clientProvidedName);
autorecoveringConnection.Init(endpointResolver);
conn = autorecoveringConnection;
}
else
{
IProtocol protocol = Protocols.DefaultProtocol;
conn = protocol.CreateConnection(this, false, endpointResolver.SelectOne(this.CreateFrameHandler), clientProvidedName);
}

只是有一个自动恢复功能,需要设置为true建立长TCP链接,然后根据在请求的时候再创建Channel。

RabbitMQ随笔的更多相关文章

  1. RabbitMQ系列随笔——介绍及安装

    一.RabbitMQ介绍 RabbitMQ是由erlang开发的AMQP(Advanced Message Queuing Protocol)的开源实现.他是高级消息队列协议,是应用层协议的一个开放标 ...

  2. RabbitMQ 应用学习随笔

    1.安装 Rabbit MQ 是建立在强大的Erlang OTP平台上,因此安装RabbitMQ之前要先安装Erlang. erlang:http://www.erlang.org/download. ...

  3. RabbitMQ消息队列随笔

    本文权当各位看官对RabbitMQ的基本概念以及使用场景有了一定的了解,如果你还对它所知甚少或者只是停留在仅仅是听说过,建议你先看看这篇文章,在对RabbitMQ有了基本认识后,我们正式开启我们的Ra ...

  4. RabbitMQ原理与相关操作(二)

    接着 上篇随笔 增加几个概念: RabbitMQ是一个在AMQP(高级消息队列协议)标准基础上完整的,可服用的企业消息系统. AMQP模型的功能组件图(上图摘自 Sophia_tj 的 第2章 AMQ ...

  5. RabbitMQ的安装

    随笔记下Rabbit的环境搭建 1.下载RabbitMQ:RabbitMQ下载地址 Windows下安装 <1>安装Erlang 下载地址:Erlang下载 安装: Erlang安装完成 ...

  6. Java 小记 — RabbitMQ 的实践与思考

    前言 本篇随笔将汇总一些我对消息队列 RabbitMQ 的认识,顺便谈谈其在高并发和秒杀系统中的具体应用. 1. 预备示例 想了下,还是先抛出一个简单示例,随后再根据其具体应用场景进行扩展,我觉得这样 ...

  7. 使用EasyNetQ组件操作RabbitMQ消息队列服务

    RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现,是实现消息队列应用的一个中间件,消息队列中间件是分布式系统中重要的组件,主要解决应用耦合, ...

  8. RabbitMQ入门:认识并安装RabbitMQ(以Windows系统为例)

    最近在学习Spring Cloud,其中消息总线Spring Cloud Bus是必不可少的,但是Spring Cloud Bus目前只支持RabbitMQ和kafka,因此学习RabbitMQ势在必 ...

  9. RabbitMQ入门:总结

    随着上一篇博文的发布,RabbitMQ的基础内容我也学习完了,RabbitMQ入门系列的博客跟着收官了,以后有机会的话再写一些在实战中的应用分享,多谢大家一直以来的支持和认可. RabbitMQ入门系 ...

随机推荐

  1. Nodejs后台管理员登录实例

    思路: 直接访问后台页面时如果无session则跳转到404 当在登录页的表单提交时对数据库进行匹配,匹配成功生成session,否则提示用户名或密码错误 准备页面 :后台首页.登录页.404页, 步 ...

  2. 【转】Intellij IDEA调试功能

    http://www.cnblogs.com/winner-0715/p/5422952.html 先编译好要调试的程序.1.设置断点

  3. java获取文件列表,并按照目录的深度及文件名的拼音的升序排列

    java实现在线浏览zip文件及文件下载 首先用java读出目录或是zip下的所有文件 1KG_20140718_HD/Readme-说明.htm:3.00KB1KG_20140718_HD/一键GH ...

  4. 谈一下Docker与Kubernetes集群的日志和日志管理

    本文的测试环境为CentOS 7.3,Kubernetes集群为1.11.2,安装步骤参见kubeadm安装kubernetes V1.11.1 集群 日志对于我们管理Kubernetes集群及其上的 ...

  5. Asp.Net Core 通过自定义中间件防止图片盗链的实例(转)

    一.原理 要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或 ...

  6. Android GUI之View绘制流程

    在上篇文章中,我们通过跟踪源码,我们了解了Activity.Window.DecorView以及View之间的关系(查看文章:http://www.cnblogs.com/jerehedu/p/460 ...

  7. 【机器学习算法-python实现】採样算法的简单实现

    1.背景     採样算法是机器学习中比較经常使用,也比較easy实现的(出去分层採样).经常使用的採样算法有下面几种(来自百度知道):     一.单纯随机抽样(simple random samp ...

  8. CS模式,客户端页面加载

    public MainForm() { //1.初始化视图 InitializeComponent(); //2.加载程序 this.Load += new System.EventHandler(t ...

  9. 四舍五入函数ROUND(x,y)

    四舍五入函数ROUND(x,y) 参数: x:数据 y:需要保留的小数点位数 ROUND(x,y)函数返回最接近于参数x的数,其值保留到小数点后面y位,若y为负值,则将保留x值到小数点左边y位. my ...

  10. 【Android】解析Android的路径

    目录结构: contents structure [+] 内部路径 外部路径 Assets目录 Android中的路径主要分为内部路径和外部路径. 一.内部路径 常见的内部存储路径有: File f1 ...