第一部分:消息通信和ActiveMQ简介
Apache的ActiveMQ是一种实现了Java Message Service(JMS)规范的,用于多系统和多应用程序之间进行远程消息通信的中介(或称代理)。ActiveMQ是使用java实现,并且为C/C++、.NET、Perl、PHP、Python、Ruby 等其他编程语言提供了客户端的API使用接口。
第一章:Apache ActiveMQ简介
企业级的消息软件从1980年后开始出现。消息不仅是应用程序间通信的一种方式,也可以当成是应用的集成方式。然而,在最近的十年间,开放源码的消息解决方案才刚刚出现。Apache 的ActiveMQ就是这样的一种软件,以一种异步的、松耦合的方式为应用程序提供通信支持。
1.1
ActiveMQ是一种开源的,实现了JMS1.1规范的,面向消息(MOM)的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。ActiveMQ使用Apache提供的授权,任何人都可以对其实现代码进行修改。
ActiveMQ的设计目标是提供标准的,面向消息的,能够跨越多语言和多系统的应用集成消息通信中间件。ActiveMQ实现了JMS标准并提供了很多附加的特性。这些附加的特性包括,JMX(java Management Extensions,即java管理扩展)管理,主从(master/salve,这是集群模式的一种,主要体现在可靠性方面,当主中介(代理)出现故障,那么从代理会替代主代理的位置,不至于使消息系统瘫痪)管理、消息组通信(同一组的消息,仅会提交给一个客户进行处理)、有序消息管理(确保消息能够按照发送的次序被接受者接收)。消息优先级(优先级高的消息先被投递和处理)、订阅消息的延迟接收(订阅消息在发布时,如果订阅者没有开启连接,那么当订阅者开启连接时,消息中介将会向其提交之前的,其未处理的消息)、接收者处理过慢(可以使用动态负载平衡,将多数消息提交到处理快的接收者,这主要是对PTP(point to point,即点对点消息)消息所说、虚拟接收者(降低与中介的连接数目)、成熟的消息持久化技术(部分消息需要持久化到数据库或文件系统中,当中介崩溃时,信息不会丢失)、支持游标操作(可以处理大消息)、支持消息的转换、通过使用Apache的Camel可以支持EIP、使用镜像队列的形式轻松的对消息队列进行监控等
1.1.1
支持JMS规范:ActiveMQ完全实现了JMS1.1规范。JMS规范提供了同步消息和异步消息投递方式、有且仅有一次投递语义(指消息的接收者对一条消息必须接收到一次,并且仅有一次)、订阅消息持久接收等。如果仅使用JMS规范,表明无论您使用的是哪家厂商的消息代理,都不会影响到您的程序。
连接方式的多样化:ActiveMQ提供了广泛的连接模式,包括HTTP/S、JGroups、JXTA、muticast、SSL、TCP、UDP、XMPP等。提供了如此多的连接模式表明了ActiveMQ具有较高的灵活性。
可插入式的持久化和安全:ActiveMQ提供了多种持久化方案,您可以根据实际需要进行选择。同时,也提供了完整的客户授权模式。
使用Java创建消息应用程序:最常见的使用ActiveMQ的方式就是使用Java程序来发送和接收消息。
与其他的Java容器紧密集成:ActiveMQ提供了和其它流行的Java容器的结合,包括Apache Geronimo、Apache Tomcat、JBoss、Jetty等。
客户端API:ActiveMQ提供了多种客户端可访问的API,包括Java、C/C++,.NET,Perl、PHP、Python、Ruby等。当然,ActiveMQ中介必须运行在Java虚拟机中,但是使用它的客户端可以使用其他的语言来实现。
中介集群:多个ActiveMQ中介可以一起协同工作,来完成某项复杂的工作,这被称为网络型中介(network of brokers),这种类型的中介将会支持多种拓扑类型。
1.1.2
在设计分布式应用程序时,应用程序间的耦合(或称集成)方式很重要。耦合意味着两个或者多个应用程序或系统的相互依赖关系。一种简单的方式是在所有的应用程序中从架构上设计他们与其他应用程序间的交叉实现。这样必然导致,一个应用程序的改变,直接导致另一个应用程序的改变。按照这种方式集成的应用是一种紧耦合的应用。一个应用的改变不会影响到其他应用的集成方式被称为是松耦合的集成方式。简单的说,松耦合应用程序集成能够更容易的处理不可预见的应用变化。
像COM、CORBA、DCE和EJB等应用技术使用RPC(Remote Procedural Calls,即远程过程调用)属于紧耦合技术。使用RPC,一个应用程序调用另一个应用程序,调用者必须阻塞,直到被调用者执行结束返回结果信息为止。下图给出了这种紧耦合技术的描述:
许多系统架构使用RPC,并且获得了巨大的成功,但是,紧耦合的架构有着天生的缺陷。首先,这种架构将会造成系统维护管理上的巨大消费,因为,即使是很小的改动,很可能会波及到整个系统。其次,由于调用者必须阻塞式的等待被调用者返回,如果被调用者处理过程复杂,将会严重影响调用者的执行效率和资源使用率。此外,如果调用失败,整个架构即失败。
下图给出一种松耦合的方式,进行架构设计:
应用程序1向消息中介(MOM)发送一条消息,很可能一段时间之后,应用程序2调用MOM来收取消息。任何一个应用程序都不知道对方是否存在也不需要阻塞等待。这种通信方式大大缩减了维护开销,因为对于一个应用程序的修改,会对其他应用程序影响极小。
ActiveMQ就是采用了上面提到的松耦合方式,因此,我们经常说应用程序发送消息仅仅是触发后忘却。应用程序将消息发送给ActiveMQ而并不关心什么时间以何种方式消息投递给接收者。同样的,消息接收者也不会关心消息来源于哪里和消息是怎样投递给ActiveMQ的。对于多语言编写的复杂应用环境中,允许客户端使用不同的编程语言甚至不同的消息包装协议。ActiveMQ作为消息的中间件,允许复杂的多语言应用程序以一种一步的方式集成和交互。
所以说,ActiveMQ是一种好的,提供松散耦合的,能够为多语言交叉应用提供集成的中间件。
1.1.3
正如前面提到的,紧耦合应用系统存在许多问题,但是,要将紧耦合系统重构成松耦合系统是一件值得但比较繁琐的事情。使用松耦合的主要优势体现在将同步改为异步。使用异步通信,应用程序将从接收者反馈的等待中解放出来,其他的任务可以得到执行,这样提高了应用程序的效率。
只要是两个应用程序间需要通信的情况,都可以考虑使用JMS,不论这种通信是在本地的(就是通信的两个应用程序在同一台主机上),还是分布在不同机器上。尽管是在同一个主机上的两个应用程序需要通信也可以使用ActiveMQ。ActiveMQ可以确保消息投递成功并采用异步方式通信。
多个需要通信的应用程序在同一个机器上的情况下,您可以考虑在执行机上独立运行ActiveMQ或者将ActiveMQ嵌入到Java应用服务中。无论采用哪种方式,都可以确保应用程序能够发送和接收消息。您可以选择订阅模式(pub/sub)或者采用PTP(point to point)模式,这两种模式都无需等待执行反馈信息。每一个应用程序都可以简单的将消息发送给ActiveMQ,然后继续做其他的工作;应用程序无需阻塞式等待消息的返回。
对于分布在多台主机上的应用程序来说,可以使用多种布置策略。主要包括单一ActiveMQ实例和多ActiveMQ实例。单一ActiveMQ实例是一个简单解决方案。所有的应用程序都向同一个ActiveMQ中介发送和接收消息,这与上面提到的单机多服务雷同。单一的ActiveMQ可以布置到一台单独的主机上,也可以和其中的一些服务布置在一起。重要的是,所有的应用必须能够直接与ActiveMQ中介进行交互,所以,你必须考虑到你的网络设计。
第二种情况比较复杂,但是有ActiveMQ来负责远程通信,而不是应用程序自身。在这种场景下,每一个应用程序都会实例化一个ActiveMQ(无论是嵌入式的还是独立式的),应用程序从其本地的ActiveMQ发送和接收消息。之后这些ActiveMQ实例将会以一种联合的方式协同工作。消息将会基于每一个应用的要求在多个ActiveMQ中介间传递到远程的处理者。在ActiveMQ中,这种模式被称为netWork of brokers。采用这种模式对于处理大量的ActiveMQ消息是可行的,但是,我们往往需要减轻网络拓扑的复杂性,这样直接将消息投递到远程接收者的ActiveMQ是不可行的。在后一种情况下,不同的协议使用可以使ActiveMQ更轻松的传递消息。
1.2 1.2.1
1.2.2
1.2.3
应该为每一个ActiveMQ代理取唯一的名字:在组内合作的方式下,如果使用默认的配置,很可能造成两个或者多个代理互相连接到对方,并且开始消费对方的消息,下面提供了防止出现上述现象的策略。
1.
<transportConnector name=”openwire” uri=”tcp://localhost:61616”
discoveryUri=”multicast://default”/>
为了终止代理使用多播的方式向其他代理发布TCP传输端口,只需要移除上面配置的discoveryUri属性即可。
2.
<networkConnector name=”default-nc” uri=”multicast://default”/>
想要使上述的网络连接器失效仅需删除或者注释上面的语句即可。
3.
<broker xmlns=”http://activemq.apache.org/schema/core” brokerName=”localhost”
dataDirectory=”${activemq.base}/data”>
为了使您的代理名唯一,请修改localhost为一个唯一的代理名。
1.3
ActiveMQ是一个很灵活的面向消息的中间件,能够应用于多种不同的情况。在本章中,您已经学习到了ActiveMQ的一些特性,并且了解了ActiveMQ应用的一些场景。下面的章节中,您需要进一步了解ActiveMQ的配置方法,使您能够灵活的配置ActiveMQ代理和面向客户端的连接器。