1.简介
前面接收ActiveMQ及代码案例中都是配置了:
broker-url: tcp://192.168.106.131:61616
可见TCP时ActiveMQ的默认协议。然而ActiveMQ处理支持TCP谢谢,它还支持client-broker通讯协议有:TCP、NIO、UDP、SSL、HTTP(s)、VM。
详细请见官网文档:http://activemq.apache.org/configuring-version-5-transports.html
ActiveMQ配置这些协议的文件位置:ActiveMQ安装路径/config/activemq.xml
其中<transportConnectiontors>标签内就是ActiveMQ支持的部分协议。
在上述的配置中,
uri描述信息的头部都是采用协议的名称,比如:
描述amqp协议的监听端口时,采用的uri描述信息为“amqp://......”,
描述stomp协议的监听端口时,采用的uri描述信息为“stomp://......”。
但是注意在进行openwire协议描述时,uri却采用“tcp://......”。
这是因为ActiveMQ默认的协议就是openwire
2.各种协议详细介绍
TCP协议(Transmission Control Protocol)
(1)这是默认的Broker配置,tcp的监听端口是61616;
(2)在进行网络传输数据前,必须首先进行数据序列化,传输的消息是通过wire protocol来进行序列化成字节流;
(3)Tcp链接的URI形式:
tcp://HostName:port?key=value&key=value
后面的参数是可选的。
(4)TCP传输的优点:
-tcp协议传输可靠性高,稳定性强;
-以字节流方式传递,效率很高;
-应用广泛,支持任何平台。有消息,可用性高。
NIO协议(New I/O API Protocol)
(1)NIO协议和TCP协议类似,但是NIO更侧重于底层的访问操作。它允许开发人员对同一资源使用更多的client调用和服务器端有更对的负载;
(2)NIO协议使用的场景:
当有大量的Client段取链接到Broker上时,操作系统对连接的线程数量有所限制。此时采用NIO的实现可以比TCP需要更少的线程,这个时候就建议使用NIO协议。
当Broker的网络传输比较迟钝时,使用NIO比TCP有更好的性能;
(3)NIO连接的URI形式:
nio://hostname:port?key=value&key=value
AMQP协议(Advanced Message Queuing Protocol)
AMQP协议是一个提供提议消息服务的应用层标志高级消息队列协议,他是应用层协议的一个开放标准,为面向消息中间件设计。
基于此协议的客户端余潇潇中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。
STOMP协议(Streaming Text Orientated Message Protocol)
是流文本定向消息协议,是一种为MOM(Message Oriented Middleware 面向消息的中间件)设计的简单文本协议。
其他协议可以通过官网去研究研究 ,这里就略过了。
3.NIO协议案例
ActiveMQ这些协议传输的底层默认都是使用BIO网络的IO模型。只有当我们指定使用nio才使用NIO的IO模型。
(1)修改配置文件activemq.xml
-修改配置文件,在<transportConnectors>节点下添加如下内容:
<transportConnector name="nio" uri="nio://0.0.0.0:61618?trace=true"/>
-重启activemq服务:
./activemq restart
-查看activemq管理后台,可以看到新增了nio协议:
(2)代码实现
其实实现的代码除了传输协议的那个参数改变了,其他与通过tcp实现的代码一致。
具体代码:
消费者
package com.jzt.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @author sj
*/
public class NIO_QueueProducer {
public static String MQ_NAME = "admin";
public static String MQ_PASSWORD = "admin";
public static String MQ_BROKETURL = "nio://192.168.106.131:61616";
public static void main(String[] args) throws JMSException {
//连接工厂
ConnectionFactory factory;
// 连接实例
Connection connection = null;
//会话
Session session = null;
// 消息发送目标地址
Destination destination;
// 消息创建者
MessageProducer messageProducer = null;
try {
factory = new ActiveMQConnectionFactory(MQ_NAME, MQ_PASSWORD, MQ_BROKETURL);
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue("nio_queue");
messageProducer = session.createProducer(destination);
for (int i = 0; i < 9; i++) {
TextMessage textMsg = session.createTextMessage("NIO: 这是第" + i + "条消息");
//textMsg.setJMSDeliveryMode(DeliveryMode.NON_PERSISTENT);
textMsg.setJMSPriority(i);
messageProducer.send(textMsg);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
messageProducer.close();
session.close();
connection.close();
}
}
}
启动生产者,可以看到消息发送成功:
消费者:
package com.jzt.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @author sj
*/
public class NIO_QueueComsumer {
public static String MQ_NAME = "admin";
public static String MQ_PASSWORD = "admin";
public static String MQ_BROKETURL = "nio://192.168.106.131:61616";
public static void main(String[] args) throws JMSException {
ConnectionFactory factory;
Connection connection = null;
Session session = null;
Destination destination;
MessageConsumer messageConsumer = null;
try {
factory = new ActiveMQConnectionFactory(MQ_NAME, MQ_PASSWORD, MQ_BROKETURL);
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue("nio_queue");
messageConsumer = session.createConsumer(destination);
messageConsumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
if(message != null && message instanceof TextMessage){
TextMessage textMessage = (TextMessage)message;
System.out.println("获取到NIO协议消息:"+textMessage);
}
}
});
System.in.read();
} catch (Exception e) {
e.printStackTrace();
} finally {
messageConsumer.close();
session.close();
connection.close();
}
}
}
启动消费者,可以看到已经消费到了消息:
4.NIO协议增强案例
除了NIO这个高效的协议外,ActiveMQ还对所有协议进行了优化,提供了增强型NIO。通过这个模式,可以让其他协议传输底层也是用NIO网络的IO模型。实现增强型NIO的方法就是使用auto关键字,相当于把所有协议封装起来,只暴露一个端口,使得使用起来更加灵活。(1)使用方法
auto关键字+nio
auto:针对于所有的协议,也就是说ActiveMQ会自动识别我们使用的是什么协议;
nio:使用NIO网络的IO模型。
(2)修改配置文件activemq.xml
<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"/>
<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>
(3)代码实现
使用nio模型的tcp协议生产者。除协议需要修改如下外,其他代码和之前一样:
private static final String ACTIVEMQ_URL = "tcp://118.24.20.3:61608";
这样,ActiveMQ服务器就可以识别我们的协议,最后底层都是通过nio的模型。