Rabbitmq使用小结

1. 神奇的现象

今天发布版本时,重启了整个rabbitmq集群,发现有的模块和rabbitmq中的exchange解绑了。而且启动时并没有自动绑定。有个同事有十几个queue,全部手动绑定了一下。导致上线时间多花了10多分钟。现象描述:

  • queue和exchange自动解绑
  • 启动时没有自动绑定queue

 

2. 背后的故事

rabbitmq我们采用的是fanout exchange模式,这样一个应用发消息,其他模块感兴趣的可以自己创建queue去绑定监听。现在用户产生一条数据,后面的很多服务比如说Feed,搜索,计数,行为记录,系统通知等都采用了异步处理的方式。也说明了我们整个架构依赖于Rabbitmq。

 

  • rabbitmq的exchange,queue有durable,非durable两种。我们自动解绑的原因就是因为exchange设置的是非durable的,导致每次重启后,绑定都失效了。但是发送方又自动创建了exchange,而queue是durable的,现象就是她们之间失去了绑定。
  • 用rabbitmq开发时,java端用了spring amqp,ruby端用了bunny。我们就说spring的amqp吧,在rabbitmq使用中有以下几点需要注意:
  1. 刚才也说到,有的项目没有自动绑定queue,原因有两个(1)没有配置amqpadmin,(2)lazy-init设置的是true。spring的amqpadmin在系统启动时会自动get出exchange,queue的bean,将她们在rabbitmq中注册。
       <rabbit:admin id="amqpAdmin" connection-factory="connectionFactory" />

 

     2. Spring在这里也使用了它那万能的template模式,connectionfactory用的是CachingConnectionFactory,cachingconnectionfactory的cachingsize要注意他不是连接数的大小,是channel的个数,channel相当于session的概念,一个connection可以创建多个channel。cachingconnectionfactory用aop的方式用一个双向链表pool了cachesize的channel。我们在它的基础上用commons-pool开发了一个连接池。不过cachingconnectionfactory性能已经够好了。

 

     3. 对于监听方Spring又使用了他那万能的simplelistenercontainer,估计还是轮询不断receive消息。concurrentconsumer可以配多个线程并发收消息,假设是收到消息的处理逻辑时间较长。可以多线程并发的处理,提高处理效率。  

 

 

3. 真实的世界

  •    真实使用时,rabbitmq如果出问题了,那我们整个系统的数据就不同步了。甚至一些主要功能都会无法正常试用。所以queue要处理好单点失败的问题。

         (1)rabbitmq我们采用的是active/active的模式,一些重要的queue可以采用mirror的方式复制。保证高可用。如果不是mirror queue的方式,就有可能会丢失数据。如果用了mirror queue,即使是ram node也会在磁盘里写入数据。

         (2)接收方负载均衡,接收方我们可以监听集群中任意rabbitmq,写入的服务器会平均的把消息deliver给其他node。两个node测试下来,各处理了50%。其他node其实也相当于一个listener。这个逻辑还需要多测试,比如一台多配一些listener,处理的快一点,试试是否还是绝对平均。

 

         (3)我们会发现在配置写入的client端时,我们还是指定的其中的某台rabbitmq服务器用于写入,就像主库一样。但是它有可能会是单点失败的。这时我们往往是在前面加个HAProxy或者LVS来解决问题。这样写入就做了负载均衡,也解决了failover的问题。HAProxy通过keeplive的方式保持高可用。

 

  •     很多人喜欢用代码来自动创建exchange,queue,binding,我其实不太喜欢这样,我觉得这些就像契约一样,应该预先商定好,创建好。(1)大家配的不是相同的,(2)可能会乱配,要求durable的,有的人配的不是durable,(3)应该是exchange,有的人用在了queue上。还是线下陪比较稳妥。

你可能感兴趣的:(rabbitmq)