这篇文章内容会很短,主要是想给大家分享下我最近在做一个简单的rabbitmq客户端类库的封装的经验总结,说是简单其实一点都不简单。为了节省时间我主要按照Library的执行顺序来介绍,在你看来这里仅仅是一个简单的经验总结,但是在我看来这些经验只有在你真正的封装rabbitmq客户端库的时候且将你的客户端安全稳定的发布上线后才会真的发现这些问题。

比如你的库只是链接单个Node的时候和链接高可用集群的HAProxy时候是完全两回事。当你未能在你的库里使用反向注入LOG接口的时候一旦在线上发生网络解析和序列化等一系列在线问题时候你是多么无能为力。当你使用同步循环获取队列消息的时候一旦发生异常你的链接就会断掉等等这些细节。我总结了我在编写这个library的时候慢慢稳定下来的过程和经验。至少目前来看网络上的文章,当然我是指.NET/C#方面的,都没有讲到这些问题,大部分的文章都是简单的介绍了一个最最基本的使用和最最基本的demo而已,达不到企业级使用的要求。在这个过程中,感谢我的团队和给过我指导的同事,让我明白了一些技术道理。

好东西不能石沉大海,尤其是.NET领域更需要这样的东西来填补这一空缺。废话不多说了,进入主题,那些编写框架和组件的大道理这里就不讲了,我只说重点。

1.发送链接、通道和接受链接、通道要关注点分离

就是说你的接受Channel和发送的Channel要分离开,如果不分开会出现偶发性的消息串掉的错误,我这里现在没有环境无法重现截图。我是在做压力测试的时候,用了一个Channel的时候Debug抛出来的异常。如果你有洁癖建议把IConnection也分离开。这样不容易出错,就算出错排错也会很容易。

(图1:分开接受和发送的IConnection、Channel)

还有一点,不要将这些对象直接散落在直接使用的Client类中,要建立起一个使用上下文,就算你暴露在外面的是一个具体的类但是那个类也是一个空壳子。

2.客户端发送消息的时候要标记上消息的持久化状态

我们可以在创建队列的时候设置此队列是持久化的,但是队列中的消息要在我们发送某个消息的时候打上需要持久化的状态标记。

(图2:标记此消息是需要持久化的)

3.要在监听的线程入口后加try{}catch{}

(图1:在线程内部方法中加try{}catch{})

这个点很多做封装的人会容易忽视掉,我这里补充下为了保持这个文章的完整性。

其实在我之前的“ .NET应用架构设计—服务端开发多线程使用小结(多线程使用常识) ”一文中有讲到过。

这个时候你的try{}catch{}其实是不会捕获到任何ListenInit方法中的异常的,因为他在另外一个线程上下文中执行的。具体原理这里就不解释了。但是可以很容易的理解就是,你这个方法一旦执行就会立马返回了。

4. 初始化的监听连接的时候要订阅Shutdown事件记录下LOG

(图4:监听Shutdown事件,记录下LOG便于排查和监管服务的稳定性)

5. 要在内部定义一个LOG反向注入接口

(图5:组件内部的LOG接口)

此接口就是你内部用来将信息传输出去的渠道,而且这个渠道是活的,有各个应用系统决定怎么记录。

简单处理你还需要一个LOG接口服务定位器对象,要不然你拿不到这个接口实例。

(图6:LOG location对象)

6. 千万不要使用while(true)接受消息

如果我们是使用死循环的方式在接受消息,那么一旦当你的接受消息的程序出现异常那么你的while直接就会跳出,你的链接可能是还链接在服务器上但是你的channel已经断开,说白了你的消息是不会接受到的,而且这样的开发方法很不稳定也不优雅。我们可以使用面向事件的消费者来接受消息。

(图7:使用Eventing类型的消费者接受消息)

7.设置一次只接受一个消息,而不是直接LOCK住所有的队列消息

默认情况下,一个队列里不管多少消息当你一个TCP连接打上去之后会LOCK住所有的消息,也就是说一个连接彻底占用了所有的消息,此时消息不会被其他集群的机器消费。

(图8:一次只取一个消息进行消费)

但是如果你对消息的处理的前后顺序有要求就不能这么做,你需要独立注册一个队列,然后将这样的一此只消费一个消息配置话。

8.自动重新连接,不需要手动处理自动连接

(图9:创建出一个会自动重连的Connection对象)

9.心跳超时时间(集群、高可用部署时至关重要的设置)

(图10:设置心跳超时时间)

如果你连接单台节点的时候不设置这个值是没问题的,但是如果你连接的是类似HAProxy虚拟节点的时候就会出现TCP被断开的可能性。如果你不设置这个心跳超时时间,它默认是不进行心跳保持的,就会出现网络中的某个设置断开空闲的TCP连接资源。就这个问题一直搞的我们的团队到第二天两点钟。大家要记住这个点。

10.消费失败的消息要重新放入队列

(图11:重新放入队列,推送给其他消费着)

总结:

最后,我是基于Rabbitmq.Client 版本3.5.3.0的基础上开发的,这个大家要注意。版本不一样会有一定的差异性。希望此文对大家在使用rabbitmq的同志有一点帮助,谢谢。

封装 RabbitMQ.NET的更多相关文章

  1. 封装RabbitMQ.NET Library 的一点经验总结

    这篇文章内容会很短,主要是想给大家分享下我最近在做一个简单的rabbitmq客户端类库的封装的经验总结,说是简单其实一点都不简单.为了节省时间我主要按照Library的执行顺序来介绍,在你看来这里仅仅 ...

  2. 封装RabbitMQ.NET Library 的一点经验总结 转载

    这篇文章内容会很短,主要是想给大家分享下我最近在做一个简单的rabbitmq客户端类库的封装的经验总结,说是简单其实一点都不简单.为了节省时间我主要按照Library的执行顺序来介绍,在你看来这里仅仅 ...

  3. .net平台的rabbitmq使用封装

    前言 RabbitMq大家再熟悉不过,这篇文章主要整对rabbitmq学习后封装RabbitMQ.Client的一个分享.文章最后,我会把封装组件和demo奉上. Rabbitmq的运作 从下图可以看 ...

  4. RabbitMQ 高可用集群搭建及电商平台使用经验总结

    面向EDA(事件驱动架构)的方式来设计你的消息 AMQP routing key的设计 RabbitMQ cluster搭建 Mirror queue policy设置 两个不错的RabbitMQ p ...

  5. 队列工厂之RabbitMQ

    本次和大家分享的是RabbitMQ队列的用法,前一篇文章队列工厂之(MSMQ)中在描述的时候已经搭建了简单工厂,因此本章内容是在其之上扩充的子项不再过多讲解工厂的代码了:RabbitMQ应该是现在互联 ...

  6. C# RabbitMQ

    鉴于本人很懒,发现好的文章一般都直接copy,本文大体摘自:https://www.cnblogs.com/MuNet/p/8546192.html 1.引言 RabbitMQ——Rabbit Mes ...

  7. spring rabbitmq集成

    pom.xml加 <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-clien ...

  8. RabbitMQ 高可用集群搭建

    面向EDA(事件驱动架构)的方式来设计你的消息 AMQP routing key的设计 RabbitMQ cluster搭建 Mirror queue policy设置 两个不错的RabbitMQ p ...

  9. net平台的rabbitmq

    net平台的rabbitmq使用封装 前言 RabbitMq大家再熟悉不过,这篇文章主要整对rabbitmq学习后封装RabbitMQ.Client的一个分享.文章最后,我会把封装组件和demo奉上. ...

随机推荐

  1. Linux mongodb安装、启动、运行

    1.下载     wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.2.4.tgz     2.安装     tar -zxvf  ...

  2. ABAP术语-HTML

    HTML 原文:http://www.cnblogs.com/qiangsheng/archive/2008/02/19/1073298.html Hypertext Markup Language( ...

  3. 针对angularjs下拉菜单第一个为空白问题处理

          angularjs 的select的option是通过循环造成的,循环的方式可能有  ng-option  或 者 <option  ng-repeat></option ...

  4. React中的全选反选问题

    全选反选问题 1.在state里维护一个数组,例如showArr:[] 2.绑定点击事件的时候将当前这个当选按钮的index加进来 <span className='arrow' onClick ...

  5. 安装docker和更改docker镜像下载目录

    centos6.x系列: yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm yum inst ...

  6. MySQL必会

    SQL语言对大小写不敏感,但一般使用大.1.创建数据库 CREATE DATABASE test; 2.授予权限 CRANT ALL ON test.* to user(s); 3.使用指定数据库 U ...

  7. APSchedule的练习使用

    1 简介 APScheduler的全称是Advanced Python Scheduler.它是一个轻量级的 Python 定时任务调度框架.APScheduler 支持三种调度任务:固定时间间隔,固 ...

  8. python应用:爬虫实例(静态网页)

    爬取起点中文网某本小说实例: # -*-coding:utf8-*- import requests import urllib import urllib2 from bs4 import Beau ...

  9. 多线程编程之Apue3rd_Chapter15.10之posix信号量

    看了APUE的chapter15,只重点看了15.10,学习了posix信号量.Posix信号量比起xsi信号量的优点是性能更好,在Linux3.2.0平台上性能提升很大.其中命名信号量使用方法如下. ...

  10. (数据科学学习手札34)多层感知机原理详解&Python与R实现

    一.简介 机器学习分为很多个领域,其中的连接主义指的就是以神经元(neuron)为基本结构的各式各样的神经网络,规范的定义是:由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系 ...