ActiveMQ -- 中间件之运用(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013457570/article/details/84197100

                                           ActiveMQ -- 中间件

                                                            

一、ActiveMQ讲解

1.1、概念

概念:官方解释:Active是属于apache下的产品,是目前最流行、能力强劲的消息总线,完全是遵循JMS规范。

1.2、在现实中应用

activeMQ是分布式中注重要的中间件之一:主要解决应用解耦、异步消息、流量削锋、消息通讯场景。

例如:唯品会上我们下订单时候,总“提示用户:您的订单正在处理”,其实这里是将用户下的订单添加到消息队列中间件中,等待消费者去消费(库存),消费者(库存)通过推拉的形式的获取消息队列中的人物。

1.3、分析使用场景(借鉴原作者案例)

这一章节我就借鉴一片博客图片(未找到原作者),举的案例非常容易理解,我在其基础上进行补充。

1.3.1、异步信息处理

异步:顾名思义就是一个调用无需等待结果返回就让其继续操作,

场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种1.串行的方式;2.并行方式。

(1)串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。

(2)并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。

假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。

因为CPU在单位时间内处理的请求数是一定的,假设CPU1秒内吞吐量是100次。

则串行方式1秒内CPU可处理的请求量是7次(1000/150)。并行方式处理的请求量是10次(1000/100)。

 

小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。如何解决这个问题呢?

引入消息队列,将不是必须的业务逻辑,异步处理。改造后的架构如下:

按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。

注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,

因此用户的响应时间可能是50毫秒。所以基于此架构改变后,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍。


1.3.2、异步信息处理

场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。如下图:

传统模式的缺点:

1)  假如库存系统无法访问,则订单减库存将失败,从而导致订单失败;

2)  订单系统与库存系统耦合;

如何解决以上问题呢?引入应用消息队列后的方案,如下图:

1:订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功,请等待物流配送。
2:库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作。
3:假如:在下单时库存系统不能正常使用。也不影响正常下单,
因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦。
 

1.3.3、流量削锋

流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛。

应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用容易挂掉。为解决这个问题,一般需要在应用前端加入消息队列。

  1. 可以控制活动的人数.
  2. 可以缓解短时间内高流量压垮应用;

  1. 用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面;
  2. 秒杀业务根据消息队列中的请求信息,再做后续处理。

1.3.3、消息通讯

消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

点对点通讯:

客户端A和客户端B使用同一队列,进行消息通讯。

聊天室通讯:

客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。实现类似聊天室效果。

以上实际是消息队列的两种消息模式,点对点或发布订阅模式。

1.4、activemq有自己的特点和优势:

(1)activemq可以很好的运行在任何JVM上,而不只是集成到JBoss的应用服务器中;

(2)activemq支持大量的跨语言客户端;

(3)activemq支持许多不同的协议,如Ajax,REST,Stomp,OpenWire,XMPP

(4)activemq支持许多高级功能,例如MessageGroups,ExclusiveConsumer,CompositeDestinations

(5)AdvisoryMessage

(6)activemq支持可靠连接并且具有可配置的自动重连接

(7)activemq对Spring有很好的支持

(8)activemq支持跨网络的分布式目的地

(9)activemq是速度非常快;一般要比jbossmq快10倍
 

二、ActiveMQ安装

2.1、下载ActiveMQ安装包

作为一个具有独立思考的程序老农,下载对应的版本都是从官网下载正宗的版本,官网路径Active官网《下载对应的版本》

进到首页如下:

点击进去之后,可以选择下载最新的版本,如果想下载历史版本

 

点击下载历史版本如下:

下载版本时候需要注意,下载对应的windown或者linux,根据自己的需要进行下载

 

 

2.2、ActiveMQ启动

为了简单且快速了解ActiveMQ,我直接下载window版本来进行演示,对应的Linux安装自己网上查询安装教程,其实很简单

我是下载时候安装如下:

启动步骤:bin-->win64(对应自己的系统)-->activemq.bat(启动)

启动成功如下图:

当启动显示"access to all MBeans is allowed"则表示ActiveMQ已经启动成功;接下来就可以直接访问了;

访问路径:http://localhost:8161/admin/

成功页面如下:

2.3、首次登录遇到问题

       首次登录的用户可能会有疑问,说端口号和登录密码是什么?这里我就来帮大家解答这问题,作为一个web开发者,相信大家都使用多web容器tomcat,tomcat在con.xml中都有配置默认的端口号,那当然ActiveMQ那必须有,因为ActiveMQ和tomcat的父母都是apache,不扯哪些没用的了,直接进入主题:

如果你是直接下载好的ActiveMQ:

默认端口号是:8161

登录账号和密码是:账号admins ;密码:admin

下面我们来看下ActiveMQ的配置文件就明白了,其实ActiveMQ中间件里面整合了简洁版的jetty容器,路径:conf -- >jetty.xml

登录密码查看或修改路径:conf-->groups.properties

到此为此ActiveMQ则安装完了,写的不好地方望网友多多指点,相互学习。

三、MQ程序测试

3.1、代码结构

这里编写简单的测试demo进行测试,需要的jar路径如下:

3.2、代码分析

3.2.1、生产者

package com.debug.test;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 生产者
 * @author debug
 * @Date 2018-1-18
 */
public class Sender {

	public static void sender() throws JMSException {
		// 1、建立ConnecttionFactory工厂连接对象,需要填入用户名、密码、以及连接地址,均使用默认就行
		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_PASSWORD,
				ActiveMQConnectionFactory.DEFAULT_PASSWORD, "tcp://localhost:61616");
		//2、通过工厂连接对象进行建立连接connection,并且开启连接(默认时关闭的)
		Connection connection = connectionFactory.createConnection();
		connection.start();
		
		//3、通过连接创建session会话(上下文环境对象),用于接受信息、参数配置:1为是否启用事务、参数配置2为签收模式、一般我们设置为自动签收。
		Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
		Destination destination = session.createQueue("queue01");
		
		//4、通过session获对象,指的时一个客户端用来指定生产消费目标合消费信息来源的对象,
		
		//5、我们需要通过sesion对象创建消息的发动合接受对象(生产者合消费者)MessageProducer/MessageConsumer
		MessageProducer messageProducer = session.createProducer(destination);
		
		//6、我们可以使用messageProducer的setDeiveryMode方法为其设置持久化性合非持久化(DeiveryMode)
		messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
		
		//7、最后发送信息(使用JMS规范)
		for (int i = 0; i <5; i++) {
			TextMessage textMessage = session.createTextMessage("我是debug");
			messageProducer.send(textMessage);
			System.out.println("生产者正在生产......."+ i);
		}
		System.out.println("生产者生产消息完成.......");
		
		//紧密判断
		if(connection != null){
			connection.close();
		}
		
		
	}

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

}

执行之后:

生产完成之后,我们来看下ActiveMQ控制后台:

 

3.2.2、消费者

package com.debug.test;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消费者
 * @author debug
 * @Date 2018-1-18
 */
public class Receiver {
	public static void sender() throws JMSException {
		// 1、建立ConnecttionFactory工厂连接对象,需要填入用户名、密码、以及连接地址,均使用默认就行
		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_PASSWORD,
				ActiveMQConnectionFactory.DEFAULT_PASSWORD, "tcp://localhost:61616");
		//2、通过工厂连接对象进行建立连接connection,并且开启连接(默认时关闭的)
		Connection connection = connectionFactory.createConnection();
		connection.start();
		
		//3、通过连接创建session会话(上下文环境对象),用于接受信息、参数配置:1为是否启用事务、参数配置2为签收模式、一般我们设置为自动签收。
		Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
		Destination destination = session.createQueue("queue01");
		
		//4、通过session获对象,指的时一个客户端用来指定生产消费目标合消费信息来源的对象,
		
		//5、我们需要通过sesion对象创建消息的发动合接受对象(生产者合消费者)MessageProducer/MessageConsumer
		MessageConsumer messageConsumer = session.createConsumer(destination);
		
		while(true){
			TextMessage msg = (TextMessage) messageConsumer.receive();
			if(msg == null){
				break;
			}
			System.out.println("消费者接受到的内容......." + msg.getText());
		}
		
		//紧密判断
		if(connection != null){
			connection.close();
		}
		
		
	}

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


}

执行之后:

此时ActiveMQ后台观察下

 

好了;目前来说demo测试已经完成了,后续有需要补充的地儿再接着完善......

 

 

 

 

 

展开阅读全文

没有更多推荐了,返回首页