一 消息中间件的价值
1 消息中间件的定义
胶水 为我们带来异步的特性,对系统进行了解耦
2 透过示例看消息中间件对应用的解耦
通过服务调用让其他系统感知事件发生的方式
例子:用户登录成功 让登录系统给用户发送短信/通知安全系统/通知其他系统
这会让登录系统变得更加复杂,并依赖非常多的系统
引入消息中间件解耦:登录系统给消息中间件发送消息
消息中间件再通知短信服务/安全系统等
需要确保消息发送到了消息中间件:数据库记录状态
这样带来问题:需要感知状态的应用要定时轮询数据库(查看状态)
做完操作后,需更改状态
增加了业务数据库的负担
依赖的复杂和不安全
扩展性不好
二 互联网时代的消息中间件
1 解决消息发送一致性
一致性的定义:业务操作成功,该操作产生的消息一定要发出去
难以保证消息发送一致性:业务成功 发送消息 面临应用出问题或者消息系统挂掉的可能 消息不能发送成功
2 JMS
JMS重要的要素:Destination ConnectionFactory Connection Session
MessageConsumer MessageProducer XXXMessage
要素间的关系:ConnectionFactory->Connection->Session->Message
Destination + Session-> MessageProducer
Destination + Session-> MessageConsumer
消息模型:JMS Queue模型:点对点
JMS Topic模型:消息发布/订阅
3 消息发送一致性除JMS外的解决方案
最终一致方案: 正向流程 : 应用把消息发送给中间件,标记消息状态为待处理
中间件把消息存储到消息存储中,并不投递该消息
消息中间件返回消息处理的结果(成功或失败)
业务操作 收到消息为失败,放弃操作
反之,操作,并发送业务处理结果至中间件
中间件更新消息信息 业务成功,消息状态待发送
业务失败,消息删除
反向流程(询问上述中业务操作结果):消息中间件询问状态为待处理的消息对应的业务操作结果
应用检查操作结果
应用发送业务操作结果
中间件更新消息状态
大多数情况下,反向流程不需要工作
4 消息中间件与使用者的强依赖问题
回顾以上过程,发现业务与消息中间件之间出现了强依赖
解决方案: A 提升消息中间件系统的可靠性 (无法提升到百分百)
B 业务操作与消息写入同一个事务
C 提供弱依赖支持
5 消息订阅者订阅消息的方式
持久订阅和非持久订阅
6 保证消息可靠性的做法(接收端)
消息发送端的可靠性 消息存储的可靠性 消息投递的可靠性
消息存储: 自主实现(非常不推荐)
关系型数据库/分布式文件系统/NoSQL
采用数据库
数据容灾:双机存储
消息系统扩容
7 消息重复的产生和应对
产生原因:消息发送端消息重复发送 解决方案:重试发送消息时使用同样的消息ID
消息中间件重复投递 解决方案:要求消息接受者的消息处理是幂等操作
消息投递的其他支持:消息优先级
订阅者消息处理顺序和分级订阅
自定义属性
局部顺序
8 Push与Pull方式的对比