docker的观察者模式Subscribe/Publisher实现

有些数据推送需要用观察者模式(也称作订阅者模式),看看docker是如何用golang实现这个的

//过一遍数据结构
type Events struct {
	mu     sync.Mutex  //锁
	events []*jsonmessage.JSONMessage //数据
	pub    *pubsub.Publisher //发布者
}

type Publisher struct {
	m           sync.RWMutex 
	buffer      int              //缓冲
	timeout     time.Duration    //超时
	subscribers map[subscriber]struct{}  //订阅者map结构,方便以后遍历map
}

作为一个订阅者,订阅一次

func (e *Events) Subscribe() ([]*jsonmessage.JSONMessage, chan interface{}) {
	e.mu.Lock()
	current := make([]*jsonmessage.JSONMessage, len(e.events)) //e.events发布时候都得通知订阅者
	copy(current, e.events)
	l := e.pub.Subscribe() //订阅,记录到Publisher的subscribers里面去
	e.mu.Unlock()
	return current, l
}

func (p *Publisher) Subscribe() chan interface{} {
	ch := make(chan interface{}, p.buffer)
	p.m.Lock()
	p.subscribers[ch] = struct{}{} //记录
	p.m.Unlock()
	return ch //返回一个管道
}

产生一次publisher,当然得广播给所有的订阅人

func (e *Events) Log(action, id, from string) {
	go func() {
		e.mu.Lock()
		jm := &jsonmessage.JSONMessage{Status: action, ID: id, From: from, Time: time.Now().UTC().Unix()}
		if len(e.events) == cap(e.events) {
			// 抛弃最老的一条记录,因为大小超过分配的咯
			copy(e.events, e.events[1:])
			e.events[len(e.events)-1] = jm
		} else {
			e.events = append(e.events, jm)
		}
		e.mu.Unlock()
		e.pub.Publish(jm) //发布广播
	}()
}

最后再看看广播的代码

func (p *Publisher) Publish(v interface{}) {
	p.m.RLock()
	for sub := range p.subscribers {
		// send under a select as to not block if the receiver is unavailable
        //如果设置超时,默认设置是100*time.Millisecond,则发送数据,如果发送不了则阻塞直到收到超时信息
		if p.timeout > 0 {
			select {
			case sub <- v: 
			case <-time.After(p.timeout):
			}
			continue
		}
	//不设置超时,没有发送到管道数据成功,则默认继续执行
		select {
		case sub <- v:
		default:
		}
	}
	p.m.RUnlock()
}

看看我们哪里取了这些数据:

//............省略
for {
		select {
		case ev := <-l: //取到订阅者的发往管道的数据
			jev, ok := ev.(*jsonmessage.JSONMessage)
			if !ok {
				continue
			}
			if err := sendEvent(jev); err != nil {
				return err
			}
		case <-timer.C://取到超时信息
			return nil
		case <-closeNotify://取到关闭通知信息
			logrus.Debug("Client disconnected, stop sending events")
			return nil
		}
	}
时间: 2024-10-11 00:00:40

docker的观察者模式Subscribe/Publisher实现的相关文章

EventBus Usage

EventBus is a publish/subscribe event bus optimized for Android. so make it simple,just think EventBus as a framework that allow different compoents to communicate, usually a subscribe register a certain event,then whenever a publisher has post an ev

观察者模式(Observer)和发布(Publish/订阅模式(Subscribe)的区别

最近在学习dubbo,学到dubbo自然要接触注册中心zookeeper,zookeeper里涉及发布和订阅问题. 观察者模式之JAVA实现:JAVA设计模式之观察者模式 发布订阅模式之JAVA实现:发布者订阅者模式之JAVA实现 在翻阅资料的时候,有人把观察者(Observer)模式等同于发布(Publish)/订阅(Subscribe)模式,也有人认为这两种模式还是存在差异,而我认为确实是存在差异的,本质上的区别是调度的地方不同. 观察者模式 比较概念的解释是,目标和观察者是基类,目标提供维

设计模式:观察者模式(发表-订阅(Publish/Subscribe)模式)

观察者模式定义:定义对象间一种一对多的依赖关系,当这个对象状态发生变化时,则所有依赖它的对象都会得到通知并被自动更新(注:这里的依赖是一种聚合的方式).  笔者对于这些定义什么的其实相当的不感冒,虽然这个写得的确很不错的样子.下面直接上代码运行效果图,通过将’男孩子们打望美女淋浴‘的例子,来讨论下该模式. 代码贴上: <?php //被打望者接口 实现该接口的对象都可以视为实际被打望的妹子 interface IbeatifulGirl{ public function join(IBoy $b

Javascript设计模式之观察者模式

首先说一下观察者模式的应用场景 观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式.(Tom大叔) 具体说一下这个观察者模式,就是一个发报纸的过程.我们订阅了报纸,在报社的数组里加上我们的名字(不仅是名字了是一个带我们名字的处理函数),这是订阅事件:报社才不管你订没订报纸,他只管给他数组里的人发报纸:我们在编码的时候只监听发报纸的事件,订不订报纸,谁订报纸,都是你的事,就不在放在监听的事件里了,于是就有了减少监听的优化:

《javascript 设计模式》 第15章 观察者模式 -- 学习笔记

定义: 在事件驱动的环境中,比如浏览器这种持续寻求用户关注的环境中,观察者模式(又名发布者-订阅者 “publisher-subscriber" 模式) 是一种管理人与其任务之间的关系(确切的讲,是其对象及其行为和状态之间的关系 )的得力工具.用javascript的 话来说,这种模式的实质 就是你可以程序中某个对象的状态进行观察并且在其发生改变时能够得到通知. 观察者API: var Publisher=function(){ this.subscribers=[]; } //推送方法 Pub

【读书笔记】读《JavaScript设计模式》之观察者模式

一.定义 在事件驱动的环境中,比如浏览器这种持续寻求用户关注的环境中,观察者模式(又名发布者-订阅者(publisher-subscripber)模式)是一种管理人与其任务之间的关系(确切地讲,是对象及其行为和状态之间的关系)的得力工具.用JavaScript的话来说,这种模式的实质就是你可以对程序中某个对象的状态进行观察,并且在其发生改变时能够得到通知. 二.例子 我们需要一个发布者的构造函数,它为该实例定义了一个类型为数组的属性,用来保存订阅者的引用. function Publisher(

JavaScript设计模式之观察者模式(学习笔记)

设计模式(Design Pattern)对于软件开发来说其重要性不言而喻,代码可复用.可维护.可扩展一直都是软件工程中的追求!对于我一个学javascript的人来说,理解设计模式似乎有些困难,对仅切图.做少量交互效果的FE甚至可能不会用到,但是当你开始使用Angular/Backbone等框架的时候,就无法避免设计模式.MVC/MVVM这些东西了(反正我是伤脑筋). 我学设计模式是刚开始接触编程大概三个月的时候,看一本书<大话设计模式>,里面用C#语言来写,我很无语,因为强类型的编程语言对于

javascript设计模式-观察者模式

观察者模式定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己. 例子:杂志订阅 发布者包含一些方法: var publisher = { subscribers:function(fn,type){ type = type ||"any"; if(typeof this.subscribers[type] ==="undefined"){ this.subscribers[typ

js实现观察者模式

基本概念介绍 观察者(observer) 模式广泛用于客户端Javascript编程中.所有的浏览器事件都是该模式的例子.它的另一个名字也称为自定义事件(custom events),与那些由浏览器触发的事件相比,自定义事件表示是由你编程实现的事件.此外,该模式的另一个别名也称为订阅/发布(subscriber/publisher)模式. 设计该模式背后的主要动力是促进形成松散耦合.在这种模式中,并不是一个对象调用另一个对象的方法,而是一个对象订阅另一个对象的特定活动并在状态改变后获得通知.订阅