1、Notify应用,锋寒 2009-08,Agenda,Notify概述 引入Notify的时机 Notify基本概念 Notify开发 常见问题和误区,Notify是什么,Notify是一个消息中间件。是一个高性能、可靠、可扩展、可与发送端业务逻辑相结合、支持订阅者集群的消息中间件。 高性能 可靠 可扩展 与发送端业务相结合(分布式事务) 支持订阅者集群 持久订阅与非持久订阅 Notify接收消息流量控制,Notify做不到,消息100%不重复投递消息100%按照发送的顺序到达,消息中间件的特性,应用程序或组件之间的一种通讯方式 可靠性 保证消息不丢 异步 松散耦合 发送者和接收者不必了解对方
2、,只需要认识消息 发送者和接收者不必同时在线,引入Notify的时机,解除应用组件的紧密耦合 可扩展性 可用性 提高应用的响应时间 可靠的异步调用 Best Practice from eBay Asynchrony Everywhere,Messaging Models,Point-to-Point (PTP) 每个消息只有一个消费者 发送者和接收者没有时间依赖 接收者确认消息处理成功,Client1,Msg,发送,Queue,Client2,Msg,消费,确认,Messaging Models,Publish/Subscribe 每个消息可以有多个订阅者 客户端只有订阅后才能收到消息 持久
3、订阅 非持久订阅,Client1,Msg,发布,Topic,Client2,Msg,订阅,投递,确认,Client3,订阅,投递,确认,Publish/Subscribe,发布者和订阅者有时间上的依赖。 客户端只有建立了订阅关系后,才能收到消息 非持久订阅 订阅者为了接收消息,必须一直在线 持久订阅 订阅关系建立后,消息就不会丢失,不管订阅者是否在线 当只有一个订阅者时,PTP Notify只支持Pub/Sub模式,非持久订阅,持久订阅,Notify基本概念,发布者 订阅者 Notify Server Config Server 保存持久订阅关系 保存Notify Server列表,Topic
4、和Message Type,Notify Server,Topic,Message TypeMessage Type,Topic,Message TypeMessage Type,Topic和Message Type共同表示一种消息类型。Topic为第一级,Message Type为第二级; Notify通过Topic对外提供服务,而在Topic下限制了服务的Message Type。,Topic和Message Type,发布者根据Topic从Config Server获得Notify列表。发送消息的Message Type,需要符合Notify的限制。,发布者,Message Topic:
5、 TRADE,Message Topic: CTU,Config Server,Notify列表,Notify,Notify,Notify,TRADELOGISTICS,Notify,Notify,Notify,CTUP4P,Topic和Message Type,订阅者订阅Topic下的Message Type的消息,订阅者标识,Topic,Message TypeMessage Type,Topic,Message TypeMessage Type,订阅关系,Topic和Message Type,订阅者订阅Topic下的Message Type的消息,订阅者,Message Topic: T
6、RADE,Message Topic: CTU,Config Server,Notify列表,Notify,Notify,Notify,TRADELOGISTICS,Notify,Notify,Notify,CTUP4P,订阅者,部署结构,发布者,发布者,发布者,Config Server,Notify列表,Notify Server,Notify Server,Notify Server,订阅关系,发送消息,消费消息,发布者,发布者,订阅者,Notify列表,订阅关系,Notify列表,集群,将多台机器归为一组,对于外部,这组机器功能上相当于一个整体,对外提供统一的服务。 当该组接收到一个请
7、求时,会选择组内的一台机器处理这个请求。 可扩展:Shared nothing architecture 使用GroupId来标识集群,集群,发布者、订阅者和Notify Server都支持集群,Publisher,Publisher,Publisher,Notify,Notify,Subscriber,Subscriber,Subscriber,集群,集群,集群,订阅者集群,Notify,Subscriber,Subscriber,Subscriber,Subscriber,Subscriber,GroupId,选择集群中的一台投递消息,Notify基本概念,简单消息 notifyManag
8、er.sendMessage(Message) 事务消息 notifyManager.sendMessage(Message, SendMessageCallback) 消息的发布和业务操作在同一个事务中 业务操作放在SendMessageCallback中 BASE风格的分布式事务支持,事务消息,业务系统,DB,Notify,DB,发送half消息,业务操作,提交/回滚,存储half消息,, 提交:更新数据库标识消息可发送 回滚:删除消息,定期检查未提交的消息,提交/回滚,本地事务域,本地事务域,事务消息,消息回滚 SendMessageCallback抛出异常 MessageStatus.
9、 setRollbackOnly() 对于未成功提交或回滚的消息,Notify会主动发送Check消息,确认消息是否提交或回滚 客户端实现CheckMessageListener接口,可靠性保证,Notify接收到消息,首先入库,才会给客户端响应,告诉它消息发送成功 订阅者收到消息并完成业务操作后,才给服务器应答,确认消息成功处理 投递失败的消息会重新投递 超时 业务抛出异常 主动回滚 MessageStatus.setRollbackOnly,消息重试策略,根据配置的时间间隔重试 第一次,立即发送 第二次,延迟5S 第三次,延迟15S 第四次,延迟1min 可以根据Topic和message
10、 type配置,重复消息的产生,发送消息时 Notify已经成功存储了消息,但给客户端响应时超时或失败 对于Notify是两条不同的消息,但业务数据相同 投递消息时 客户端已经成功处理了消息,但返回响应时超时或失败 对于Notify是同一条消息,对订阅者的要求,消息可能重复投递 处理消息的业务操作应该具备幂等性 消息的顺序 时间戳,消息的存储,Normal message DLQ message Ignore message(没有订阅者时),消息的类型,BytesMessage 用来传输Bytes类型的Message。 Bytes的内容由用户控制,一般是用户传输对象序列化后的bytes。 St
11、ringMessage 用了传输简单的String类型的Message。 StringMessage用来传输小于String.length 小于或等于 2000的String有优势。 在Notify中,但发现String.length 大于 2000(或者更小)一般会在Notify端转变为BytesMessage处理。,消息的属性,Topic:Message所属主题。如:消息的Topic是TC,HSF等。 MessageType:消息类型。Subscriber根据Topic和MessageType订阅相关消息。 GMTCreate(Read Only):Message进入Notify Serv
12、er的时间。 GMTLastDelivery(Read Only):Message最后一次在Notify Server上投递的时间。 DeliverCount(Read Only): Message被成功投递前,重复投递的次数。 TimeToLive: Message在Notify Server最大生命时间。单位:秒。 DLQTime:Message被放到DLQ中的时间阀值。单位:秒。 PostTimeout:Notify Server向Client发布Message的超时时间。单位:ms ClientPostTimeout: Notify Client向Server发布Message的超时时
13、间。单位:ms SendOnceMessage:标识消息是否为只发布一次,不管是成功还是失败。 PushlisherHostName(Read Only):发布该消息的Publisher的Host Name BornTime(Read Only):消息的产生时间。 和GMTCreate的区别: BornTime是Message在Client产生的时间。 GMTCreate是Message被Server接受的时间。,支持自定义属性,ByteProperty ShortProperty IntProperty LongProperty FloatProperty DoubleProperty Bo
14、oleanProperty StringProperty,属性使用方法,必填属性 Topic MessageType GroupId(或者不填,系统会自动加上Notify Client使用的GroupId) 可选属性 TimeToLive DLQTime PostTimeout ClientPostTimeout SendOnceMessage 只读属性 GMTCreate GMTLastDelivery DeliverCount DeliverCount PushlisherHostName BornTime,属性使用方法,属性间的约束 TimeToLive和DLQTime同时配置时,DLQ
15、Time失效。 TimeToLive没有配置,DLQTime有效。DLQTime没有配置,使用默认值。 postTimeout没有配置,使用默认值。 属性限制 对Topic,MessageType,GroupId的限制:对这些属性,不能是Character.isWhitespace()。 对用户自定义属性的限制:如果是String,其中不能包含“(char)1“和“(char)2“ HostName长度不能超过32位,超过长度部分,将被忽略。 属性的默认值 ClientPostTimeout,默认值3000,单位:millisecond TimeToLive,默认为没有设置,范围1, 14 *
16、 24 * 3600(14天), 单位:second DLQTime,默认为没有设置,范围1, 14 * 24 * 3600(14天), 单位:second PostTimeOut,默认值10*1000, 范围100, 15 * 1000, 单位: millisecond,Notify开发,Maven引用,com.taobao.hsfhsf.notify.spring1.4.2com.taobao.hsfhsf.lib1.4.2 ,Notify开发范例程序,普通模式 最基本的使用方式 example 配置文件 publisher-beans.xml subscriber-beans.xml,N
17、otify开发范例程序,使用SubscriptionHelper 使用辅助类增加订阅关系 com.taobao.notify.helperexample 配置文件 helper-subscriber-beans.xml,Notify开发范例程序,扩展模式 当订阅的消息类型很多,每个消息可以由单独的Processor处理 com.taobao.notify.extendedexample 配置文件 extend-beans.xml,Notify开发范例程序,广播模式 消息投递到分组中的每一台机器 com.taobao.notify.syncexample 配置文件 syn-subscriber-
18、beans.xml,Notify开发线下分组,线下会有多个环境并存,为了不互相干扰,需要分组隔离,Notify TRADE,Client,Client,Client,日常环境,Notify TRADE,Client,Client,Client,项目环境,Config server,FAQ,为什么我发的消息有部分收不到了 很有可能发送方的groupId与订阅者的GroupId是相同的。NotifyServer并不区别发送方与订阅者,只是根据groupId来区分 相同的groupId有多台机器 为什么我会收到重复的消息 NotifyServer对于消息的处理反馈设置有超时,如果消息处理超时(可能是因为Debug),会导致Notify将消息再次发送 为什么我发送消息会失败 具体原因可以通过sendMessage返回的SendResult的getErrorMessage()来判断。 为什么我收不到消息 确认分组环境(日常、项目环境) 是否成功订阅消息 第一次发送消息失败 客户端从Config Server接收Notify列表是异步的,常见误区,可靠消息的含义 不能认为调用了sendMessage就万事大吉 消息成功发送到Notify后,消息不会丢失 需要关注Notify客户端的返回值 订阅者吃异常 =丢消息 订阅者提前返回 可能会丢消息,