简介
在一个涉及多模块交互的系统中,如果模块的交互需要手动去调用对方的方法,那么代码的耦合度就太高了。所以产生了异步消息通信。实际上,各种各样的消息队列都是基于异步消息的。不过它们大部分都有着非常复杂的设计,很多被设计成一个独立的软件来使用。今天我们介绍一个非常小巧的异步消息通信库[message-bus]
(https://github.com/vardius/message-bus),它只能在一个进程中使用。源代码只有一个文件,我们也简单看一下实现。
快速使用
安装:
$ go get github.com/vardius/message-bus
使用:
package main
import (
"fmt"
"sync"
messagebus "github.com/vardius/message-bus"
)
func main() {
queueSize := 100
bus := messagebus.New(queueSize)
var wg sync.WaitGroup
wg.Add(2)
_ = bus.Subscribe("topic", func(v bool) {
defer wg.Done()
fmt.Println(v)
})
_ = bus.Subscribe("topic", func(v bool) {
defer wg.Done()
fmt.Println(v)
})
bus.Publish("topic", true)
wg.Wait()
}
这是官网提供的例子,message-bus
承担了模块间消息分发的角色。模块 A 和 模块 B 先向message-bus
订阅主题(topic),即告诉message-bus
对什么样的消息感兴趣。其他模块 C 产生某个主题的消息,通知message-bus
,由message-bus
分发到对此感兴趣的模块。这样就实现了模块之间的解耦,模块 A、B 和 C 之间不需要知道彼此。
上面的例子中:
- 首先,调用
messagebuss.New()
创建一个消息管理器; - 其次调用
Subscribe()
方法向管理器订阅主题; - 调用
Publish()
向管理器发布主题消息,这样订阅该主题的模块就会收到通知。
更复杂的例子
其实很多人会对何时使用这个库产生疑问,message-bus
GitHub 仓库中 issue 中至今还躺着这个问题,https://github.com/vardius/message-bus/issues/4。我是做游戏后端开发的,在一个游戏中会涉及各种各样的功能模块,它们需要了解其他模块产生的事件。例如每日任务有玩家升多少级的任务、成就系统有等级的成就、其他系统还可能根据玩家等级执行其他操作...如果硬写的话,最后可能是这样:
func (p *Player) LevelUp() {
// ...
p.DailyMission.OnPlayerLevelUp(oldLevel, newLevel)
p.Achievement.OnPlayerLevelUp(oldLevel, newLevel)
p.OtherSystem.OnPlayerLevel