一 嵌入式的MQ实例
1.1 broker启动
一个broker相当于一个activeMQ实例。
1:activemqstart :使用默认的activemq.xml来启动
2:activemqstart xbean:file:../conf/activemq-2.xml :使用指定的配置文件 来启动
3:如果不指定file,也就是xbean:activemq-2.xml,那么xml必须在classpath下面
1.2 代码嵌入broker
1.2.1 启动方式说明
1:Broker Service启动broker ,示例如下:
BrokerServicebroker = new BrokerService();
broker.setUseJmx(true);
broker.addConnector("tcp://localhost:61616");
broker.start();
2:BrokerFactory启动broker ,示例如下:
String Uri = "properties:broker.properties";
BrokerServicebroker1 = BrokerFactory.createBroker(newURI(Uri));
broker1.addConnector("tcp://localhost:61616");
broker1.start();
3:broker.properties的内容示例如下:
useJmx=true
persistent=false
brokerName=Cheese
1.2.2 启动实例
(1)Broker服务
public class Snippet {
public static void main(String[] args) throws Exception {
BrokerService broker = new BrokerService();
broker.setUseJmx(true);
broker.addConnector("tcp://localhost:61616");
broker.start();
}
}
(2)Sender
public class MsgSendder {
public static void main(String[] args) throws Exception {
ActiveMQConnectionFactory ConnectionFactoryconnectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = ConnectionFactoryconnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("my-queue");
MessageProducer producer = session.createProducer(destination);
for (int i = 0; i < 3; i++) {
TextMessage message = session.createTextMessage("message--" + i);
Thread.sleep(1000);
producer.send(message);
}
session.commit();
session.close();
connection.close();
}
}
(3)Receiver
public class MsgReceiver {
public static void main(String[] args) throws Exception {
ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = cf.createConnection();
connection.start();
final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("my-queue");
MessageConsumer consumer = session.createConsumer(destination);
int i = 0;
while (i < 3) {
i++;
TextMessage message = (TextMessage) consumer.receive();
session.commit();
System.out.println("收到消息:" + message.getText());
}
session.close();
connection.close();
}
}
1.3 spring嵌入broker
1.3.1 spring配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<bean id="broker" class="org.apache.activemq.broker.BrokerService"
init-method="start" destroy-method="stop">
<property name="brokerName" value="myBroker" />
<property name="persistent" value="false" />
<property name="transportConnectorURIs">
<list>
<value>tcp://localhost:61616</value>
</list>
</property>
</bean>
</beans>
1.3.2 sender
public class MsgSendder {
public static void main(String[] args) throws Exception {
ActiveMQConnectionFactory ConnectionFactoryconnectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = ConnectionFactoryconnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("my-queue");
MessageProducer producer = session.createProducer(destination);
for (int i = 0; i < 3; i++) {
TextMessage message = session.createTextMessage("message--" + i);
Thread.sleep(1000);
producer.send(message);
}
session.commit();
session.close();
connection.close();
}
}
1.3.3 receiver
public class MsgReceiver {
public static void main(String[] args) throws Exception {
ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = cf.createConnection();
connection.start();
final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("my-queue");
MessageConsumer consumer = session.createConsumer(destination);
int i = 0;
while (i < 3) {
i++;
TextMessage message = (TextMessage) consumer.receive();
session.commit();
System.out.println("收到消息:" + message.getText());
}
session.close();
connection.close();
}
}
二 spring集成MQ
2.1 spring继承MQ(p2p)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:property-placeholder location="classpath:resource/*.properties" />
<context:component-scan base-package="xiao.it.*"/>
<bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://192.168.232.128:61616</value>
</property>
</bean>
</property>
<property name="maxConnections" value="100"></property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsFactory" />
<property name="defaultDestination" ref="destination" />
<property name="messageConverter">
<bean
class="org.springframework.jms.support.converter.SimpleMessageConverter" />
</property>
</bean>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="spring-queue" />
</bean>
<bean id="springSender" class="xiao.it.jms.SpringSender"></bean>
<bean id="springReceiver" class="xiao.it.jms.SpringReceiver"></bean>
</beans>
2.2 producer
public class SpringSender {
@Autowired
private JmsTemplate jmsTemplate= null;
public static void main(String[] args)
{
@SuppressWarnings("resource")
ApplicationContext ctx= new ClassPathXmlApplicationContext("spring-service.xml");
SpringSender ct = (SpringSender)ctx.getBean("springSender");
ct.jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session s) throws JMSException {
TextMessage msg= s.createTextMessage("Springmsg===");
return msg;
}
});
}
}
2.3 consumer
@Service
public class SpringReceiver {
@Autowired
private JmsTemplate jmsTemplate= null;
public static void main(String[] args) throws Exception {
@SuppressWarnings("resource")
ApplicationContext ctx= new ClassPathXmlApplicationContext("spring-service.xml");
SpringReceiver ct = (SpringReceiver)ctx.getBean("springReceiver");
String msg= (String)ct.jmsTemplate.receiveAndConvert();
System.out.println("msg==="+msg);
}
}
2.4 spring继承MQ(pub/sub)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:property-placeholder location="classpath:resource/*.properties" />
<context:component-scan base-package="xiao.it.*"/>
<bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://192.168.232.128:61616</value>
</property>
</bean>
</property>
<property name="maxConnections" value="100"></property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsFactory" />
<property name="defaultDestination" ref="destinationTopic" />
<property name="messageConverter">
<bean
class="org.springframework.jms.support.converter.SimpleMessageConverter" />
</property>
</bean>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="spring-queue" />
</bean>
<bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg index="0" value="spring-topic" />
</bean>
<bean id="springSender" class="xiao.it.jms.SpringSender"></bean>
<!-- <bean id="springReceiver" class="xiao.it.jms.SpringReceiver"></bean> -->
</beans>
2.5 producer
public class SpringSender {
@Autowired
private JmsTemplate jmsTemplate= null;
public static void main(String[] args)
{
@SuppressWarnings("resource")
ApplicationContext ctx= new ClassPathXmlApplicationContext("spring-service.xml");
SpringSender ct = (SpringSender)ctx.getBean("springSender");
ct.jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session s) throws JMSException {
TextMessage msg= s.createTextMessage("Springmsg===");
return msg;
}
});
}
}
2.6 consumer
@Service
public class SpringReceiver {
@Autowired
private JmsTemplate jmsTemplate= null;
public static void main(String[] args) throws Exception {
@SuppressWarnings("resource")
ApplicationContext ctx= new ClassPathXmlApplicationContext("spring-service.xml");
SpringReceiver ct = (SpringReceiver)ctx.getBean("springReceiver");
String msg= (String)ct.jmsTemplate.receiveAndConvert();
System.out.println("msg==="+msg);
}
}
2.7 spring继承MQ(消息监听器)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:property-placeholder location="classpath:resource/*.properties" />
<context:component-scan base-package="xiao.it.*" />
<bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://192.168.232.128:61616</value>
</property>
</bean>
</property>
<property name="maxConnections" value="100"></property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsFactory" />
<property name="defaultDestination" ref="destinationTopic" />
<property name="messageConverter">
<bean
class="org.springframework.jms.support.converter.SimpleMessageConverter" />
</property>
</bean>
<bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg index="0" value="spring-topic" />
</bean>
<!-- <bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="spring-queue" />
</bean>
<bean id="springReceiver" class="xiao.it.jms.SpringReceiver"></bean> -->
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsFactory" />
<property name="destination" ref="destinationTopic" />
<property name="messageListener" ref="messageListener" />
</bean>
<bean id="messageListener" class="xiao.it.jms.MyMessageListener">
</bean>
</beans>
2.8 producer
public class SpringSender {
@Autowired
private JmsTemplate jmsTemplate= null;
public static void main(String[] args)
{
@SuppressWarnings("resource")
ApplicationContext ctx= new ClassPathXmlApplicationContext("spring-service.xml");
SpringSender ct = (SpringSender)ctx.getBean("springSender");
ct.jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session s) throws JMSException {
TextMessage msg= s.createTextMessage("Springmsg===");
return msg;
}
});
}
}
2.9 consumer
前提是已经通过spring进行初始化,并且注入
public class MyMessageListener implements MessageListener
{
public void onMessage(Message message) {
TextMessage msg= (TextMessage)message;
try {
System.out.println("receivetxt msg==="+msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
2.10 最佳实践和建议
1:Spring消息发送的核心架构是JmsTemplate,隔离了像打开、关闭Session和 Producer的繁琐操作,因此应用开发人员仅仅需要关注实际的业务逻辑。但是 JmsTemplate损害了ActiveMQ的PooledConnectionFactory对session和消息 producer的缓存机制而带来的性能提升。
2:新的Spring里面,可以设置 org.springframework.jms.connection.CachingConnectionFactory的 sessionCacheSize ,或者干脆使用ActiveMQ的PooledConnectionFactory
3:不建议使用JmsTemplate的receive()调用,因为在JmsTemplate上的所有调用都 是同步的,这意味着调用线程需要被阻塞,直到方法返回,这对性能影响很大
4:请使用DefaultMessageListenerContainer,它允许异步接收消息并缓存session 和消息consumer,而且还可以根据消息数量动态的增加或缩减监听器的数量
三 ActiveMQ的通信协议
client-broker通讯协议如下:
1:TCP:这个也是缺省使用的协议 2:NIO 3:UDP 4:SSL 5:Http(s)
3.1 TCP协议Transmission Control Protocol (TCP)
1:这是默认的Broker配置,TCP的Client监听端口是61616。
2:在网络传输数据前,必须要序列化数据,消息是通过一个叫wire protocol的来序列化成字 节流。默认情况下,ActiveMQ把wire protocol叫做OpenWire,它的目的是促使网络上的效 率和数据快速交互。
3:TCP连接的URI形式:tcp://hostname:port?key=value&key=value,加粗部分是必须的
4:TCP传输的优点:
(1) TCP协议传输可靠性高,稳定性强
(2)高效性:字节流方式传递,效率很高
(3)有效性、可用性:应用广泛,支持任何平台
5:所有关于Transport协议的可配置参数,可以参见: http://activemq.apache.org/configuring-version-5-transports.html
3.2 New I/O API Protocol(NIO)
1:NIO协议和TCP协议类似,但NIO更侧重于底层的访问操作。它允许开发人员对同一资源可有 更多的client调用和服务端有更多的负载
2:适合使用NIO协议的场景:
(1)可能有大量的Client去链接到Broker上 一般情况下,大量的Client去链接Broker是被操作系统的线程数所限制的。因此, NIO的实现比TCP需要更少的线程去运行,所以建议使用NIO协议
(2)可能对于Broker有一个很迟钝的网络传输 NIO比TCP提供更好的性能
3:NIO连接的URI形式:nio://hostname:port?key=value
4:Transport Connector配置示例:
<transportConnectors>
<transportConnector name="tcp" uri="tcp://localhost:61616?trace=true" />
<transportConnectorname="nio"uri="nio://localhost:61618?trace=true"/> </transportConnectors>
上面的配置,示范了一个TCP协议监听61616端口,一个NIO协议监听61618端口
3.3 User Datagram Protocol(UDP)
1:UDP和TCP的区别
(1)TCP是一个原始流的传递协议,意味着数据包是有保证的,换句话说,数据包是不会被复 制和丢失的。UDP,另一方面,它是不会保证数据包的传递的
(2)TCP也是一个稳定可靠的数据包传递协议,意味着数据在传递的过程中不会被丢失。这样 确保了在发送和接收之间能够可靠的传递。相反,UDP仅仅是一个链接协议,所以它没有可 靠性之说
2:从上面可以得出:TCP是被用在稳定可靠的场景中使用的;UDP通常用在快速数据传递和不 怕数据丢失的场景中,还有ActiveMQ通过防火墙时,只能用UDP
3:UDP连接的URI形式:udp://hostname:port?key=value
4:Transport Connector配置示例:
<transportConnectors>
<transportConnector name="udp" uri="udp://localhost:61618?trace=true" />
</transportConnectors>
3.4 Secure Sockets Layer Protocol (SSL)
1:连接的URI形式:ssl://hostname:port?key=value
2:Transport Connector配置示例:
<transportConnectors>
<transportConnectorname="ssl"uri="ssl://localhost:61617?trace=true"/> </transportConnectors>
3.5 Hypertext Transfer Protocol (HTTP/HTTPS)
1:像web和email等服务需要通过防火墙来访问的,Http可以使用这种场合
2:连接的URI形式:http://hostname:port?key=value或者 https://hostname:port?key=value 3:Transport Connector配置示例:
<transportConnectors>
<transportConnectorname="http"uri="http://localhost:8080?trace=true"/> </transportConnectors>
3.6 VM Protocol(VM)
1:VM transport允许在VM内部通信,从而避免了网络传输的开销。这时候采用的连 接不是socket连接,而是直接的方法调用。
2:第一个创建VM连接的客户会启动一个embed VM broker,接下来所有使用相同的 broker name的VM连接都会使用这个broker。当这个broker上所有的连接都关闭 的时候,这个broker也会自动关闭。
3:连接的URI形式:vm://brokerName?key=value
4:Java中嵌入的方式:
vm:broker:(tcp://localhost:6000)?brokerName=embeddedbroker&persistent=fal se , 定义了一个嵌入的broker名称为embededbroker以及配置了一个 tcptransprotconnector在监听端口6000上
5:使用一个加载一个配置文件来启动broker
vm://localhost?brokerConfig=xbean:activemq.xml