JMS消息服务-ActiveMQ

来源:互联网 发布:数据分析 java 编辑:程序博客网 时间:2024/04/28 02:40

JMS消息服务-ActiveMQ

sf2gis@163.com

2015年7月28日

 

1  JMS消息服务

目标:网络或进程间的消息异步、同步通信、点对点或发布模式通信。将消息的收、发方解耦。

原理:Java提供JMS(Java Message Service)作为消息服务的规范,可以有不同的实现方法。发送方将消息发向JMS服务器,由JMS服务器处理消息后再发送到收取方。

参考:http://my.oschina.net/zmf/blog/368017

方法:开源消息服务软件,ActiveMQ。

2 方法:ActiveMQ服务器

2.1 打开服务器:bin\activemqstart。

注意:有可能出现VM创建错误,这是由于ActiveMQ默认需要1G内存,如果物理内存不足,则创建失败。可能通过释放内存,达到1G再启动。或者修改ActiveMQ的内存配置(推荐)。

启动成功后出现下图所示:access to all MBeans is allowed。

2.2 修改内存配置:activemq.bat。

修改第80行-Xms -Xmx为512m或更少。

参考:http://activemq.apache.org/javalangoutofmemory.html

2.3 关闭服务器:ctrl+C

2.4 打开WEB 控制台:localhost:8161,可以看到控制台和示例程序。

示例程序在webapps-demo/demo中,需要从其中copy到webapps中。

3 方法:消息收发模式:点对点,订阅

由消息服务器管理消息,收发双方独立联系服务器,消息的生命周期由消息服务器管理。

3.1 点对点:单线联系。

双方完全无关,不须维持在线状态。

3.2 订阅:广播。

临时订阅时,订阅者须维持在线状态。

持久订阅时,双方完全无关,不须维持在线状态。

3.3 消息持久化:存储消息,重启后消息依然存在。

可以指定数据库。

参考:http://bbs.paris8.org/viewthread.php?tid=4252

3.4 集群:扩展服务器

可以使用集群服务器扩展性能。

参考:http://blog.evercoding.net/2014/07/17/activemq-note/

4 方法:收发消息

目标:与消息服务器进行消息收发。

原理:收/发方通过与服务器建立连接,然后以session为单位建立单线程消息收/发。

方法:设置服务器地址和类型、编写收发逻辑。

参考:

http://baike.baidu.com/link?url=XaCsMIRVQEhZLTQB2jI1ysPQK0xUCKWaE9UQlFXVbPPKralw6XTFJHv8j6HnbcPMOjZYHFUMR5Ir_P6d2OE28kvtLTBCBLDHuvPyEC_rA0q

4.1 设置服务器:设置服务器的连接地址。

目标:配置mq服务器能够提供服务的IP地址。

方法:修改conf/activemq.xml中<transportConnectors>的连接选项,默认是tcp://0.0.0.0:61616。

具有多种类型的连接,如tcp,udp,http等。

参考:http://activemq.apache.org/configuring-transports.html

示例:添加新的tcp连接服务tcp://0.0.0.0:61618。

<transportConnectors>

            <!-- DOS protection, limitconcurrent connections to 1000 and frame size to 100MB -->

            <transportConnectorname="openwire"uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>           

            <transportConnector name="tcp"uri="tcp://0.0.0.0:61618?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

            <transportConnectorname="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

            <transportConnectorname="stomp"uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

            <transportConnectorname="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

            <transportConnectorname="ws"uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

        </transportConnectors>

4.2 建立连接:Connection。

4.2.1配置连接工厂:连接使用ConnectionFactory配置连接服务器,并由其创建连接。使用完成之后要关闭连接服务器和连接。

4.2.2建立连接:使用连接工厂生成一个连接。并使用start()启动连接。

只有启动连接才真正的建立连接。

4.2.3示例

           //create connection

           ConnectionFactory cf=newActiveMQConnectionFactory("tcp://localhost:61618");

           Connection conn = cf.createConnection();

           conn.start();

4.3 创建会话:Session,独立的消息队列。支持回滚。

4.3.1创建会话:使用连接创建一个独立的会话。createSession(transacted,acknowledgeMode)。

会话将指定是否支持事务,如果支持(true)则忽略acknowledgeMode。如果为不支持事务(false),则指定处理消息(如何确认接收)的方式。

处理方式:Session.AUTO_ACKNOWLEDGE,Session.CLIENT_ACKNOWLEDGE,Session.DUPS_OK_ACKNOWLEDGE。

参考:https://docs.oracle.com/javaee/7/api/javax/jms/Session.html#AUTO_ACKNOWLEDGE

示例:        Sessionsession=conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

4.3.2创建点对点消息队列:createQueue()。

Queue为点对点消息队列,一条消息只能被一个接收者使用。一个消息队列可以被多个接收方接收,mq自动进行负载平衡。

需要指定消息队列的名称,作为收发双方连接ID。

示例:Destination dest= session.createQueue("TEST.FOO");

4.3.3创建订阅主题:createTopic()。

Topic为点对多消息,一条消息可以被多个接收者使用。默认使用持久化存储。

需要指定主题的名称,作为收发双方连接ID。

参考:http://coderbase64.iteye.com/blog/2081937

示例:Destination dest = session.createTopic("TEST.FOO");

4.4 操作消息:消息的控制对象和内容

4.4.1消息控制对象:生产者MessageProducer,消费者MessageConsumer。

                 MessageProducer sender =session.createProducer(dest);

MessageConsumer receiver =session.createConsumer(dest);

4.4.2消息内容:createTextMessage()。

可以使用5种消息:

StreamMessage

Java基元值流的消息。其填充和读取均按顺序进行。

MapMessage

一组键--值对的消息。没有定义条目顺序。

TextMessage

Java字符串的消息(例如,XML消息)。

ObjectMessage

序列化Java对象的消息。

BytesMessage

连续字节流的消息。

示例:

                 Message msg = session.createTextMessage("thisis a msg from sender="+i+","

                                       + new Date().toString());

4.4.3发送消息:sender.sende(Msg)。

sender.send(msg);

4.4.4接收消息:receiver.receive()。

将阻塞,直至消息到来。

Message msg = receiver.receive();

4.5 关闭消息对象、会话、连接:

           // close

           receiver.close();

           session.close();

           conn.close();

5 示例

5.1 示例:点对点收发消息

Sender发送消息后,多个Receiver都能收到消息,但mq服务自动平衡负载,每个消息只能被处理一次。

//activemq.xml

<!--

    Licensed to the Apache Software Foundation(ASF) under one or more

    contributor license agreements.  See the NOTICE file distributed with

    this work for additional informationregarding copyright ownership.

    The ASF licenses this file to You under theApache License, Version 2.0

    (the "License"); you may not usethis file except in compliance with

    the License.  You may obtain a copy of the License at

 

    http://www.apache.org/licenses/LICENSE-2.0

 

    Unless required by applicable law or agreedto in writing, software

    distributed under the License isdistributed on an "AS IS" BASIS,

    WITHOUT WARRANTIES OR CONDITIONS OF ANYKIND, either express or implied.

    See the License for the specific languagegoverning permissions and

    limitations under the License.

-->

<!-- START SNIPPET:example -->

<beans

 xmlns="http://www.springframework.org/schema/beans"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd

  http://activemq.apache.org/schema/corehttp://activemq.apache.org/schema/core/activemq-core.xsd">

 

    <!-- Allows us to use system propertiesas variables in this configuration file -->

    <beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

        <propertyname="locations">

           <value>file:${activemq.conf}/credentials.properties</value>

        </property>

    </bean>

 

   <!-- Allows accessing the server log-->

    <bean id="logQuery"class="io.fabric8.insight.log.log4j.Log4jLogQuery"

          lazy-init="false"scope="singleton"

          init-method="start"destroy-method="stop">

    </bean>

 

    <!--

        The <broker> element is used toconfigure the ActiveMQ broker.

    -->

    <broker xmlns="http://activemq.apache.org/schema/core"brokerName="localhost" dataDirectory="${activemq.data}">

 

        <destinationPolicy>

            <policyMap>

              <policyEntries>

                <policyEntrytopic=">" >

                    <!-- TheconstantPendingMessageLimitStrategy is used to prevent

                         slow topic consumersto block producers and affect other consumers

                         by limiting the numberof messages that are retained

                         For more information, see:

 

                        http://activemq.apache.org/slow-consumer-handling.html

 

                    -->

                 <pendingMessageLimitStrategy>

                   <constantPendingMessageLimitStrategy limit="1000"/>

                 </pendingMessageLimitStrategy>

                </policyEntry>

              </policyEntries>

            </policyMap>

        </destinationPolicy>

 

 

        <!--

            The managementContext is used toconfigure how ActiveMQ is exposed in

            JMX. By default, ActiveMQ uses theMBean server that is started by

            the JVM. For more information, see:

 

            http://activemq.apache.org/jmx.html

        -->

        <managementContext>

            <managementContextcreateConnector="false"/>

        </managementContext>

 

        <!--

            Configure message persistence forthe broker. The default persistence

            mechanism is the KahaDB store(identified by the kahaDB tag).

            For more information, see:

 

           http://activemq.apache.org/persistence.html

        -->

        <persistenceAdapter>

            <kahaDBdirectory="${activemq.data}/kahadb"/>

        </persistenceAdapter>

 

 

          <!--

            The systemUsage controls themaximum amount of space the broker will

            use before disabling caching and/orslowing down producers. For more information, see:

           http://activemq.apache.org/producer-flow-control.html

          -->

          <systemUsage>

            <systemUsage>

                <memoryUsage>

                    <memoryUsagepercentOfJvmHeap="70" />

                </memoryUsage>

                <storeUsage>

                    <storeUsagelimit="100 gb"/>

                </storeUsage>

                <tempUsage>

                    <tempUsagelimit="50 gb"/>

                </tempUsage>

            </systemUsage>

        </systemUsage>

 

        <!--

            The transport connectors exposeActiveMQ over a given protocol to

            clients and other brokers. For moreinformation, see:

 

           http://activemq.apache.org/configuring-transports.html

        -->

        <transportConnectors>

            <!-- DOS protection, limitconcurrent connections to 1000 and frame size to 100MB -->

            <transportConnectorname="openwire"uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>           

            <transportConnector name="tcp"uri="tcp://0.0.0.0:61618?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

            <transportConnectorname="amqp"uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

            <transportConnectorname="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

            <transportConnectorname="mqtt"uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

            <transportConnectorname="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

        </transportConnectors>

 

        <!-- destroy the spring context onshutdown to stop jetty -->

        <shutdownHooks>

            <beanxmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook"/>

        </shutdownHooks>

 

    </broker>

 

    <!--

        Enable web consoles, REST and Ajax APIsand demos

        The web consoles requires by defaultlogin, you can disable this in the jetty.xml file

 

        Take a look at${ACTIVEMQ_HOME}/conf/jetty.xml for more details

    -->

    <importresource="jetty.xml"/>

 

</beans>

<!-- END SNIPPET: example-->

//Sender.java

import java.util.Date;

 

import javax.jms.Connection;

import javax.jms.Destination;

importjavax.jms.JMSException;

import javax.jms.Message;

importjavax.jms.MessageProducer;

import javax.jms.Session;

 

importorg.apache.activemq.ActiveMQConnectionFactory;

 

/**

 * @author sf2gis@163.com

 * @date 2015年7月28日上午11:10:51

 *

 */

public class Sender {

 

      public static void main(String[] args) throws JMSException,InterruptedException {

           // TODO Auto-generated method stub

           sendMsg();

      }

 

     

      /**

       * send messages to mqserver.

       *

       * @throws JMSException

       * @throwsInterruptedException

       */

      public static void sendMsg() throws JMSException,InterruptedException {

           // create connection

           ActiveMQConnectionFactory cf = newActiveMQConnectionFactory(

                      "tcp://localhost:61616");

           Connection conn = cf.createConnection("admin","admin");

           conn.start();

           System.out.println("create connection");

 

           // create session

           Session session = conn.createSession(false,Session.AUTO_ACKNOWLEDGE);

           System.out.println("create session");

           // create message

           Destination dest =session.createQueue("TEST.FOO");

           MessageProducer sender = session.createProducer(dest);

           for (int i = 0; i < 3; ++i) {

                 Message msg = session

                            .createTextMessage("this is a msgfrom sender="+i+","

                                       + new Date().toString());

                 sender.send(msg);

                 Thread.sleep(1000);

           }

           System.out.println("send a msg");

 

           // close

           sender.close();

           session.close();

           conn.close();

      }

}

 

//Receiver.java

import java.util.Date;

 

import javax.jms.Connection;

importjavax.jms.ConnectionFactory;

import javax.jms.Destination;

import javax.jms.JMSException;

import javax.jms.Message;

importjavax.jms.MessageConsumer;

import javax.jms.Session;

import javax.jms.TextMessage;

 

importorg.apache.activemq.ActiveMQConnectionFactory;

 

/**

 * @author sf2gis@163.com

 * @date 2015年7月28日下午3:56:20

 *

 */

public class Receiver {

 

      public static void main(String[] args) throws JMSException {

           // TODO Auto-generated method stub

           receiveMsg();

      }

 

      /**

       * receive messages frommq server.

       *

       * @throws JMSException

       */

      public static void receiveMsg() throws JMSException {

           // create connection

           ConnectionFactory cf = new ActiveMQConnectionFactory(

                      "tcp://localhost:61618");

           Connection conn = cf.createConnection();

           conn.start();

 

           // create session

           Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

           Destination dest =session.createQueue("TEST.FOO");

           MessageConsumer receiver = session.createConsumer(dest);

           System.out.println("waiting msg...");

           int i = 0;

           while (i != 100) {

                 Message msg = receiver.receive();

                 // get msg

                 if (msg instanceof TextMessage) {

                      TextMessage txt = (TextMessage) msg;

                      System.out.println("ReceiveMsg " + i+ "=" + txt.getText()

                                  + ",now=" + newDate().toString());

                 } else {

                      System.out.println(msg);

                 }

                 ++i;

           }

 

           // close

           receiver.close();

           session.close();

           conn.close();

      }

}

 

5.2 示例:订阅收发消息

Sender发送消息后,多个Receiver能同时收到消息。

//activemq.xml

同上。

//Sender.java

import java.util.Date;

 

import javax.jms.Connection;

import javax.jms.Destination;

importjavax.jms.JMSException;

import javax.jms.Message;

importjavax.jms.MessageProducer;

import javax.jms.Session;

 

importorg.apache.activemq.ActiveMQConnectionFactory;

 

/**

 * @author sf2gis@163.com

 * @date 2015年7月28日上午11:10:51

 *

 */

public class Sender {

 

      public static void main(String[] args) throws JMSException,InterruptedException {

           // TODO Auto-generated method stub

           sendMsg();

      }

 

     

      /**

       * send messages to mqserver.

       *

       * @throws JMSException

       * @throwsInterruptedException

       */

      public static void sendMsg() throws JMSException,InterruptedException {

           // create connection

           ActiveMQConnectionFactory cf = newActiveMQConnectionFactory(

                      "tcp://localhost:61616");

           Connection conn = cf.createConnection("admin","admin");

           conn.start();

           System.out.println("create connection");

 

           // create session

           Session session = conn.createSession(false,Session.AUTO_ACKNOWLEDGE);

           System.out.println("create session");

           // create message

           Destinationdest = session.createTopic("TEST.FOO");

           MessageProducer sender = session.createProducer(dest); 

           for (int i = 0; i < 3; ++i) {

                 Message msg = session

                            .createTextMessage("this is a msgfrom sender="+i+","

                                       + new Date().toString());

                 sender.send(msg);

                 Thread.sleep(1000);

           }

           System.out.println("send a msg");

 

           // close

           sender.close();

           session.close();

           conn.close();

      }

}

//Receiver.java

import java.util.Date;

 

import javax.jms.Connection;

importjavax.jms.ConnectionFactory;

import javax.jms.Destination;

importjavax.jms.JMSException;

import javax.jms.Message;

importjavax.jms.MessageConsumer;

import javax.jms.Session;

import javax.jms.TextMessage;

 

importorg.apache.activemq.ActiveMQConnectionFactory;

 

/**

 * @author sf2gis@163.com

 * @date 2015年7月28日下午3:56:20

 *

 */

public class Receiver {

 

      public static void main(String[] args) throws JMSException {

           // TODO Auto-generated method stub

           receiveMsg();

      }

 

      /**

       * receive messages frommq server.

       *

       * @throws JMSException

       */

      public static void receiveMsg() throws JMSException {

           // create connection

           ConnectionFactory cf = new ActiveMQConnectionFactory(

                      "tcp://localhost:61618");

           Connection conn = cf.createConnection();

           conn.start();

 

           // create session

           Session session = conn.createSession(false,Session.AUTO_ACKNOWLEDGE);

           Destinationdest = session.createTopic("TEST.FOO");

           MessageConsumer receiver = session.createConsumer(dest);

           System.out.println("waiting msg...");

           int i = 0;

           while (i != 100) {

                 Message msg = receiver.receive();

                 // get msg

                 if (msg instanceof TextMessage) {

                      TextMessage txt = (TextMessage) msg;

                      System.out.println("ReceiveMsg " + i+ "=" + txt.getText()

                                  + ",now=" + newDate().toString());

                 } else {

                      System.out.println(msg);

                 }

                 ++i;

           }

 

           // close

           receiver.close();

           session.close();

           conn.close();

      }

}

 

0 0
原创粉丝点击