ActiveMQ
ActiveMQ的传输协议
一、简介
ActiveMQ支持的client-broker通讯协议有:
TVP、NIO、UDP、SSL、Http(s)、VM。
其中配置Transport Connector的文件在ActiveMQ安装目录的conf/activemq.xml中的< transportConnectors >
标签之内。
activemq传输协议的官方文档:
http://activemq.apache.org/configuring-version-5-transports.html
这些协议参见文件:%activeMQ安装目录%/conf/activemq.xml
,下面是文件的重要的内容
在上文给出的配置信息中,URI描述信息的头部都是采用协议名称:例如
描述amqp协议的监听端口时,采用的URI描述格式为“amqp://······”;
描述Stomp协议的监听端口时,采用URI描述格式为“stomp://······”;
唯独在进行openwire协议
描述时,URI头却采用的“tcp://······”
。这是因为ActiveMQ中默认的消息协议就是openwire
二、支持的传输协议
个人说明:除了tcp和nio协议,其他的了解就行。各种协议有各自擅长该协议的中间件,工作中一般不会使用activemq去实现这些协议。如: mqtt是物联网专用协议,采用的中间件一般是mosquito。ws是websocket的协议,是和前端对接常用的,一般在java代码中内嵌一个基站(中间件)。stomp好像是邮箱使用的协议的,各大邮箱公司都有基站(中间件)。
注意:
Java程序员只需要关注tpc、nio两个,其他的仅了解即可。
协议不同,我们的代码都会不同。
1、TCP协议【关注】
(1) Transmission Control Protocol(TCP
)是默认的
。TCP的Client监听端口61616
(2) 在网络传输数据前,必须要先序列化数据,消息是通过一个叫wire protocol的来序列化成字节流。
(3) TCP连接的URI形式如:tcp://HostName:port?key=value&key=value,后面的参数是可选的。
(4) TCP传输的的优点:
- TCP协议传输可靠性高,稳定性强
- 高效率:字节流方式传递,效率很高
- 有效性、可用性:应用广泛,支持任何平台
(5) 关于Transport协议
的可选配置参数可以参考官网http://activemq.apache.org/tcp-transport-reference
2、NIO协议【关注】
(1) New I/O API Protocol(NIO)
(2) NIO协议和TCP协议类似,但NIO更侧重于底层的访问操作。它允许开发人员对同一资源可有更多的client调用和服务器端有更多的负载。
(3) 适合使用NIO协议的场景:
可能有大量的Client去连接到Broker上,一般情况下,大量的Client去连接Broker是被操作系统的线程所限制的。因此,NIO的实现比TCP需要更少的线程去运行,所以建议使用NIO协议。
可能对于Broker有一个很迟钝的网络传输,NIO比TCP提供更好的性能。
(4) NIO连接的URI形式:nio://hostname:port?key=value&key=value
(5) 关于Transport协议的可选配置参数可以参考官网http://activemq.apache.org/configuring-version-5-transports.html
3、AMQP协议
4、STOMP协议
5、 MQTT协议
三、NIO协议案例
ActiveMQ这些协议传输的底层默认都是使用BIO网络的IO模型。只有当我们指定使用nio才使用NIO的IO模型。
1、修改配置文件activemq.xml
① 修改配置文件activemq.xml在 节点下添加如下内容:
< transportConnector name=“nio” uri=“nio://0.0.0.0:61618?trace=true” />
② 修改完成后重启activemq:
service activemq restart
③ 查看管理后台,可以看到页面多了nio
2、代码
上下代码就修改了
ACTIVEMQ_URL
的值,为nio协议,然后nio的port,其他都不变
生产者【JmsProduce_nio】:
注意:nio协议端口设置为了61618
public class JmsProduce_nio {
=============================================================================
public static final String ACTIVEMQ_URL = "nio://192.168.109.101:61618";
=============================================================================
public static final String QUEUE_NAME = "Transport";
public static void main(String[] args) throws JMSException {
//1、创建连接工厂,这个构造器采用默认的用户名密码(admin&admin)。该类的其他构造方法可以指定用户名和密码。
ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2、通过连接工厂,获得连接connection 并 启动访问
Connection conn = mqConnectionFactory.createConnection();
conn.start();
//3、创建会话session(参数1:事务 / 参数2:签收)
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4、创建目的地(队列 / 主题)
Queue queue = session.createQueue(QUEUE_NAME);
//5、创建消息的生产者
MessageProducer messageProducer = session.createProducer(queue);
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
//6、通过使用消息生成者生成3条消息 发送给MQ队列
for (int i = 1; i <= 3; i++) {
//7、创建消息,【好比学生们按照老师约定的要求写好单子】
TextMessage textMessage = session.createTextMessage("msg--MessageListener---" + i);//理解为一个字符串消息
//8、通过 messageProducer 消息生产者将消息发送给MQ中间件
messageProducer.send(textMessage);
}
//9、关闭资源【顺着申请,倒着关闭】
messageProducer.close();
session.close();
conn.close();
System.out.println("========消息发布到MQ完成===========");
}
}
消费者【JmsConsumer_nio】:
注意:nio协议端口设置为了61618
public class JmsConsumer_nio {
=============================================================================
public static final String ACTIVEMQ_URL = "nio://192.168.109.101:61618";
=============================================================================
public static final String QUEUE_NAME = "Transport";
public static void main(String[] args) throws JMSException, IOException {
//1、创建连接工厂,这个构造器采用默认的用户名密码(admin&admin)。该类的其他构造方法可以指定用户名和密码。
ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2、通过连接工厂,获得连接connection 并 启动访问
Connection conn = mqConnectionFactory.createConnection();
conn.start();
//3、创建会话session(参数1:事务 / 参数2:签收)
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4、创建目的地(队列 / 主题)
Queue queue = session.createQueue(QUEUE_NAME);
//5、创建消息的消费者
MessageConsumer consumer = session.createConsumer(queue);
//通过监听的方式来获取消息
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
if (null != message && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("消费者获取到的数据: " + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
System.in.read();
consumer.close();
conn.close();
session.close();
}
}
四、NIO协议案例增强
1、目的
上面是Openwire协议传输底层使用NIO网络IO模型。 如何让其他协议传输底层也使用NIO网络IO模型呢?
2、修改配置文件activemq.xml
<transportConnector name="auto+nio" uri="auto+nio://0.0.0.0:61608?maximumConnections=1000&wireFormat.maxFrameSize=104857600&org.apache.activemq.transport.nio.SelectorManager.corePoolSize=20&org.apache.activemq.transport.nio.Se1ectorManager.maximumPoo1Size=50"/>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61626?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5682?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61623?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1893?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61624?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<!--<transportConnector name="nio" uri="nio://0.0.0.0:61618?trace=true" />-->
<transportConnector name="auto+nio" uri="auto+nio://0.0.0.0:61608?maximumConnections=1000&wireFormat.maxFrameSize=104857600&org.apache.activemq.transport.nio.SelectorManager.corePoolSize=20&org.apache.activemq.transport.nio.Se1ectorManager.maximumPoo1Size=50"/>
</transportConnectors>
auto : 针对所有的协议,他会识别我们是什么协议。
nio :使用NIO网络IO模型
修改配置文件后重启
activemq。
3、代码
使用上面添加好的NIO增强的端口,61608
,他会自动的适配多重协议
①适配tpc协议:
生产者:
public class JmsProduce_nio {
==============================================================================
public static final String ACTIVEMQ_URL = "tcp://192.168.109.101:61608";
==============================================================================
public static final String QUEUE_NAME = "nio-auto";
public static void main(String[] args) throws JMSException {
..........
}
}
消费者:
public class JmsConsumer_nio {
==============================================================================
public static final String ACTIVEMQ_URL = "tcp://192.168.109.101:61608";
==============================================================================
public static final String QUEUE_NAME = "nio-auto";
public static void main(String[] args) throws JMSException, IOException {
..........
}
}
②适配nio协议:
生产者:
public class JmsProduce_nio {
==============================================================================
public static final String ACTIVEMQ_URL = "nio://192.168.109.101:61608";
==============================================================================
public static final String QUEUE_NAME = "nio-auto";
public static void main(String[] args) throws JMSException {
..........
}
}
消费者:
public class JmsConsumer_nio {
==============================================================================
public static final String ACTIVEMQ_URL = "nio://192.168.109.101:61608";
==============================================================================
public static final String QUEUE_NAME = "nio-auto";
public static void main(String[] args) throws JMSException, IOException {
..........
}
}