标签:服务端 nec sdk dna this rabbitmq 研究 经验 else
不管是官方还是能搜到的文章,使用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的链接客户端和服务端链接过程(这个过程较为复杂,写了几遍都删了)得出如下结论:
那么,建立和关闭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。
标签:服务端 nec sdk dna this rabbitmq 研究 经验 else
原文地址:http://www.cnblogs.com/madyina/p/6322689.html