ActiveMQ客户端原理及源码分析
主要解决三个问题:
- 1 客户端通过什么与服务端建立连接?
- 2 客户端通过什么方式向服务端发送消息?
- 3 用到的设计模式-策略模式
1客户端通过什么与服务端建立连接?
客户端通过传输连接器(transport connectors)与服务端建立连接。对于服务端,传输连接器用于接收(生产者)和监听(消费者)来自客户端的连接;对于客户端,传输连接器用于创建一个到服务端的连接,便于发送消息。
图1 传输连接器与客户端和服务端的关系
传输连接器的体现
ActiveMQ软件自带5类传输连接器,具体可以查看conf/activemq.xml配置文件,我这里使用的是5.15.9版本,默认的传输连接器有以下5类:
<!--
The transport connectors expose ActiveMQ over a given protocol to
clients and other brokers. For more information, see:
http://activemq.apache.org/configuring-transports.html
-->
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
此处传输连接器包括name属性和uri属性,当然还包括其他属性,如discoveryUri属性。name为传输连接器的名字,必须唯一;这里重点讲一讲uri属性:
tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600
属性uri包括三部分:
- scheme:tcp协议;用于指明客户端到服务端的底层网络协议。
- path:0.0.0.0:61616;用于指明服务器的IP地址和端口,此处默认配置为本机,如果ActiveMQ服务端运行在其他主机上则需要修改为相应的的IP地址。端口号是统一默认的,不需要修改。
- query:maximumConnections=1000&wireFormat.maxFrameSize=104857600;用于指定额外的参数。maximumConnections表示最大连接数,wireFormat.maxFrameSize表示最大帧数,用于限定单条消息的大小,单位为字节(默认为104857600字节,即100MB)。
注意:query部分的参数内容与scheme部分相关紧密,如果有兴趣可以参考官网
传输连接器的不同主要体现在scheme部分,即底层网络协议的不同。上面默认提供的传输连接器(应用层)有openwire协议,amqp协议,stomp协议,mqtt协议和ws协议。下面简单介绍下ActiveMQ支持的几种应用层网络协议。
- OpenWire协议:是一种跨语言连接协议,允许从不同的平台和语言对ActiveMQ进行本地访问。它是ActiveMQ默认传输协议。OpenWire通过代码生成特定于语言的命令,并对理解核心OpenWire协议的代码进行封送处理。然后,我们可以为低层协议编写特定于语言的扩展,以在不同的语言中提供良好且易于使用的客户机API。
- AMQP协议:即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。
- STOMP协议:即Simple (or Streaming) Text Orientated Messaging Protocol,简单(流)文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。STOMP协议由于设计简单,易于开发客户端,因此在多种语言和多种平台上得到广泛地应用。
- MQTT协议:即Message Queuing Telemetry Transport,消息队列遥测传输;是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。
- WS协议:即webScoket,是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。
PS:这些协议都是TCP/UDP/NIO等上层协议,关于网络协议这块了解不深,所以不敢说的太多,只能简单的介绍每个协议的概念和作用。
传输连接器的实现
下面用Java代码实现客户端上的的传输连接器。
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
通过连接工厂创建传输连接器。大概过程如下:
1 根据入参生成URI对象,并生成一个ActiveMQConnectionFactory对象;
public ActiveMQConnectionFactory(String brokerURL) {
this(createURI(brokerURL));
}
public ActiveMQConnectionFactory(URI brokerURL) {