消息中间件

消息中间件是指利用高效可靠的消息传递机制进行平台无关的数据交流,并且基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,可以在分布式架构下扩展进程之间的通信。

消息中间件能做什么

消息中间件主要解决分布式系统之间消息的传递问题 ,能够屏蔽各种平台以及协议之间的特性,实现应用之间的协同。

示例:

电商平台中的注册功能,用户注册不单是向数据库insert,可能还需要赠送积分,发送邮件,发送短信等系列操作。

假如:每个操作都耗时1s,那么注册过程就需要耗时4s才能响应给用户。从注册这个服务可以看出,每个子操作都是独立的,同时,基于领域划分以后,它们都属于不同的子域。所以我们可以对这些子操作实现异步化操作。类似多线程并行处理。

如何实现异步化?用多线程能实现吗?多线程当然可以实现,只是,消息的持久化、消息的重发这些条件,多线程 并不能满足.所以需要借助一些开源的消息中间件来解决。 而分布式消息队列就是一个很好的解决办法。通过引入分布式队列,大大提升程序的处理效率,并且还解决了各个模块之间的耦合问题。

分布式消息队列解决的场景:

引入消息中间件后(异步处理),电商平台中的注册架构图变为

电商中的秒杀:

用户提交过来的请求,先写入消息队列。消息队列是有长度的,如果消息队列超过指定长度,直接抛弃。

秒杀的 具体核心处理业务,接收消息队列中消息进行处理。这里的消息处理能力取决于消费端本身的吞吐量。

解耦、异步化、流量整形、数据的最终一致性(最大化的重试完成数据一致性)

ActiveMQ 简介

ActiveMQ

ActiveMQ 是完全基于JMS 规范实现的一个消息中间件产品,是Apache 开源基金会研发的消息中间件。ActiveMQ 主要应用在分布式系统架构中,帮助构建高可用、高性能、可伸缩的企业级面向服务的系统。

ActiveMQ 特性

  • 多语言和协议编写客户端

    • 语言:Java、C、C++、C#、Ruby、Perl、Python、PHP

    • 协议:openwire、stomp、REST、ws、notification、xmpp、AMQP

  • 完全支持JMS1.1和J2EE1.4规范

  • 对Spring的支持,ActiveMQ可以很容易的嵌入到spring模块中

ActiveMQ 下载安装启动

下载地址

http://activemq.apache.org/activemq-5158-release.html

解压

tar -zxvf apache-activemq-5.15.8-bin.tar.gz

启动服务

  • cd apache-activemq-5.15.8/bin

    sh activemq start

  • 启动并带指定日志文件 sh activemq start > /tmp/activemqlog

关闭服务

  • sh activemq stop

监控地址

http://192.168.15.134:8161/admin/ admin admin

ActiveMQ 的端口61616

  • 默认为61616

  • 检查是否成功启动ActiveMQ

    • netstat -an|grep 61616

JMS 基本概念和模型

JMS的定义

JMS(Java Message Service) :面向消息中间件的API

MOM(Message Oriented Middleware):面向消息中间件

Java 消息服务是Java平台中关于面向消息中间件的API,用于两个程序 之间,或者分布式系统中发送消息,进行异步通信。

JMS 是一个与具体平台无关的API,绝大多数MOM 提供商都对JMS提供了支持。ActiveMQ就是其中的一个实现。

MOM

MOM 是面向消息的中间件,使用消息传送提供者来协调消息传送操作。 MOM 需要提供API和管理工具。客户端使用API调用,把消息发送到由提供者管理的目的地。在发送消息后,客户端会继续执行其他工作,并且在接收方收到这个消息确认之前,提供者一直保留该消息。

MOM 的特点

  • 消息异步接收,发送者不需要等待消息接受者响应

  • 消息可靠接收,确保消息中间件可靠保存。只有接收方收到消息后才删除消息

开源JMS提供商

JbossMQ(jboss4)、Jboss messaging(jboss5)、joram、ubermq、mantamq、openjms ...

JMS 规范

JMS 规范的目的是为了使得Java 应用程序能够访问现有MOM(消息中间件)系统,形成一套统一的标准规范,解决不同消息中间件之间的协作问题。

  • 不同消息的传递域,点对点消息传送和发布/订阅消息传送

  • 提供接收同步和异步消息的工具

  • 对可靠消息传送的支持

  • 常见消息格式,例如流、文本和字节

JMS 的体系结构

JMS 的基本功能

JMS 的基本功能是用于和面向消息中间件相互通信的应用程序的接口

消息传递域

  • p2p(point-2-point) 点对点消息传递域

    • 每个消息只能有一个消费者(离线存储)

      • 类似QQ聊天的私聊

    • 生产者和消费者之间没有时间上的相关性,无论消费者在生产者发送消息的时候是否处于运行状态,都可以提取消息

    • 如果session关闭时,有一些消息已经被收到,但是没有被签收,消费者下一次连接到相同对列时,这些消息仍然会被接收

    • 如果用户在receive 方法中设定了消息的选择条件(消息过滤)

    • 如果是持久化消息,消息会被持久化保存,直到消息被签收

  • 发布订阅(publish/subscribe)消息传递域

    • 每个消息有多个消费者

      • 类似QQ群聊

    • 生产者和消费者有时间上的相关性

      • 订阅一个主题的消费者只能消费自它订阅之后发布的消息。

      • JMS 规范允许客户创建持久订阅,一定程度上降低了时间的相关性要求

      • 持久订阅允许消费者消费它在未处于激活状态时发送的消息

    • 持久化订阅和非持久化订阅

    • 在非持久化订阅的前提下,不能恢复或者重新指派一个未签收的消息;

    • 如果所有消息必须要签收,则使用持久订阅

消息的组成

消息头(Header)

消息头包含消息的识别信息和路由信息

消息头包含一些标准的属性:

  • JMSDestination

    • 消息发送的目的地,queue或者topic

  • JMSDeliveryMode

    • 传送模式,持久化模式和非持久模式

  • JMSPrority

    • 消息优先级(优先级分为10个级别,从0最低-9最高)

    • 如果不设定优先级,默认级别4,需要注意的是,JMS Provider 并不一定保证按照优先级的顺序提交

  • JMSMessageID

    • 唯一识别每个消息的标识

消息体

就是我们需要传递的消息的内容

JMS API定义了5种消息体格式:

  • TextMessage

    • java.lang.String 对象,如xml文件内容

  • MapMessage

    • 名/值对的集合,名是String 对象,值可以是Java 任何基本类型

  • BytesMessage

    • 字节流

  • StreamMessage

    • Java 中的输入输出流

  • ObjectMessage

    • Java 中的可序列化对象

  • Message

    • 没有消息体,只有消息头和属性

消息的属性

按类型分为:

  • 应用设置的属性

    • Message.setStringProperty(key,value);

  • 标准属性

    • 使用“JMSX” 作为属性名的前缀

  • 消息中间件定义的属性

    • JMS Provider 特定的属性

JMS 的可靠机制

消息的确认方式

消息的处理阶段:

  • 客户端接收消息

  • 客户端处理消息

  • 消息被确认

会话存在两种机制:

  • 事务性会话

    • createSession(boolean transacted, int acknowledgeMode)

      • Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);

    • session.commit() //消息被确认 事务提交意味着生产的所有消息被发送,消费的所有消息被确认

    • session.rollback(); //重新处理 消息没有被提交,没有被处理,消费端的所有消息被恢复,并且重新被提交, 表示一个事务结束, 另一个事务会开始。事务回滚意味着生产的所有消息被销毁,消费的所有消息 被恢复并重新提交,除非它们已经过期

    • 通过session.commit() //完成事务的签收

  • 非事务性会话

    • transacted 设置为FALSE

    • Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);

    • 客户端签收模型

    • Session session = connection.createSession(Boolean.FALSE, Session.CLIENT_ACKNOWLEDGE);

    • 那么需要手动签收

    • textMessage.acknowledge();

    • 客户端延迟确认,消息可能重复消费

      • Session session = connection.createSession(Boolean.FALSE, DUPS_OK_ACKNOWLEDGE);

事务性的自动确认

非事务性的自动确认和手动确认

消息的持久化存储

持久化(存储在数据库或磁盘)

producer.setDeliveryMode(DeliveryMode.PERSISTENT);

对于持久消息,消息提供者会使用存储-转发机制,先将消息存储到稳定的介质中,等消息发送成功后再删除。如果JMS Provider 宕机,那么这些未送达的消息则不会丢失,JMS Provider 恢复正常后,会重新读取这些消息,并传送给对应的消费者。

非持久化(存储在内存中)

producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

对于非持久化消息,JMS Provider 不会将它存到文件、数据库等稳定介质中。也就是说非持久消息,存储在内存中,如果JMS Provider 宕机,那么非持久化消息会丢失。

持久订阅

  • 持久订阅者和非持久订阅者针对的Domain 是Pub/Sub,而不是P2P

  • 当Broker 发送消息给订阅者时,如果订阅者处于未激活状态,持久订阅者可以收到消息,而非持久订阅者则收不到消息。

  • 当持久订阅者处于未激活状态时,Broker 需要为持久订阅者保存消息,如果持久订阅者订阅的消息太多则会溢出。

  • 持久订阅时,客户端向JMS 服务器注册一个自己身份的ID, 当这个客户端处于离线时,JMS Provider 会为这个ID 保存所有发送到主题的消息,当客户再次连接到 JMS Provider时,会根据自己的ID得到所有当自己处于离线时发送到主题的消息。

  • 持久订阅的方式(消费端)

    • connection.setClientID("test");

    • Topic destination=session.createTopic("myTopic");

    • MessageConsumer consumer=session.createDurableSubscriber(destination,"test");

JMS 规范结合ActiveMQ 实现消息发送

案例架构图

示例代码

引入Jar 包

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

生产端

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JMSQueueProducer {
public static void main(String args[]) {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.15.134:61616");
Connection connection = null;
try {
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//创建目的地
Destination destination = session.createQueue("myQueue");
//创建发送者
MessageProducer producer = session.createProducer(destination);
//持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
TextMessage textMessage = session.createTextMessage("Hello,World");
producer.send(textMessage);
session.commit();
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}

消费端

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import javax.xml.soap.Text;
public class JMSQueueConsumer { public static void main(String args[]) {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.15.134:61616");
Connection connection = null;
try {
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
//创建目的地
Destination destination = session.createQueue("myQueue");
//创建接收者
MessageConsumer consumer = session.createConsumer(destination);
//接收消息 阻塞方式监听消息
TextMessage textMessage =(TextMessage) consumer.receive();
System.out.println(textMessage.getText());
session.commit(); //表示消息被自动确认
session.close();
} catch (JMSException e) {
e.printStackTrace();
}finally {
if(connection!=null)
{
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}

  

分布式消息通信ActiveMQ的更多相关文章

  1. 分布式消息通信(ActiveMQ)

    分布式消息通信(ActiveMQ) 应用场景 异步通信 应用解耦 流量削峰 # ActiveMQ安装 下载 http://activemq.apache.org/ 压缩包上传到Linux系统 apac ...

  2. 分布式消息通信之RabbitMQ_01

    目录 官网 1. RabbitMQ安装 1.1 Window版安装 1.2 Linux版安装 2. 典型应用场景 3. 基本介绍 3.1 AMQP协议 3.2 RabbitMQ的特性 3.3 工作模型 ...

  3. 分布式消息通信Kafka-原理分析

    本文目标 TopicPartition 消息分发策略 消息消费原理 消息的存储策略 Partition 副本机制 1 关于 Topic 和 Partition 1.1 Topic 在 kafka 中, ...

  4. 分布式消息通信之RabbitMQ Tutorials

    目录 官网 1 Hello World! 1.1 生产者demo producer 1.2 消费者demo consumer 1.3 查看queue队列中的信息 页面查看,可看到有4条消息 命令查看 ...

  5. 分布式消息通信之RabbitMQ_Note

    目录 1. RabbitMQ 安装 2. RabbitMQ 应用场景,特性 3. 官网入门指引 4. RabbitMQ 工作模型 5. RabbitMQ 主要的几种交换机类型 6. Java API的 ...

  6. 分布式消息通信之RabbitMQ_02

    目录 1. 可靠性投递分析 1.1 消息投递 1.2 消息路由 1.3 消息存储 1.4 消息消费 1.5 其他 2. 高可用架构部署方案 2.1 集群 2.2 镜像 3. 经验总结 3.1 配置文件 ...

  7. 使用ActiveMQ实现JMS消息通信服务

    PTP(点对点的消息模型) 在点对点模型中,相当于两个人打电话,两个人独享一条通信线路.一方发送消息,一方接收消息. 在p2p的模型中,双方通过队列交流,一个队列只有一个生产者和一个消费者. 1.建立 ...

  8. Netty构建分布式消息队列实现原理浅析

    在本人的上一篇博客文章:Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇 中,重点向大家介绍了AvatarMQ主要构成模块以及目前存在的优缺点.最后以一个生产者.消费者传递消息的例子, ...

  9. 消息通信库ZeroMQ 4.0.4安装指南

    一.ZeroMQ介绍 ZeroMQ是一个开源的消息队列系统,按照官方的定义,它是一个消息通信库,帮助开发者设计分布式和并行的应用程序. 首先,我们需要明白,ZeroMQ不是传统的消息队列系统(比如Ac ...

随机推荐

  1. 【数据库】java链接jdbc 释放资源

    /* *   编写快速 入门的jdbc 程序 : *    *    1. 先导入 具体的驱动jar包 *    2. 编写一个类 , 写jdbc 的程序 *  *  具体的编写 java类的 代码的 ...

  2. PHP学习笔记(二) ---- PHP数据类型

    PHP  __数据结构类型 一.php 中的八种数据类型 1.四种标量类型 Boolean (布尔类型): true  or  false,多用于条件判断. 实例: <?php $x = &qu ...

  3. drupal7 用到的一些钩子简介

    1.hook_user_delete($account) 可用于自定义模块中,当用户被删除时,可以自定义一些自己需要的处理动作 2.hook_mail_alter(&$message) 可用于 ...

  4. Centos7 下安装Apache2 + MySQL + PHP7

    Apache 1.安装Apache yum install httpd 2.设置服务器开机自动启动Apache systemctl enable httpd.service 若要验证是否自动启动可在重 ...

  5. Eclipse调试不能进入断点

    Eclipse下在给行设置断点或者在调试时弹出错误“Unable to install breakpoint due to missing line number attributes,Modify ...

  6. Python3利用Dlib19.7实现摄像头人脸识别的方法

    0.引言 利用python开发,借助Dlib库捕获摄像头中的人脸,提取人脸特征,通过计算欧氏距离来和预存的人脸特征进行对比,达到人脸识别的目的: 可以自动从摄像头中抠取人脸图片存储到本地,然后提取构建 ...

  7. Oralce 序列

    序列: 是oacle提供的用于产生一系列唯一数字的数据库对象. l  自动提供唯一的数值 l  共享对象 l  主要用于提供主键值 l  将序列值装入内存可以提高访问效率 创建序列: 1.  要有创建 ...

  8. 自动化测试基础篇--Selenium unittest简介

    一.什么是unittest unittest是Python单元测试框架,类似于JUnit框架. unittest中有4个重要的概念:test fixture, test case, test suit ...

  9. 爬虫IP被禁的简单解决方法——切换UserAgent

    [转载]Python爬虫之UserAgent 用到的库 https://github.com/hellysmile/fake-useragent

  10. how to drop multiple talbes in oracle use a sigle query

    Tool:PL/SQL developer Syntax:SELECT 'DROP TABLE ' || table_name || ';' FROM user_tables; 1.then you ...