Go实现微服务异步消息通信(一)Broker

本文深入探讨了Go实现微服务异步消息通信的两种方式,首先分析了go-micro内存实现的Broker,包括NewBroker、Connect、Disconnect、Publish和Subscribe的详细操作。然后介绍了基于HTTP的实现,重点讨论了httpSubscriber和httpBroker的工作流程,指出httpBroker高度依赖registry服务发现功能。文章以源码解读和流程图的形式,为读者提供了深入理解go-micro异步消息通信的途径。
摘要由CSDN通过智能技术生成

先学习一下go-micro源码

先贴出Broker接口定义:

// Broker is an interface used for asynchronous messaging.
type Broker interface {
	Options() Options
	Address() string
	Connect() error
	Disconnect() error
	Init(...Option) error
	Publish(string, *Message, ...PublishOption) error
	Subscribe(string, Handler, ...SubscribeOption) (Subscriber, error)
	String() string
}

首先是基于内存的实现

源码位于: https://github.com/micro/go-micro/tree/master/broker/memory

type memoryBroker struct {
	opts broker.Options

	sync.RWMutex
	connected   bool
	Subscribers map[string][]*memorySubscriber
}

基于内存的实现很简单

  • NewBroker,只是创建一个memoryBroker实例然后初始化opts和Subscribers。
  • Connect和Disconnect都只是简单的用一下读写锁,然后判断memoryBroker的connected,如果可以connect/disconnect,则对应修改connected。
  • Publish,根据topic从Subscribers中取出对应的subs,然后遍历subs调用每个订阅者的handler去处理memoryPublication
......
subs, ok := m.Subscribers[topic]
if !ok {
	return nil
}

p := &memoryPublication{
	topic:   topic,
	message: message,
}

for _, sub := range subs {
	if err := sub.handler(p); err != nil {
		return err
	}
}
......
  • Subscribe,根据传入的topic和handler创建memorySubscriber并添加到memoryBroker.Subscribers中,最后创建一个go routine去等待sub.exit的信号,当sub.exit可读时做移除subscriber的清理工作
......
sub := &memorySubscriber{
	exit:    make(chan bool, 1),
	id:      uuid.New().String(),
	topic:   topic,
	handler: handler,
	opts:    options,
}

m.Subscribers[topic] = append(m.Subscribers[topic], sub)

// 开一个routine去等待退出信号,即创建后就阻塞在<-sub.exit这里了
// 为啥不用同步调用呢?
go func() {
	<-sub.exit
	m.Lock()
	var newSubscribers []*memorySubscriber
	for _, sb := range m.Subscribers[topic] {
		if sb.id == sub.id {
			continue
			// 跳过这个subscriber,把其他subscriber添加到一个新的切片中去
			// 这样就实现了从切片中移除subscriber
			// 个人认为如果用链表存储subscriber更好
		}
		newSubscribers = append(newSubscribers, sb)
	}
	m.Subscribers[topic] = newSubscribers
	m.Unlock()
}()
......

另外贴上使sub.exit可读的代码:

func (m *memorySubscriber) Unsubscribe() error {
	m.exit <- true
	return nil
}

也就是说(只有)取消订阅的时候就会将这个subscriber从memoryBroker的订阅者中移除,个人觉得这里用channel通信是完全没有必要的

接下来是基于http的实现

源码位于:https://github.com/micro/go-micro/blob/master/broker/http_broker.go

httpSubscriber

type httpSubscriber struct {
	opts  SubscribeOptions
	id    string
	topic string
	fn    Handler
	svc   *registry.Service
	hb    *httpBroker
}
  • Unsubscribe,和memorySubscriber不一样,httpSubscriber取消订阅时直接通过自己保存的httpBroker的指针去调用httpBroker的unsubscribe方法。不过httpBroker.unsubscribe的实现倒是和memorySubscriber取消订阅的操作差不多

httpPublication

type httpPublication struct {
	m *Message
	t string
}

httpBroker

代码量比较大,这里就不贴出源码分析了,直接上流程图:
在这里插入图片描述
httpBroker十分依赖于registry服务发现功能,go-micro的registry实现,据官方文档说时可以和zookeeper等整合,That sounds good!后续接着研究registry实现。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值