消息中间件

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

消息中间件能做什么

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

示例:

电商平台中的注册功能,用户注册不单是向数据库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. MySQL数据库(11)----使用子查询实现多表查询

    子查询指的是用括号括起来,并嵌入另一条语句里的那条 SELECT 语句.下面有一个示例,它实现的是找出与考试类别('T')相对应的所有考试事件行的 ID,然后利用它们来查找那些考试的成绩: SELEC ...

  2. Ubuntu下搭建Hbase单机版并实现Java API访问

    工具:Ubuntu12.04 .Eclipse.Java.Hbase 1.在Ubuntu上安装Eclipse,可以在Ubuntu的软件中心直接安装,也可以通过命令安装,第一次安装失败了,又试了一次,开 ...

  3. Linux常用命令(二)————压缩+解压

    tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个.下面的 ...

  4. Ionic控件之——按钮(Button)

    Ionic提供丰富的按钮特性,足以满足大部分的按钮实现需求. 一.HTML实现一个简单按钮: <button class="button"> 我是按钮 </but ...

  5. 【Leetcode】【Hard】Copy List with Random Pointer

    A linked list is given such that each node contains an additional random pointer which could point t ...

  6. 沉淀再出发:kafka初探

    沉淀再出发:kafka初探 一.前言 从我们接触大数据开始,可能绕在耳边的词汇里面出现的次数越来越多的就包括kfaka了.kafka的设计初衷是希望作为一个统一的信息收集平台,能够实时的收集反馈信息, ...

  7. c# winform文本框数字,数值校验

    文本框数字,数值校验 public void DigitCheck_KeyPress(object sender, KeyPressEventArgs e) { e.Handled = !char.I ...

  8. rpc、socket、tcp/udp简要梳理

    RPC:远程过程调用(分布式.微服务间的方法调用) HTTP:无状态,每次请求都要发送一个request,服务器响应之后就断掉(http header中的keep-alive指的是tcp) TCP:面 ...

  9. 彻底关闭Firefox自动更新的方法

    自己最近在使用firefox进行自动化测试时,发现配置好的firefox总是会自动更新,主要是因为一些高版本的浏览器无法安装firepath,没有firepath的火狐浏览器使用起来总是有很多的不方便 ...

  10. Eclipse中的BuildPath详解【转载】

    什么是Build Path? Build Path是指定Java工程所包含的资源属性集合. 在一个成熟的Java工程中,不仅仅有自己编写的源代码,还需要引用系统运行库(JRE).第三方的功能扩展库.工 ...