MQ acquaintance --Activemq

    Currently the Internet is basically a distributed architecture of the system is inseparable from the message middleware, that is, the blog post to talk about, and then we get to know about the friends.

MQ have to submit asynchronous decoupling talked about this concept, so they took down the electricity supplier orders, for example (Orders are generally involved in all processes SMS, logistics, mail, etc.), the following picture as an example to illustrate.

Introduction of Application

Application of Decoupling

  1. And do not bind the thread pool, do not write text messages threaded tasks, such as logistics threaded tasks
  2. Even if the logistics system hung up, take a few minutes to repair, the message in this message a few minutes logistics system to be processed are cached in the MQ, the orders will not affect the user, when the system is restored, supplemental information is stored in order in the MQ to end customers unaware of the logistics system failure, upgrade experience.

 Consumers peak flow

        Taobao double eleven most of the traffic will surge during this time if there is no buffer mechanism unsustainable, the MQ request by staging up, disperse over a longer period of time to deal with, which is what we double eleven Why to zero, an order can not be a place of feeling, but in fact the traffic peak and not because of lack of capacity, but out of economic principles, such as some business systems will not exceed the peak flow 10000QPS, usually only 1000QPS, in this case you can use an ordinary server (supports 1000QPS can), then add a message queue as the peak of the buffer without large sums of money to buy servers.

Message Distribution

       In the era of big data, data is constantly generated, each team analysis, algorithms team needs to rely on these data to work, this time there is a persistent message queue is particularly important. Only needs to generate data aspects written into the respective messages to the message queue to, consumer subscription data of the data of interest according to their respective needs, different teams subscription message can be repeated may not be repeated, and do not interference, and do not have associated data producers.

       Each subsystem log data continuously written to the message queue, data processing systems have different respective Offset, independently of each other. Even processed data of the respective groups may also be written to a message queue, as produced party data, and to other groups, to avoid double counting.

Guarantee eventual consistency

 

 

Dynamic expansion

 

 

Messaging middleware concept

1. What is the Message-Queue messaging middleware

  • Using the message mechanism efficiently and reliably data exchange platform-independent
  • To realize the data communication based on distributed systems integration
  • By providing messaging and message queuing model, it can be extended to communication between processes in a distributed environment
  • Essentially accept requests -> Save Data -> Data transmission

2, messaging middleware application scenario

  • Data transfer across the system, a high peak and the concurrent flow, asynchronous data processing, and the like Decoupling

3, common messaging middleware

  • ActiceMq、RabbitMq、Kafka、RocketMq

protocol

       Protocol is a set of conventions comply common computer communication, the rules and the format of data between computers must follow when exchanging data. (Http protocol heavy, light use protocol) messaging middleware protocol: OpenWire, AMQP, MQTT, Kafka, OpenMessage

  1.  AMQP (Advanced Message Queuing Protocol) protocol: Advanced Message Queuing Protocol. Features: transaction support, support persistence born in the financial sector, have a natural advantage in reliable message handling. With this agreement MQ: ActiceMq, RabbitMq
  2.  MQTT (Message Queue Telemetry Transport) protocol: a message queue telemetry transmission, a chat communication protocol developed by IBM, part of the system architecture things Central Asia. Features: Lightweight, simple structure, no fast transfer transaction support, there is no persistence related design, application scenarios: for limited computing power, low bandwidth network unstable scene. With this agreement MQ: ActiceMq, RabbitMq
  3.  OpenMessage last couple of years have initiated Ali, Yahoo, and pieces travel, Streamlio other companies to participate in the creation of distributed messaging middleware agreement to develop a standard stream processing applications, is the first launched worldwide distribution international standard message type field. Features: simple structure, resolved quickly, there are transaction support, persistent and design. With this agreement MQ: Apache RocketMq
  4.  Kafka protocol: binary protocol is based on TCP, the message is separated by the internal length of the basic data types. Features: simple structure, resolve quickly without transaction support lasting design. With this agreement MQ: Kafka

Note: Persistence is simply the data to disk rather than stored in memory as the life-cycle services is consistent with the students with the dead, but is permanently stored data is called persistence.

ActiveMQ安装(得先安装JDK1.8以上版本)

1、下载后解压文件

       mkdir /usr/activemq 并将文件解压至此处文件夹 tar -zxvf apache-activemq-5.15.9-bin.tar.gz -C /usr/activemq  解压后目录如下(可以发现基本上和tomcat一模一样,其中data是存放日志文件,webapps是存放管理控制台程序目录 ,jar包为activemq全量包。)

2、创建软链接并启动    

      为方便写配置项,创建软链接    ln -s /usr/activemq/apache-activemq-5.15.9 /usr/activemq/latest  (和快捷方式一样,操作同一个文件)  

      启动:

  1. 进入bin目录     cd /usr/activemq/latest/bin   
  2. 后台守护进程启动 (稍等会会启动进程)  ./activemq start   备注:前台启动   ./activemq console

   2、检测是否启动成功

      方法一:访问管理控制台:http://ip:8161/admin ActiveMQ的管理页面默认开启了身份校验: 账号:admin 密码:admin 

      方法二:在启动Console 或 日志文件(data/activemq.log)中看到日志输出 

      方法三:或用jps命令查看 6193为启动的Pid

[root@zhujiname bin]# jps

6193 activemq.jar

6350 Jps

备注:输入网址,因为我这里是虚拟机所以以实际ip为准(可能会被防火墙拦截,记得关闭防火墙:service iptables stop,查看防火墙状态service iptables status)。


           
       

ActiveMQ使用

使用下载好的jar包 (在ActiveMQ目录有activemq-all-5.15.9jar包)或者使用maven依赖下载

<dependency>    
    <groupId>org.apache.activemq</groupId>    
    <artifactId>activemq-all</artifactId>    
    <version>5.15.9</version> 
</dependency>

如果是springboot那么请添加一下依赖

<dependency>    
    <groupId>org.springframework.boot</groupId>    
    <artifactId>spring-boot-starter-activemq</artifactId> 
</dependency>

普通web项目运行activemq

package activemq;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.util.Date;

/**
 * @author Heian
 * @time 19/08/14 12:22
 * @description: 消息生产者
 */
public class Producer {

    public static void main(String[] args) {
        //启动生产者
        ProducerThread producerThread = new ProducerThread ("tcp://192.168.32.130:61616","queue1");
        producerThread.start ();
    }

    static class ProducerThread extends Thread{
        String brokerUrl;
        String destinationUrl;

        public ProducerThread(String brokerUrl,String destinationUrl){
            this.brokerUrl = brokerUrl;
            this.destinationUrl = destinationUrl;
        }

        @Override
        public void run() {

            ActiveMQConnectionFactory connectionFactory;
            Connection connection;
            Session session;

            try {
                //1、创建连接工厂
                connectionFactory = new ActiveMQConnectionFactory (brokerUrl);
                //2、创建连接
                connection = connectionFactory.createConnection ();
                connection.start ();//一定要记得start
                //3、创建会话(可以创建一个或者多个session,我这里默认一个)
                // 第一个参数:是否开启事务。true:开启事务,第二个参数忽略。第二个参数:当第一个参数为false时,才有意义。消息的应答模式。1、自动应答2、手动应答。一般是自动应答。
                session = connection.createSession (false, Session.AUTO_ACKNOWLEDGE);
                //4、创建消息发送目标 (Topic 或者 Queue  都实现了Destination)
                Destination destination = session.createQueue (destinationUrl);
                //5、用目的地创建消息生产者
                MessageProducer producer = session.createProducer (destination);
                producer.setDeliveryMode (DeliveryMode.PERSISTENT);//设置递送模式(持久化/不持久化)
                //6、创建一条文本消息
                String str = "hello activemq:from" + Thread.currentThread ().getName () + ",时间:" + new Date (System.currentTimeMillis ());
                TextMessage message = session.createTextMessage (str);
                //7、通过producer推送消息
                producer.send (message);
                //8、清理 关闭连接
                session.close ();
                connection.close ();

            }catch (JMSException e){
                e.printStackTrace ();
            }
            super.run ();
        }
    }

}
package activemq;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * @author Heian
 * @time 19/08/14 20:13
 * @description: 消息消费者
 */
public class Consumer {


    public static void main(String[] args) {
        new ConsumerThread("tcp://192.168.32.130:61616","queue1").start ();
        new ConsumerThread("tcp://192.168.32.130:61616","queue1").start ();
    }

    static class ConsumerThread extends Thread{

        String brokerUrl;//ip+端口
        String destinationUrl;//目标队列

        public ConsumerThread(String brokerUrl,String destinationUrl){
            this.brokerUrl = brokerUrl;
            this.destinationUrl = destinationUrl;
        }

        @Override
        public void run() {
            ActiveMQConnectionFactory connectionFactory;
            Connection connection;
            Session session;
            MessageConsumer messageConsumer;//消息消费者
            try {
                //1、创建连接工厂
                connectionFactory = new ActiveMQConnectionFactory (brokerUrl);
                //2、创建连接
                connection = connectionFactory.createConnection ();
                connection.start ();//一定要启动
                //3、创建会话(可以创建一个或者多个session,我这里默认一个)类似于selector 可以同时监听多个连接
                // 第一个参数:是否开启事务。true:开启事务,第二个参数忽略。第二个参数:当第一个参数为false时,才有意义。消息的应答模式。1、自动应答2、手动应答。一般是自动应答。
                session = connection.createSession (false, Session.AUTO_ACKNOWLEDGE);
                //4、创建消息消费目标 (Topic 或者 Queue  都实现了Destination)
                Destination destination = session.createQueue (destinationUrl);
                //5、创建消息消费者
                messageConsumer = session.createConsumer (destination);
                //session.createDurableSubscriber ("topic",destinationUrl);持久订阅
                //6、接收消息,没有消息就持续等待  阻塞等待
                Message receiveMsg = messageConsumer.receive ();
                if (receiveMsg  instanceof TextMessage ){
                    System.out.println ("收到消息:" + ((TextMessage) receiveMsg).getText ());
                }else {
                    System.out.println (receiveMsg);
                }
                //8、清理 关闭连接
                messageConsumer.close ();
                connection.close ();
                session.close ();
            } catch (JMSException e) {
                e.printStackTrace ();
            }


        }
    }

}

可以看出其创建过程类似于我们的jdbc的创建,可参考下面的流程图:

现在分别启动一个生产和两个消费者:此时消费者已经消费了一个消息,但还有一个消费者处于阻塞状态,可查看前台页面

如果生产者创建的topic,消费者也订阅了(发布订阅),伪代码如下:那么生生产者发一条并且两个消费者订阅了,那么这两个消费者都会收到消息。

引出问题?

       如何是先运行生产者,在运行消费者,也就是生产者生产了1条数据,两个消费者处于等待,那么这两个消费者会收到消息吗?答案是并不会,就像你订阅报纸一样,你开始都没订阅人家报纸,人家为什么还给你送报纸,对吧。如果想要收到,就必须的持久订阅。

备注:在发布订阅模式下,订阅者只会收到发布者的订阅以后的消息;在持久订阅模式下(在MQ登记一个有名的订阅),当前消费者消费了一段时间后可能挂了,此时发布者会将没传递到你的消息存起来,当你复活起来后,继续给你推送未收到的消息。

//生产者 
public static void main(String[] args) { 
        ProducerThread producerThread = new ProducerThread("tcp://192.168.32.130:61616","topic1");                      
        producerThread.start ();
    }
//消费者
public static void main(String[] args) {
        new ConsumerThread("tcp://192.168.32.130:61616","topic1").start ();
        new ConsumerThread("tcp://192.168.32.130:61616","topic1").start ();
    }

SpringBoot项目运行activemq

yaml配置:

spring:
  activemq:
    broker-url: tcp://192.168.32.130:61616
    #user:admin
    #password:admin

配置类:第一配置:连接mq实例配置Bean      第二个配置:对象序列化转成json类型配置Bean

package com.example.customers.activemq.day1;

import javax.jms.ConnectionFactory;

import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;

@Configuration
public class JmsConfiguration {

	//定义 连接mq实例的工厂类  如果是多个mq实例,则要建立连接工厂,单机测试的话可有可无
	@Bean
	public DefaultJmsListenerContainerFactory myFactory(ConnectionFactory connectionFactory,
			DefaultJmsListenerContainerFactoryConfigurer configurer) {
		System.out.println ("----------创建工厂连接监听器--------------");
		DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
		configurer.configure(factory, connectionFactory);
		return factory;
	}

	@Bean // 序列化对象在将其转成json形式
	public MessageConverter jacksonJmsMessageConverter() {
		MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
		converter.setTargetType(MessageType.TEXT);
		converter.setTypeIdPropertyName("_type");
		return converter;
	}

}

生产者:

package com.example.customers.activemq.day1;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jms.core.JmsTemplate;

import javax.annotation.PostConstruct;

/**
 * @author Heian
 * @time 19/08/15 21:47
 * @description: 生产者发送对象出去
 */
@SpringBootApplication
public class Producer {

    @Autowired
    private JmsTemplate jmsTemplate;

    @PostConstruct
    public void sendMessage() {
        // 发送对象出去
        System.out.println("-----发送短信中-----");
        jmsTemplate.convertAndSend("destinationName", new Emails ("[email protected]", "hello 1"));
        jmsTemplate.convertAndSend("destinationName", new Emails ("[email protected]", "hello 2"));
    }

    public static void main(String[] args) {
        SpringApplication.run(Producer.class, args);
    }

}

消费者:

package com.example.customers.activemq.day1;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

/**
 * @author Heian
 * @time 19/08/15 21:51
 * @description: 消费者接受对象
 */
@Component
public class Consumer {

    //会启动线程池创建监听线程不断的轮询指定目标地址是否有消息   必须指定连接工厂myFactory,否则无法收到消息
    @JmsListener(destination = "destinationName",containerFactory = "myFactory")
    public void receive(Emails email) {
        System.out.println(Thread.currentThread().getName() + "接受到的消息" + email);
    }

}

传输对象实体类       

package com.example.customers.activemq.day1;

/**
 * @author Heian
 * @time 19/08/15 21:36
 * @description: 测试activemq
 */
public class Emails {

    private String emailsUrl;
    private String emailsContent;

    public Emails() {
    }

    public Emails(String emailsUrl, String emailsContent) {
        this.emailsUrl = emailsUrl;
        this.emailsContent = emailsContent;
    }

    public String getEmailsUrl() {
        return emailsUrl;
    }

    public void setEmailsUrl(String emailsUrl) {
        this.emailsUrl = emailsUrl;
    }

    public String getEmailsContent() {
        return emailsContent;
    }

    public void setEmailsContent(String emailsContent) {
        this.emailsContent = emailsContent;
    }

    @Override
    public String toString() {
        return "Emails{" +
                "emailsUrl='" + emailsUrl + '\'' +
                ", emailsContent='" + emailsContent + '\'' +
                '}';
    }
}

此时启动生产者,会扫描路径同时消费者也会启动,即生产者生产了两条信息,消费者自然也会消费两条,类比发布订阅。

发布了73 篇原创文章 · 获赞 18 · 访问量 1万+

Guess you like

Origin blog.csdn.net/qq_40826106/article/details/97977395