Hyperledger Fabric源码解析 Gossip-Emitter

批量处理器(batchingEmitter)旨在解决单条数据处理效率低的问题,通过累积数据到一定数量或定时触发来批量处理。它包含一个内部缓冲区,当达到预设的转发阈值或定时器超时时,会调用回调函数处理消息。在Gossip协议中,批量处理器用于消息的推送和转发,允许消息被转发多次。工作流程包括定时触发和消息计数触发,确保了数据处理的批量性和效率。
摘要由CSDN通过智能技术生成

分批发射器 batchingEmitter

分批发射器的实现是为了解决来一条数据就处理一次所带来的效率问题。采用的思想是,将收到的数据累积到一定数量后再进行处理或者定时器超时进行就处理。
我更喜欢将分批发射器叫做分批处理器。

接口定义

type batchingEmitter interface {
	// Add 添加要批处理的消息
	Add(interface{})

	// Stop 停止组件
	Stop()

	// Size 返回要转发的挂起消息的数量
	Size() int
}

batchingEmitter 被用于gossip的推送或转发阶段。消息被添加到batchingEmitter中,它们被周期性地分批转发T次,然后被丢弃。如果batchingEmitter存储的消息计数达到一定的容量,那么也会触发消息转发。

batchingEmitterImpl 实现

type batchingEmitterImpl struct {
	iterations int               // 消息转发的次数
	burstSize  int               // 触发转发的阈值
	delay      time.Duration     // 定时触发转发的时间
	cb         emitBatchCallback // 进行转发而调用的回调
	lock       *sync.Mutex
	buff       []*batchedMessage // 待处理的消息
	stopFlag   int32
}

type batchedMessage struct {
	data           interface{}
	iterationsLeft int // 消息转发的剩余次数
}

注:消息并不是只能转发(处理)一次,在Emitter中,一条消息可能被转发多次,转发次数由用户配置文件设置。

导致分批发射器触发主要方式:定时触发消息计数达到转发的阈值

定时触发

func (p *batchingEmitterImpl) periodicEmit() {
	for !p.toDie() {
		time.Sleep(p.delay)
		p.lock.Lock()
		p.emit()
		p.lock.Unlock()
	}
}

每间隔delay时间,就调用emit()进行消息处理。

消息计数达到转发的阈值

func (p *batchingEmitterImpl) Add(message interface{}) {
	if p.iterations == 0 {
		return
	}
	p.lock.Lock()
	defer p.lock.Unlock()

	p.buff = append(p.buff, &batchedMessage{data: message, iterationsLeft: p.iterations})

	if len(p.buff) >= p.burstSize {
		// 达到触发转发的阈值,直接转发
		p.emit()
	}
}

若是当前存储的消息个数达到设置的阈值,则直接调用emit()函数进行消息处理。

emit

func (p *batchingEmitterImpl) emit() {
	if p.toDie() {
		return
	}
	if len(p.buff) == 0 {
		return
	}
	msgs2beEmitted := make([]interface{}, len(p.buff))
	for i, v := range p.buff {
		msgs2beEmitted[i] = v.data
	}

	p.cb(msgs2beEmitted)
	p.decrementCounters()
}

emit 中对消息的处理,主要是通过调用消息处理回调函数cb,处理结束后调用decrementCounters对每条消息的转发次数进行减一的操作。

总结

不难看出,分批发射器是一个通用的组件。具体的处理逻辑由用户提供,在分批发射器内部仅仅关注如何将数据批量触发的问题,即定时触发与消息计数达到转发的阈值。

分批发射器主要用于Gossip的推送或转发阶段。例如:发现层中定时发送Alive消息时对Emitter的应用。调用流程如下:

gossipDiscoveryImpl
    periodicalSendAlive
        d.comm.Gossip(msg)
            da.gossipFunc(msg)
                g.emitter.Add(...)
                    sendGossipBatch // 消息处理回调函数cb
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值