Understand the basic use of JMS and ActiveMQ

Original link:

http://www.cnblogs.com/luochengqiuse/p/4678020.html

I have used mq in my recent project. Before, I have been taking pictures of gourds and scoops like code farmers. I have studied it in the past few days, and summarized all the documents and understandings I have read.

1. Understanding JMS

1 Overview

For JMS, Baidu Encyclopedia describes it like this: JMS, the Java Message Service (Java Message Service) application program interface, is an API for message-oriented middleware (MOM) in the Java platform, which is used between two application programs, Or send messages in a distributed system for asynchronous communication. Java Message Service is a platform-independent API, and most MOM providers support JMS.

In short, JMS is a vendor-neutral API for accessing messaging system messages. It is similar to JDBC (Java Database Connectivity) and provides the function of asynchronous communication between applications.

JMS1.0 is the specification specified in jsr 194 (for the jsr specification, please click). The latest specification is JSR 343, JMS2.0.

Well, having said so much, I'm just saying that JMS is just a set of api interfaces defined by sun company in order to unify the interface specifications of manufacturers.

2. JMS Architecture

Described as follows:

  • JMS provider (implementer of JMS, such as activemq jbossmq, etc.)
  • JMS client (a program or object that uses the provider to send messages, for example, in 12306, is responsible for sending a ticket purchase message to the processing queue to solve the problem of peak ticket purchases, then, the program that sends messages to the queue and gets messages from the queue programs are called clients)
  • JMS producer, JMS consumer (producer and client responsible for creating and sending messages, consumer is the client responsible for receiving and processing messages)
  • JMS messages (objects that pass data between JMS clients)
  • JMS queue (an area that holds messages that are sent waiting to be read)
  • JMS topic (a mechanism that supports sending messages to multiple subscribers)

3. JMS Object Model

  • The connection factory (connectionfactory) The client uses JNDI to find the connection factory, and then uses the connection factory to create a JMS connection.
  • A JMS connection represents an active connection between a JMS client and a server, and is established by the client by calling the connection factory method.
  • JMS session session identifies the session state of the JMS client and server. A session is established over a JMS connection and identifies a session process between the client and the server.
  • JMS purpose Destinatio, also known as message queue, is the actual message source
  • producer and consumer
  • Message type, divided into queue type (priority in first out) and subscription type

2. ActiveMQ

1. Installation of ActiveMQ

  1. Download the installation package from the official website, http://activemq.apache.org/download.html
  2. Grant running permission chmod +x, windows can ignore this step
  3. run ./active start | stop

After startup, activeMQ will occupy two ports, one is the tcp port responsible for receiving and sending messages: 61616, and the other is the web-based port responsible for user interface management: 8161. These two ports can be found in the xml below conf. The http server uses jettry.
There is a problem here that after starting mq, it takes a long time for the management interface to be displayed.

2. Access ActiveMQ with Java

First attach the Bean code:

public class MqBean implements Serializable{
    private Integer age;
    private String name;
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

2.1 Sending of queue messages:

public static void main(String[] args) {
    ConnectionFactory connectionFactory;
    Connection connection;
    Session session;
    Destination destination;
    MessageProducer producer;
    connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.159:61616");
    try {
        connection = connectionFactory.createConnection();
        connection.start();
        //第一个参数是是否是事务型消息,设置为true,第二个参数无效
        //第二个参数是
        //Session.AUTO_ACKNOWLEDGE为自动确认,客户端发送和接收消息不需要做额外的工作。异常也会确认消息,应该是在执行之前确认的
        //Session.CLIENT_ACKNOWLEDGE为客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会删除消息。可以在失败的
        //时候不确认消息,不确认的话不会移出队列,一直存在,下次启动继续接受。接收消息的连接不断开,其他的消费者也不会接受(正常情况下队列模式不存在其他消费者)
        //DUPS_OK_ACKNOWLEDGE允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。在需要考虑资源使用时,这种模式非常有效。
        //待测试
        session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        destination = session.createQueue("test-queue");
        producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        //优先级不能影响先进先出。。。那这个用处究竟是什么呢呢呢呢
        MqBean bean = new MqBean();
        bean.setAge(13);
        for(int i=0;i<100;i++){
            bean.setName("小黄"+i);
            producer.send(session.createObjectMessage(bean));
        }
        producer.close();
        System.out.println("呵呵");
    } catch (JMSException e) {
        e.printStackTrace();
    }
}

Note: In the above code, there are three confirmation modes, DUPS_OK_ACKNOWLEDGE and AUTO_ACKNOWLEDGE have never understood the difference. Because it can't be tested. But probably also understand some. In fact, it is mainly determined by the process of MQ processing messages:

  1. Messages are delivered from the producer client to the message server.
  2. The message server reads the message.
  3. Messages are placed into persistent storage (for reliability reasons).
  4. The message server acknowledges receipt of the message (for reliability reasons).
  5. The message server determines the routing of messages.
  6. The message server writes out the message.
  7. Messages are delivered from the message server to the consuming client.
  8. The consuming client acknowledges receipt of the message (for reliability reasons).
  9. The message server handles client acknowledgments (for reliability reasons).
  10. The message server determines that the client acknowledgment has been processed.

These steps are sequential, so any step can become a bottleneck in the delivery of messages from the producing client to the consuming client. Most of these steps depend on the physical characteristics of the messaging system: network bandwidth, computer processing speed, message server architecture, and so on. However, some steps also depend on the characteristics of the messaging application and the level of reliability that the application requires.
In fact, it is a choice based on reliability or performance.

2.2 Reception of queue messages:

public static void main(String[] args) {
    ConnectionFactory connectionFactory;
    // Connection :JMS 客户端到JMS Provider 的连接  
    Connection connection = null;
    // Session: 一个发送或接收消息的线程  
    Session session;
    // Destination :消息的目的地;消息发送给谁.  
    Destination destination;
    // 消费者,消息接收者  
    MessageConsumer consumer;
    connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.159:61616");
    try {
        // 构造从工厂得到连接对象  
        connection = connectionFactory.createConnection();
        // 启动  
        connection.start();
        // 获取操作连接  
        //这个最好还是有事务
        session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
        // 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置  
        destination = session.createQueue("test-queue");
        consumer = session.createConsumer(destination);
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                try {
                    MqBean bean = (MqBean) ((ObjectMessage)message).getObject();
                    System.out.println(bean);
                    if (null != message) {
                        System.out.println("收到消息" + bean.getName());
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Note: For queues, a relatively simple optimization strategy should be queue offloading. Since each consumer is single-threaded, multiple consumers can be set up to improve speed.
You can copy a consumer to test it yourself, and add sleep to the consumer to test the effect.

2.3 Sending subscription messages

public static void main(String[] args) {
    ConnectionFactory connectionFactory;
    Connection connection;
    Session session;
    Destination destination;
    MessageProducer producer;
    connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.159:61616");
    try {
        connection = connectionFactory.createConnection();
        connection.start();

        session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        destination = session.createTopic("test-topic");
        producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        //优先级不能影响先进先出。。。那这个用处究竟是什么呢呢呢呢
        MqBean bean = new MqBean();
        bean.setAge(13);
        for(int i=0;i<100;i++){
            Thread.sleep(1000);
            bean.setName("小黄"+i);
            producer.send(session.createObjectMessage(bean));
        }
        producer.close();
        System.out.println("呵呵");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2.4 Reception of subscription messages

public static void main(String[] args) {
    ConnectionFactory connectionFactory;
    // Connection :JMS 客户端到JMS Provider 的连接  
    Connection connection = null;
    // Session: 一个发送或接收消息的线程  
    Session session;
    // Destination :消息的目的地;消息发送给谁.  
    Destination destination;
    // 消费者,消息接收者  
    MessageConsumer consumer;
    connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.159:61616");
    try {
        // 构造从工厂得到连接对象  
        connection = connectionFactory.createConnection();
        // 启动  
        connection.start();
        // 获取操作连接  
        //这个最好还是有事务
        session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
        // 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置  
        destination = session.createQueue("test-queue");
        consumer = session.createConsumer(destination);
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                try {
                    MqBean bean = (MqBean) ((ObjectMessage)message).getObject();
                    System.out.println(bean);
                    if (null != message) {
                        System.out.println("收到消息" + bean.getName());
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}

After the above message is sent, if you do not receive it, you can log in to your own MQ management page: http://192.168.3.159:8161/admin/ , the default account password is admin, and you can view the messages in the queue

enter image description here

Number Of Pending Messages Messages waiting to be consumed This is the number of currently unqueued. It can be understood as the total number of receptions - the total number of queues out.
Messages Enqueued The total number of messages entering the queue, including those that are out of the queue. This number only increases and does not
decrease Messages Dequeued Messages out of the queue can be understood as the amount consumed

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325400873&siteId=291194637