2013年7月30日星期二

[Erlang 0079] RabbitMQ 初探

  最近在项目中实践RabbitMQ,比较幸运现在除了官方网站,还有一本非常棒的书可以读:RabbitMQ in Action;这本书目前还没有中文版或者影印版,但是从网上很容易找到PDF版本和epub mobi的版本.RabbitMQ上有关于这本书的介绍文章.从本文开始我会陆续把学习实践过程中的收获记录分享出来.

What is RabbitMQ?


What for?

    从概念上讲,RabbitMQ解决的是应用程序之间互联(connect)和规模(scale)的问题,消息发送和接收是隔离,发送方不知道消息最终由谁接收,接收方也不必关心消息是谁步发出的;发送和接收是隔离的,消息本质上就是异步的.这种隔离也就解耦了应用程序之间的依赖.RabbitMQ的角色就是应用程序中间的路由器.
   规模(scale),应用程序解除了相互依赖之后从业务层面更容易做扩展,而Erlang的先天优势让代码层面的开发也更容易.

Why RabbitMQ?

  摘录两段吧,第一段来自<RabbitMQ in Action>,第二段来自那篇很有名的<Rabbits and warrens>(后面我们还会提到它):

 [第一段]
   Today, RabbitMQ isn’t the only game in town for open messaging. Options like ActiveMQ, ZeroMQ, and Apache Qpid all providing different open source approaches to message queuing. The question is, why do we think you should pick RabbitMQ? 
  •     Except for Qpid, RabbitMQ is the only broker implementing the AMQP open standard.
  •     Clustering is ridiculously simple on RabbitMQ because of Erlang. 
  •     Your mileage may vary, but we’ve found RabbitMQ to be far more reliable and crash resistant than its competitors. 
  •     Perhaps the most important reason is that RabbitMQ is incredibly easy to install and use. Whether you need a simple one-node setup for your workstation, or a seven server cluster to power your web infrastructure, RabbitMQ can be up and running in about 30 minutes. With that in mind, it’s about time we fired up the little critter.

[第二段]
  Cutting to the chase, over the last 4 years there have been no shortage of open-source message queueing servers written. Most of them are one-offs by folks like LiveJournal to scratch a particular itch. Yeah, they don’t really care what kind of messages they carry, but their design parameters are usually creator-specific (and message persistence after a crash usually isn’t one of them). However, there are three in-particular, that are designed to be highly flexible message queues for their own sake:
Apache ActiveMQ gets the most press, but it appears to have some issues not losing messages. Next.
ZeroMQ and RabbitMQ both support an open messaging protocol called AMQP. The advantage to AMQP is that it’s designed to be a highly-robust and open alternative to the two commercial message queues out there (IBM and Tibco). Muy bueno. However, ZeroMQ doesn’t support message persistence across crashes reboots. No muy bueno. That leaves us with RabbitMQ. (That being said if you don’t need persistence ZeroMQ is pretty darn interesting…incredibly low latency and flexible topologies).

Why Erlang?

   
 RabbitMQ的设计目标是实现开源版本的AMQP,在RabbitMQ在设计之初,两位设计者对于使用Erlang能否达到预期目标提出了三个关键问题:
  1. Would large financial institutions care whether their messaging broker was written in Erlang? 
  2. Was Erlang really a good choice for writing an AMQP server? 
  3. If it was written in Erlang, would that slow down adoption in the open source community?
    即:大金融机构是否在意选择Erlang作为消息broker的开发语言;Erlang是否是开发AMQP服务的合适之选;使用Erlang,开源社区是否能够快速的接受.这三个问题的解答很有意思,首先金融公司表示他们不在意用什么语言开发只要能帮助他们减少集成成本即可;第二个问题Erlang Solutions公司的Francesco Cesarini (这位就是著名的袋鼠书的作者之一)给出了的解答:他分析了AMQP的协议,协议规格说明里面描述的架构遍布电话交换机系统,而Erlang就是起源于电信行业(点击维基百科了解Erlang),是针对电信领域的做的设计,这个在Joe Armstrong的论文中也有详细的背景介绍,所以Erlang几乎是构建AMQP Broker的不二之选.
   最后一个问题的验证需要相当长的时间,这个已经由另外一个产品来验证了:ejabberd.ejabberd实现了即时消息通信协议XMPP协议,XMPP(Extensible Messaging and Presence Protocol).ejabberd被广泛使用,并没有负面的消息爆出.所以第三个问题也侧面得到了回答.
   其实这里还可以补充两条Erlang的优势:相比其他语言构建集群简单,崩溃恢复容易.这两点可以说是Erlang与生俱来的优势.

Who Use MQ

 
  列举几个使用消息队列的产品(不一定是使用RabbitMQ哦),slideshare上的信息更多一些,可惜被ping了,这里只罗列几个国内的:
 
  首先必须是淘宝,淘宝数据库研发组的资料共享太给力了: http://mysql.taobao.org/index.php/Rabbitmq
  • 虎扑网的分享

    InfoQ:为什么选择了RabbitMQ作为消息服务器?我们知道RabbitMQ是ERLang语言编写了,在实际使用的过程中是否对RabbitMQ进行了集群,是否需要进行扩展开发?如果需要扩展开发,你们采用了哪种语言?我们知道RabbitMQ支持多种语言..
    洪涛:其实我们对消息队列的需求还是比较高的,一共有5点:一是能够提供多种消息分法的规则以匹配我们不同的业务类型,二是性能要高,三是需要支持多种语言的类库以便做接入,四是提供持久化,五是需要在未来支持集群。而同时满足这几个条件的成熟的消息队列系统其实并不多,RabbitMQ是其中之一。另一个原因是我在之前公司工作时有一位来自乌拉圭的同事对RabbitMQ很有研究,当时经常和他讨论消息队列方面的问题,所以在众多消息队列中,对RabbitMQ比较熟悉,也对它比较认可,使用它作为消息队列自然也就不奇怪了。补充一句,这位同事叫Alvaro Videla,他是市面上唯一一本RabbitMQ方面的书《RabbitMQ in Action》的作者之一,对消息队列很有研究,我的很多经验都来自和他的交流。
    消息队列能够将业务逻辑解耦,调用方只需要下达命令而不用等待整个逻辑执行完毕。除此之外消息队列也可以抑制性能波峰的产生,在瞬时业务增长产生时保持性能曲线的平滑。

How to Install


   RabbitMQ的安装非常简单,下载源码包之后编译即可,很多脚本都可以在scripts文件夹里面找到,简单给出一个在centos环境下的安装示例:
 yum install libxslt python zip unzip nc -y
 wget http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.7/rabbitmq-server-2.8.7.tar.gz
 tar xfvz rabbitmq-server-2.8.7.tar.gz 
 cd  rabbitmq-server-2.8.7
 make
  如果你还没有安装Erlang,那么参考这里:[Erlang 0004] Centos 源代码编译 安装 Erlang 记得使用Erlang最新版本哦,晚安各位!

2013-06-06 更新 有朋友问.net开发者如何比较"优雅"的构造Rabbit消息,除了使用Json/XML这种文本消息结构之外,我们还可以使用二进制序列化
复制代码
  public static class SerializationHelper
    {
        public static byte[] ToByteArray<T>(this T t)
        {
            using (var memoryStream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(memoryStream, t);
                return memoryStream.ToArray();
            }
        }

        public static object FromByteArray(byte[] data)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(data, 0, data.Length);
                stream.Position = 0;
                BinaryFormatter formatter = new BinaryFormatter();
                return formatter.Deserialize(stream);
            }
        }
    }

    [Serializable]
    public class RequestMessage
    {
        public int Id { get; set; }
        public string Request { get; set; }

        public override string ToString()
        {
            return string.Format("Id: {0} Request: '{1}'", Id, Request);
        }
    }

    [Serializable]
    public class ReplyMessage
    {
        public int Id { get; set; }
        public string Reply { get; set; }

        public override string ToString()
        {
            return string.Format("Id: {0} Reply: '{1}'", Id, this.Reply);
        }
    }
复制代码

没有评论:

发表评论