原文链接:http://en.wikipedia.org/wiki/Publish - subscribe_pattern
在软件架构中,发布-订阅(publish–subscribe)是一种消息传播模式,消息的发送者(发布者)不会将消息直接发送给特定的接收者(订阅者)。而是将发布的消息按特征分类,无需对订阅者(如果有的话)有所了解。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需对发布者(如果有的话)有所了解。
发布/订阅(pub/sub)与消息队列范式属于同一层级,通常是更大的面向消息中间件系统的一部分。大多数消息系统在应用程序接口(API)中同时支持消息队列模型和发布/订阅模型,例如Java消息服务(JMS)。
这种模式提供了更大的网络扩展性和更动态的网络拓扑。
消息过滤
在发布/订阅模型中,订阅者通常只接收所有发布消息的一个子集。对需要接收和处理的消息做出选择的过程,称为过滤。有两种常用的过滤形式:基于主题和基于内容。
在基于主题的系统中,消息被发布到“主题”或命名的逻辑通道。基于主题的系统中,订阅者将收到其订阅的主题上的所有消息,而且同一主题的所有订阅者将接收到同样的消息。发布者负责定义订阅者可以订阅的消息类别。
基于内容的系统中,只有当消息的属性或内容匹配订阅者定义的约束条件时,消息才会被投递给该订阅者。订阅者负责对消息进行分类。
有些系统支持两者的混合:发布者发布消息到一个主题,而用户注册基于内容的订阅到一个或多个主题。
拓扑结构
在许多发布/订阅系统中,发布者发布消息到消息中介,而订阅者在该中介注册订阅,让中介进行过滤。中介一般执行存储转发的功能将消息从发布者路由到订阅者。此外,路由之前中介可能会将队列中的消息按优先级排序。
历史
最早公开描述的发布/订阅系统是Isis Toolkit中的“新闻”子系统,描述在1987年的美国计算机协会(ACM)操作系统原理专题讨论会(87年SOSP)中的一份报告中,名为“分布式系统中的虚拟同步开发。123-138”[3]。 其中描述的发布/订阅技术是由Frank Schmuck发明的。
优点
松耦合
发布者松耦合到订阅者,甚至不需要知道它们的存在。因为关注的是主题,发布者和订阅者可以对系统拓扑结构保持一无所知。各自继续正常操作而无需顾及对方。在传统的紧耦合的客户端-服务器模式中, 当服务器进程不运行时,客户端无法发送消息给服务器,服务器也无法在客户端不运行时接收消息。许多发布/订阅系统不但将发布者和订阅者从位置上解耦,还从时间上解耦发布者和订阅者。中间件分析师对发布/订阅使用的常用策略,是分摊出版者的份额来解决订阅者的线路阻塞(带宽限制的一种形式)。
扩展性
通过并行操作,消息缓存,基于树或基于网络的路由等技术,发布/订阅提供了比传统的客户端–服务器更好的扩展性。然而,在某些类型的紧耦合、高容量的企业环境中,随着系统规模上升到由上千台服务器组成的数据中心所共享的发布/订阅基础架构,现有的供应商系统经常失去这项好处;在这些高负荷环境下,发布/订阅产品的扩展性是一个研究挑战。
另一方面,脱离了企业环境,布/订阅范式已经证明了它的可扩展性远超过一个单一的数据中心,通过网络聚合协议如RSS和Atom(标准)提供互联网范围内分发的消息。在交互时,为了能够即便是用低端web服务器也能将消息播出到(可能)数以百万计的独立用户节点,这些聚合协议接受更高的延迟和无保障交付。
缺点
发布/订阅系统最严重的问题是其主要优点的副作用:发布者解耦订阅者。发布/订阅系统必须仔细设计,才能提供特定的应用程序可能需要的更强大的系统性能,例如有保证交付。
- 发布/订阅系统的中介(broker)可能设计为在指定时间发送消息,随后便停止尝试发送,无论是否已收到所有用户成功接收消息的确认回复。这样设计的发布/订阅系统不能保证消息能够传递到所有需要这种有保证交付的应用程序。要完成有保证交付,这种发布者订阅者在设计上的紧密耦合,必须强行脱离发布/订阅架构(例如,通过要求订阅者宣布消息已接收)。
- 发布/订阅系统中的发布者会“假定”订阅者正在监听,而实际上可能没有。一个工厂可能会使用发布/订阅系统来允许设备发布问题和故障,订阅者将问题显示并记录。如果记录器失败(崩溃了),那么设备故障发布者不一定收到记录器失败的通知,发布/订阅系统的任何设备都不会显示和记录错误消息。应当指出的是,对于其它消息架构这也是一个设计上的挑战,例如客户端/服务器系统。在客户端/服务器系统中,当一个错误记录器失效,系统将收到迹象。但是,客户端/服务器系统要处理这个失效,就必须拥有一个在线的冗余日志服务器,或者动态生成回退日志服务器。这就增加了服务端和客户端以及整个客户端/服务器架构设计的复杂度。然而,发布/订阅系统中,在不影响任何其它设备的情况下,精确复制现有日志器的冗余日志记录订阅者可以添加到系统,来增加日志记录的可靠性。在发布/订阅系统中,有保障的错误消息日志功能可以逐步添加,随后实现设备故障信息记录的简单基本功能。
在有少量发布者和订阅节点的小型网络和低信息量时发布/订阅能够自如伸缩。然而,随着节点和消息量的增长,不稳定性随之增长,限制了发布/订阅网络的最大可扩展性。大规模时吞吐量不稳定的例子有:
- 负荷激增 - 订阅请求使网络流量饱和,随后进入低信息量(未充分利用网络带宽)
- 速度变慢 - 越来越多的应用程序使用该系统(即使它们是在不同的发布/订阅频道通信)消息量流入单个订阅者的速度缓慢
- IP 广播风暴 - 过量消息导致的饱和时,局域网可能会彻底关闭,阻塞所有与发布/订阅无关的正常通信
使用中介(服务器)的发布/订阅系统,同意中介发送消息给带内订阅者,会引发安全问题。中介可能被愚弄,从而将通知发送给错误的客户端,增大了针对客户端的服务请求被拒绝的可能性。中介本身可能超载,因为他们分配资源来跟踪创建的订阅者。
即使不依赖中介的系统,订阅者也可能可以接收未被授权的数据。未经授权的发布者可能将不正确或损坏的消息引入到发布/订阅系统。对于广播或多播消息的系统,这是很真实的。加密(例如传输层安全性(SSL/TLS)),可以防止未经授权的访问,但不能防止损坏的消息被授权的发布者引入。除了发布/订阅架构,例如客户端/服务器系统,也经常碰到授权的消息发送者有恶意行为。
语义耦合
发布/订阅系统对于空间、时间和同步的松散耦合,提供了可扩展的基础架构,来进行信息交换和分布式工作流。然而,通过事件的订阅和方式,发布/订阅紧密耦合到底层事件的模式和取值的语义。在大型开放的部署中,例如智能城市和传感器网络,事件的高度语义多相性使得发布/订阅系统难以开发和维护。为了解决发布/订阅系统中的语义耦合,使用事件的近似语义匹配是一个活跃的研究领域。
参考
- PubSubHubbub (an implementation of pub/sub)
- RSS - a highly scalable web-syndication protocol
- Atom (standard) - another highly scalable web-syndication protocol
- Event-driven programming
- Observer Pattern
- DDS
- Push technology
- Usenet
- Internet Group Management Protocol
引用
- ^ Birman, K. and Joseph, T. "Exploiting virtual synchrony in distributed systems" in Proceedings of the eleventh ACM Symposium on Operating systems principles (SOSP '87), 1987. pp. 123-138.
- ^ Hasan, Souleiman, Sean O’Riain, and Edward Curry. 2012. “Approximate Semantic Matching of Heterogeneous Events.” In 6th ACM International Conference on Distributed Event-Based Systems (DEBS 2012), 252–263. Berlin, Germany: ACM. “DOI”.
外部链接
- XMPP XEP-0060: Publish-Subscribe
- For an open source example which is in production on MSN.com and Microsoft.com, see Distributed Publish/Subscribe Event System
- Python PubSub a Python Publish-Subscribe broker for messages *within* an application (NOT network)