JMS服务器ActiveMQ的初体验并持久化消息到MySQL数据库中

一、JMS的理解
JMS(Java Message Service)是jcp组织02-03年定义了jsr914规范(http://jcp.org/en/jsr/detail?id=914),它定义了消息的格式和消息传递模式;
消息包括:消息头,消息扩展属性和消息体,其结构看起来与SOAP非常的相似,但一般情况下,SOAP主要关注远程服务调用,而消息则专注于信息的交换;
消息分为:消息生产者,消息服务器和消息消费者。生产者与消费者之间是透明的,生产者在产生消息之后,把消息发送到消息服务器,再由消息服务器发给消费者,因此它们构成了JMS的3点结构;
消息服务器再给消费者时,有2种模式:点到点(ptp: point to point)模式和发布/订阅(publish/subscribe)模式;
ptp:即生产者把消息投递到消息服务器后,这条消息只能由某一个消费者使用;
发布/订阅:顾名思义,就是共享消息了,只要愿意,消费者都可以监听消息;

二、消息服务器(ActiveMQ)
消息服务器在JMS的3点结构中起着重要作用,没有它,生产者的消息不知道如何投递出去,消费者不知道从哪里取得消息,它同样是隔离生产者和消费者的关键部分…………
JMS消息服务器有很多:ActiveMQ、Jboss MQ、Open MQ、RabbitMQ、ZeroMQ等等。
本文介绍的是开源的Java实现的Apache ActiveMQ(http://activemq.apache.org),它的特性在首页就能看到,我就不再介绍了;

1、下载AMQ:http://activemq.apache.org/download.html,最新版本是5.5.0;
2、解压apache-activemq-5.5.0-bin.zip文件到文件系统(比如D:\ActiveMQ-5.5.0);
3、执行bin/activemq.bat脚本即可启动AMQ:
Java代码  
  1. INFO | ActiveMQ 5.5.0 JMS Message Broker (localhost) is starting   
  2. ......   
  3. INFO | Listening for connections at: tcp://SHI-AP33382A:61616  

 当看到上面的日志输出时,表示AMQ已经启动了;
4、默认情况下,AMQ使用conf/activemq.xml作为配置文件,我们可修改它,然后以 bin/activemq.bat xbean:./conf/my.xml启动AMQ;

三、持久化消息(MySQL)
因为接下来我们修改AMQ的默认配置文件,所以先备份conf/activemq.xml文件;
1、建立MySQL数据库:要使用MySQL存储消息,必须告诉AMQ数据源:

Sql代码  
  1. /**   
  2.  * 创建数据库   
  3.  */   
  4. CREATE DATABASE misc DEFAULT CHARSET=UTF8;   
  5.   
  6. /**   
  7.  * 创建用户和授权   
  8.  */   
  9. GRANT ALL PRIVILEGES ON misc.* TO 'misc_root'@'%' IDENTIFIED BY 'misc_root_pwd';   
  10. GRANT ALL PRIVILEGES ON misc.* TO 'misc_root'@'localhost' IDENTIFIED BY 'misc_root_pwd';  

通过上面的SQL脚本,我们建立了名为misc的数据库,并且把所有权限都赋予了misc_root的用户;
由于AMQ需要在本数据库中建立数据表,因此用户的权限必须具有建表权限;
2、添加MySQL数据源:默认情况下,AMQ使用KahaDB存储(我对KahaDB不了解),注释到KahaDB的配置方式,改为MySQL的:

Xml代码  
  1. <!--   
  2. <persistenceAdapter>  
  3.     <kahaDB directory="${activemq.base}/data/kahadb"/>  
  4. </persistenceAdapter>  
  5. -->  
  6. <persistenceAdapter>  
  7.     <jdbcPersistenceAdapter dataSource="#MySQL-DS"/>  
  8. </persistenceAdapter>  
 


该配置表示,我们将要使用一个叫做“MySQL-DS”的JDBC数据源;
3、配置MySQL数据源:在</broker>节点后面,增加MySQL数据源配置:

Xml代码  
  1. <!-- MySQL DataSource -->  
  2. <bean id="MySQL-DS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  3.     <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  4.     <property name="url" value="jdbc:mysql://127.0.0.1:3306/misc?useUnicode=true&amp;characterEncoding=UTF-8"/>  
  5.     <property name="username" value="misc_root"/>  
  6.     <property name="password" value="misc_root_pwd"/>  
  7.     <property name="poolPreparedStatements" value="true"/>  
  8. </bean>  
 


其实这就是一个Spring的Bean的配置,注意id与上面的保持一致;

整个AMQ的配置文件内容为:

Xml代码  
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd   
  4.   http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">  
  5.   
  6.     <!-- Allows us to use system properties as variables in this configuration file -->  
  7.     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  8.         <property name="locations">  
  9.             <value>classpath:/META-INF/credentials.properties</value>  
  10.         </property>  
  11.     </bean>  
  12.   
  13.     <!--  
  14.         The <broker> element is used to configure the ActiveMQ broker.  
  15.     -->  
  16.     <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost">  
  17.         <!--   
  18.             For better performances use VM cursor and small memory limit. For more information, see: http://activemq.apache.org/message-cursors.html Also, if your producer is "hanging", it's probably due to producer flow control. For more information, see:   
  19.             http://activemq.apache.org/producer-flow-control.html   
  20.         -->  
  21.         <destinationPolicy>  
  22.             <policyMap>  
  23.                 <policyEntries>  
  24.                     <policyEntry topic=">" producerFlowControl="true" memoryLimit="1mb">  
  25.                         <pendingSubscriberPolicy>  
  26.                             <vmCursor />  
  27.                         </pendingSubscriberPolicy>  
  28.                     </policyEntry>  
  29.                     <policyEntry queue=">" producerFlowControl="true" memoryLimit="1mb">  
  30.                         <!--  
  31.                             Use VM cursor for better latency For more information, see: http://activemq.apache.org/message-cursors.html <pendingQueuePolicy> <vmQueueCursor/> </pendingQueuePolicy>  
  32.                         -->  
  33.                     </policyEntry>  
  34.                 </policyEntries>  
  35.             </policyMap>  
  36.         </destinationPolicy>  
  37.   
  38.         <!--   
  39.             The managementContext is used to configure how ActiveMQ is exposed in   
  40.             JMX. By default, ActiveMQ uses the MBean server that is started by   
  41.             the JVM. For more information, see:   
  42.               
  43.             http://activemq.apache.org/jmx.html   
  44.         -->  
  45.         <managementContext>  
  46.             <managementContext createConnector="false" />  
  47.         </managementContext>  
  48.   
  49.         <!--   
  50.             Configure message persistence for the broker. The default persistence   
  51.             mechanism is the KahaDB store (identified by the kahaDB tag).   
  52.             For more information, see:   
  53.               
  54.             http://activemq.apache.org/persistence.html   
  55.         -->  
  56.         <!--   
  57.         <persistenceAdapter>  
  58.             <kahaDB directory="${activemq.base}/data/kahadb"/>  
  59.         </persistenceAdapter>  
  60.         -->  
  61.         <persistenceAdapter>  
  62.             <jdbcPersistenceAdapter dataSource="#MySQL-DS" />  
  63.         </persistenceAdapter>  
  64.   
  65.         <!--   
  66.             The transport connectors expose ActiveMQ over a given protocol to   
  67.             clients and other brokers. For more information, see:   
  68.               
  69.             http://activemq.apache.org/configuring-transports.html   
  70.         -->  
  71.         <transportConnectors>  
  72.             <transportConnector name="openwire" uri="tcp://0.0.0.0:61616" />  
  73.         </transportConnectors>  
  74.     </broker>  
  75.   
  76.     <!-- MySQL DataSource -->  
  77.     <bean id="MySQL-DS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  78.         <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
  79.         <property name="url" value="jdbc:mysql://127.0.0.1:3306/misc?useUnicode=true&amp;characterEncoding=UTF-8" />  
  80.         <property name="username" value="misc_root" />  
  81.         <property name="password" value="misc_root_pwd" />  
  82.         <property name="poolPreparedStatements" value="true" />  
  83.     </bean>  
  84.   
  85.     <!--   
  86.         Enable web consoles, REST and Ajax APIs and demos   
  87.         It also includes Camel (with its web console), see ${ACTIVEMQ_HOME}/conf/camel.xml for more info   
  88.           
  89.         Take a look at ${ACTIVEMQ_HOME}/conf/jetty.xml for more details   
  90.     -->  
  91.     <import resource="jetty.xml"/>  
  92.   
  93. </beans>  
 



四、查看MySQL数据表
重新启动AMQ,启动完成之后,我们发现,misc数据库多了3张数据表:

Sql代码  
  1. mysql> SHOW tables;   
  2. +----------------+   
  3. | Tables_in_misc |   
  4. +----------------+   
  5. | activemq_acks  |   
  6. | activemq_lock  |   
  7. | activemq_msgs  |   
  8. +----------------+  
 


数据表activemq_msgs即为持久化消息表;

五、持久化消息
系统启动完毕之后,消息表中内容为空:

Sql代码  
  1. mysql> SELECT * FROM activemq_msgs;   
  2. Empty set  
 



1、发送消息:打开http://127.0.0.1:8161/demo/页面,找到“Send a message”链接,打开页面(http://127.0.0.1:8161/demo/send.html),填写完表格后,点击“Send”按键,即AMQ投递了一个消息;
2、查看消息:发送之后,我们可以看到数据表中多了一条消息:

Sql代码  
  1. mysql> SELECT * FROM activemq_msgs;   
  2. +----+-----------------+--------------------------------------------+-----------+------------+-----+----------+   
  3. | ID | CONTAINER       | MSGID_PROD                                 | MSGID_SEQ | EXPIRATION | MSG | PRIORITY |   
  4. +----+-----------------+--------------------------------------------+-----------+------------+-----+----------+   
  5. |  1 | queue://FOO.BAR | ID:SHI-AP33382A-1486-1309840138441-2:2:1:1 |         1 |          0 | |        5 |   
  6. +----+-----------------+--------------------------------------------+-----------+------------+-----+----------+  
 


3、取得消息:找到“Receive a message”链接,打开页面(http://127.0.0.1:8161/demo/message/FOO/BAR?readTimeout=10000&type=queue),发现该页面不是一个标准HTML页面,查看其源代码,其内容是不是就是刚才的消息内容?
4、查看消息:消息消费之后,我们可以看到数据表没有消息了:

Sql代码  
  1. mysql> SELECT * FROM activemq_msgs;   
  2. Empty set  
 


5、我们可以生产多条消息,然后一条一条的消费,发现消息表中的消息一条一条的减少;
6、在发送消息页面,“Destination Type”如果选择“Topic”的话,则消息表中并没有数据,原因在于“Queue”为ptp模式消息,“Topic”为发布/订阅模式消息,当没有订阅者时,消息直接丢掉了。

JMS的内容先介绍到这里,下面我将结合Spring来启动AMQ(即AMQ与应用一同启动,上面介绍的都是单独的启动),通过测试代码来发送和消费消息,敬请期待!

------------------------
欢迎大家批评指正:
http://obullxl.iteye.com
http://www.cnblogs.com/obullxl
http://hi.baidu.com/obullxl
-----------------------

posted @ 2012-03-25 13:23  十二十二  阅读(588)  评论(0编辑  收藏  举报