分布式发布订阅Akka集群中Publish与Send策略的区别及应用场景
Akka集群分布式Pub/Sub:Publish vs Send策略的核心差异与适用场景
嘿,我在Akka集群的分布式发布订阅这块摸过挺久的,来给你把这俩策略的区别掰明白——别看代码表面流程好像差不多,底层逻辑和适用场景可是天差地别!
核心差异
1. 消息分发的目标范围
- Publish策略:是广播模式,消息会发送给所有订阅了指定topic的Actor,不管这些Actor在集群的哪个节点,只要订阅了对应topic,都会收到消息副本。相当于微信群发,一发多收。
- Send策略:是点对点模式,消息只会发送给你指定的某个特定Actor。你得明确提供目标Actor的标识(比如ActorPath、注册的自定义ID),集群会帮你找到这个Actor的位置,然后精准投递,其他订阅者/注册者完全收不到。相当于一对一私聊。
2. 底层路由逻辑
- Publish:依赖topic的订阅关系表,mediator会遍历所有订阅该topic的Actor,把消息复制多份分别投递到对应的集群节点。
- Send:依赖集群的全局Actor注册表,mediator先通过你提供的标识找到目标Actor的集群位置,然后直接把消息单份投递过去,没有复制过程。
3. 注册/订阅的本质
- Publish对应的是订阅topic:订阅者调用
Subscribe(topic, self),告诉mediator“我要收这个topic的所有消息”。 - Send对应的是注册自身身份:接收方调用
Put(self)(或带自定义ID的Put(self, Some("my-id"))),把自己的Actor信息注册到集群全局注册表,让发送方可以通过标识找到自己。
适用场景
结合官方文档的例子,再补充几个实际场景:
Publish策略适合这些场景:
- 即时通讯的群聊:比如公司部门群,发一条消息所有群成员都需要收到。
- 系统全局通知:比如运维发布的系统维护预警,所有在线服务节点都得接收并处理。
- 事件驱动的业务流程:比如电商系统里的订单支付成功事件,库存、物流、积分系统都需要监听这个事件并执行各自的逻辑。
Send策略适合这些场景:
- 一对一私密聊天:用户A给用户B发私信,只有B能收到,其他人看不到。
- 定向服务调用:比如你需要调用集群中某个特定节点的计算服务,通过它的注册ID找到并发送任务请求。
- 单点指令下发:比如运维给某台特定服务器发送重启指令,只投递到目标节点的管理Actor。
代码层面的细节(为啥你觉得相似?)
两者都用DistributedPubSub的mediator来处理集群通讯,所以代码结构看起来像,但核心调用的方法和逻辑完全不同:
Publish的典型代码:
// 订阅者(群聊成员) val mediator = DistributedPubSub(context.system).mediator mediator ! Subscribe("dev-team-chat", self) // 发布者(发群消息的人) mediator ! Publish("dev-team-chat", "明天下午2点开技术评审会!")
Send的典型代码:
// 接收方(私聊的B用户) val mediator = DistributedPubSub(context.system).mediator // 注册自己的自定义ID,方便发送方找到 mediator ! Put(self, Some("user-b-123")) // 发送方(私聊的A用户) mediator ! Send("user-b-123", "嘿,评审会的材料我发你邮箱了!")
你看,Publish只需要指定topic,不用管谁在订阅;而Send必须指定具体的目标标识,这就是最直观的区别。
内容的提问来源于stack exchange,提问作者bumblebee
相关产品推荐
相关产品推荐

