精华内容
参与话题
问答
  • events事件

    2018-08-12 15:51:33
    大多数node.js核心API都采用异步事件驱动架构,当主进程遇到了一个I?O请求时,把I/O 交给底层,然后并不受阻塞,当I/ 0完成之后就通知主进程,怎么做到的通知呢,通过触发一个事件,来告诉主进程我已经完事了。...

    大多数node.js核心API都采用异步事件驱动架构,当主进程遇到了一个I?O请求时,把I/O 交给底层,然后并不受阻塞,当I/ 0完成之后就通知主进程,怎么做到的通知呢,通过触发一个事件,来告诉主进程我已经完事了。

    用http写了一个server事件,每当有plant进行连接时,server就会触发一个contaction事件,这个时候如果我们绑定的contaction事件给他绑定了一些事件处理程序,每次客户端来都会调用相应的程序来进行处理了。

    在node端所有能够触发事件处理程序的对象都是EventEmitter的实例,我们想着这个类有触发事件的能力,就要继承这个EventEmitter的实例。

    //1.EventEmiter 在node内置的events包里

    const EventEmitter=require('events');

    //2.定义一个自己的class,这是es6方法,继承EventEmitter类

    class CustomEvent extends EventEmitter{

    }

    //3.定义一个实例

    const ce=new CustomEvent();

     

    //3.写一下对应的事件处理程序

    ce.on('test',()=>{

    console.log('this id a test!');

    });

     

    //4.用ce.emit事件触发这个定义的函数;

    setInterval(()=>{

    ce.emit('test');

    },500);

    不停地输出this id a test!

     

    展开全文
  • Events的重要性: node是单线程,基于事件驱动的,所以node中很多模块都是基于events去实现的,所以event模块在node中属于很重要的模块。 Events常用的API: emitter.on(eventName, listener)和emitter....

    Events的重要性:

    node是单线程,基于事件驱动的,所以node中很多模块都是基于events去实现的,所以event模块在node中属于很重要的模块。

    Events常用的API:

    1. emitter.on(eventName, listener)和emitter.addListener(eventName, listener)用来添加订阅事件
    2. emitter.once(eventName, listener)用来添加只执行一次的事件
    3. emitter.prependListener(eventName, listener)用来在事件队列前面添加事件
    4. emitter.emit(eventName[, ...args])用来触发事件队列执行
    5. emitter.removeListener(eventName, listener)用来移除某个事件队列
    6. EventEmitter.defaultMaxListeners 默认事件队列的长度
    7. emitter.setMaxListeners 设置最大队列的长度
    8. emitter.prototype.getMaxListeners 获取最大队列的长度

    Event的核心原理:

    events模块是基于发布订阅模式来实现的,其核心的逻辑可以用下面的代码表示:

    function Event(){
        this.events=[];
    }
    //添加订阅者
    Events.prototype.on = function(listener){
        if(typeof listener === 'function'){
            this.events.push(listener)
        }
    }
    //执行订阅回调
    Events.prototype.emit = function(){
        this.events.forEach(event=>evetn());
    }
    复制代码

    Events.prototype.on 实现

    function EventEmitter(){
        this._events={};//用来存储各种不同类型的事件队列
        this._maxListeners = undefined; // 默认实例上没有最大监听数
    }
    
    EventEmitter.defaultMaxListeners//默认事件队列的长度为10
    
    EventEmitter.prototype.setMaxListeners = function(count){
        this._maxListeners = count;
    }
    
    EventEmitter.prototype.getMaxListeners = function(){
        if(!this._maxListeners){ // 如果没设置过那就是10个
            return EventEmitter.defaultMaxListeners;
        }
        return this._maxListeners
    }
    EventEmitter.prototype.on = EventEmitter.prototype.addListener=function(eventName,listener){
        if(!this._events){this._events = Object.create(null);}//防止缓存不存在,创建一个没有原型的干净缓存
        if(eventName!=='newListener'){//newListener每次绑定事件都会调用这个里面的回调并且传入当前事件名
            if(this._events['newListener']){
                this._events['newListener'].forEach(fn=>fn(eventsName))
            }
        }
        if(this.events[eventName]){//已存在队列就直接将回调放入
             if(this._events[eventName].length === this.getMaxListeners()){
                console.warn(`Possible EventEmitter memory leak detected.${this._events[eventName].length}${String(eventName)}listeners added. Use emitter.setMaxListeners() toincrease limit'`)
            }
            this._events[eventName].push(callback);
        }else{//不存在就创建一个队列再放入
            if(this._events[eventName].length === this.getMaxListeners()){
                console.warn(`Possible EventEmitter memory leak detected.${this._events[eventName].length}${String(eventName)}listeners added. Use emitter.setMaxListeners() toincrease limit'`)
            }
            this._events[eventsName]=[listener];
        }
    }
    module.exports = EventEmitter;
    复制代码

    Events.prototype.prependListener 实现

    EventEmitter.prototype.prependListener = function (eventName,listener) {
      this.on(eventName,listener, true);
    }
    //修改EventEmitter.prototype.on让其可以选择添加事件的位置
    EventEmitter.prototype.on = EventEmitter.prototype.addListener=function(eventName,listener,flag){
        if(!this._events){this._events = Object.create(null);}
        if(eventName!=='newListener'){
            if(this._events['newListener']){
                this._events['newListener'].forEach(fn=>fn(eventsName))
            }
        }
        if(this.events[eventName]){
            if(!flag){//根据flag来判断添加的位置
                this._events[eventName].push(callback);
            }else{
                this._events[eventName].unshift(callback);   
            }
        }else{
            this._events[eventsName]=[listener];
        }
    }
    复制代码

    Events.prototype.once 实现

    EventEmitter.prototype.once = function(eventName,listener){
        function once(){//once缓存listener,不然的话移除时找不到listener
            listener();
            this.removeListener(eventName,once)
        }
        this.on(eventName,once)
    }
    复制代码

    Events.prototype.emit 实现

    EventEmitter.prototype.emit = function(eventName,...args){
        if(this._events[eventName]){
            this._events.forEach(fn=>{//使用箭头函数,所以this指向外层的this即emit实例
                fn.call(this,...args)
            })
        }
    }
    复制代码

    Events.prototype.removeListener 实现

    Events.prototype.removeListener = finction(eventName,listener){//需要从相应的事件队列中筛选排除传入的listener
        this._events[eventName].filter(fn=>{
            return listener!==item &&item.g!===listener//第二个针对于用once绑定的事件回调
        })
    }
    EventEmitter.prototype.once = function(eventName,listener){
        function once(){//once缓存listener,不然的话移除时找不到listener
            listener();
            this.removeListener(eventName,once)
        }
        once.g = listener;//用来缓存原来的listener,删除时用到
        this.on(eventName,once)
    }
    复制代码

    结语:

    以上就是关于Events模块原理的介绍,如果有错误欢迎指正,本文参考:

    1. Node API
    2. javascript设计模式


    作者:梦想攻城狮
    链接:https://juejin.im/post/5b990be75188255c7566b479
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    展开全文
  • js事件——Events

    千次阅读 2014-12-11 23:32:20
    本文介绍了事件处理机制,相关问题以及如何写出跨浏览器的脚本

    没有共产党就没有新中国,没有 events 就没有 scripts。每个包含 JavaScript 的页面中: 几乎所有的脚本都是由 event 触发的。原因很简单。 JavaScript 可以增加交互性: user 做一些操作,页面给出响应。Events 是所有 JavaScript 应用的小心脏。本文介绍了事件处理机制,相关问题以及如何写出跨浏览器的 scripts。同时也展示了几个带有事件处理细节的页面。

    因此JavaScript 检测用户的操作,以便知道何时做出反应,反应时执行哪个 functions 。

    当用户做出某操作就会触发一个 event 。也有一些  events 不是由用户直接触发: 例如 load event 是页面加载时触发的。

    JavaScript 可以检测一些 events。从 Netscape 2 开始就可以把事件处理程序( event handler)附加到某个HTML 元素。 事件处理程序会等候某个 event (例如 链接上的 click 事件 )发生。这时候就会执行你定义好的JavaScript 代码来处理事件 。

    用户操作会产生一个 event。当 script 对 event做出响应,这就是所谓的交互。

    事件处理的历史

    假如没有事件处理机制,在页面中添加 JavaScript 就毫无意义。好的脚本可以对用户操作做出响应。因此网景发布第二版支持JavaScript的浏览器时,它也支持事件处理机制。

    Netscape 模型

    Netscape 2 只支持一些 events。Mouseover 和 mouseout 很快风靡,因为可以通过onMouseOver 改变  images ,通过onMouseOut 把它们变回去。在那个时候是很神奇的。也可以看到用户 submit  或 reset 表单,因此实现了客户端表单验证( form validation)。浏览器也可以检测表单获得焦点、失去焦点、页面加载完成、开始上传等。尽管现在看来很稀松平常,但是在那个年代,这可是Web页面革命性的进展。真正的交互成为了可能,因为你可以对用户操作做出响应。

    最古老的事件处理就下面一样:

    <a href="somewhere.html" οnclick="alert('I\'ve been clicked!')">
    

    这种最古老的事件处理机制实际上是由Netscape 定义的标准。如果想要JavaScript工作,其他的浏览器包括IE都得遵从Netscape 2和3的处理事件的标准。因此这些最古老的事件和事件处理程序在任何JavaScript浏览器中都能很好地运行。

    现代事件模型

    然而,自从引进这些简单的事件处理器后很多东西都发生了变化。首先事件数量增加,同时,事件注册机制也发生了变化。现在可以完全由JavaScript来设置。不再需要大量的附着于代码之上,你可以写一些很简单的代码来设置所有的事件处理程序。

    第4版的浏览器还提供了更多的关于事件本身的信息。光标在哪儿(光标在撒钱)事件何时触发?有没有键被按? 如果该界面元素存在父子元素,而且父子元素也定义了同样的事件,这个时候事件该如何处理呢,事件在父子元素之间是如何传递的呢,谁会先接收到这个事件,又是谁先处理呢?不同的浏览器其处理机制也不尽相同。

    在网景和微软斗争的年代,两个公司选择了完全不同的事件模型。W3C非常理智的处理了这种差异,在两者之间采取了中和的方法 DOM Event specification。除了一个严重漏洞( serious flaw), W3C的模型, 添加了很多新功能并解决了旧模型的很多问题。

    三个模型意味着事件处理机制在不同的浏览器中可能有所不同。

    浏览器兼容性问题

     就像 DHTML,W3C DOM 或其他的高级脚本技术一样,我们必须在浏览器中小心翼翼地执行代码。 在 Explorer 中调用 stopPropagation() 或者在 Netscape调用 srcElement 将会导致严重的错误甚至导致脚本不可用。因此在使用之前,我们必须确保浏览器支持该方法或该属性( the methods or properties) 。

    如下一个简单的代码分支

    if (Netscape) {
    	use Netscape model
    }
    else if (Explorer) {
    	use Microsoft model
    }
    

    只是一个近似的解决方案,因为它忽略了非主流的浏览器。现在的解决方案可以处理大量的 modern event handling,除非你的脚本机智地设定非主流浏览器不允许执行代码,因为它们不是 Netscape 或 Explorer。

    所有其他非主流的浏览器都必须做出决定站在哪一队:支持哪一种模型。Konqueror/Safari, 选择了严格的标准并支持 W3C model。Opera and iCab 则比较谨慎,支持旧的 Netscape model 和 Microsoft model中的大部分。

    但非主流的浏览器可能支持的是 Microsoft 标准,但实际上其事件属性既有 W3C 的也有 old Netscape model的。

    不要使用浏览器检测

    首先,千万不用使用 browser detect。这是最快的作死方法。任何代码如果使用navigator.userAgent事件模型检测简直没用还没用应该直接拉出去弹JJ。

    其次,不要将 DHTML 对象检测(object detection  )与事件对象检测混为一谈。当书写DHTML 时我们通常这样检测是否支持DOM: if (document.all) is supported. 如果是酱紫,使用 Microsoft allcontainer 的脚本可以正常执行。

    但 DHTML和事件处理程序有不同的浏览器兼容模式。例如: Opera 6 支持部分 W3C DOM 但不支持 W3C event model。因此在Opera中。所以代码使用  if (document.layers) 或者其他的事件模型检测都是不正确的。

    正确的提问

    然后我们应该做些什么? 事件属性( event properties)引起严重的问题。如果我们使用大量特定对象检测,可以解决99%的浏览器的不兼容问题。只有鼠标位置( mouse position)非常的麻烦,其他的都比较简单了。

    此外,最好是不去在意三个事件模型。相反,我们必须理解四个事件注册模型,两个事件访问模型和两个事件的命令。
    事件处理和浏览器兼容性,参见事件兼容性表( event compatibility tables)。

    貌似很复杂,其实so easy。实际上,当我认识到要对不同事件模型单独处理之后,我才开始真正理解事件处理。 这都是关于如何提出正确的问题的。别这么问“如何写一个事件来处理脚本?”  这是个问题,但很难给出答案,你应该问得再具体一点,别人才好给出答案:

    • “都有哪些事件?”
      很多,当然在某些浏览器中,一些事件无法生效。
    • “如何给一个HTML 元素注册事件处理程序?
      注册事件处理器有四种模型: 内敛模型( inline), 传统模型(traditional), W3C模型和微软模型(W3C and Microsoft)。第一种方法使用与所有浏览器,完全没有问题。
    • “如何阻止事件的默认行为?”
      从事件处理脚本中 return false , 默认的动作就会被阻止。该技术标准是由 Netscape 2 定义的,现在依然有效。
    • “若要获取更多事件相关的属性,该怎么做?”
      有两种方法:W3C 或 Netscape and Microsoft。为了解决这个问题你还需要这样一行代码
    • “接下来改如何读取它的这些属性呢?”
      要读取这些属性存在兼容性问题,这些问题在事件属性这篇文章中详细说明了。要解决兼容性问题还需要参考事件属性兼容性表 和进行一些严格的对象检测。
    • “元素存在父元素,而且父元素也定义了同样的事件,这个时候事件该如何处理呢,事件在父子元素之间是如何传递的呢,谁会先接收到这个事件,又是谁先处理呢?” — 这个问题很有技术含量
      不同的浏览器有不同的方法。有两个 事件处理顺序,事件捕获(event capturing )和事件冒泡( event bubbling)。在实践中他们并不是很重要,只有少数情况下会用到,这种情况下我们通常会关心如何把它们关掉。需要两行代码。


    写跨浏览器的脚本的技巧不是单单使用一个的事件模型,而是问自己上面那些问题。你将会发现需要考虑浏览器兼容性的情况:主要是在读取事件属性的时候。

    首先选择一种事件注册模型, 确保所有的浏览器都支持该事件,随后去读取所需的事件属性,期间,如果存在兼容性问题的话还需要去解决。这样你就能浏览器兼容性问题各个击破,也能确保你的代码能在所有的浏览器里正常运行。

    继续

    如果你想详细了解事件相关的更加详细的内容,建议你继续阅读 events 这篇文章

    编写事件处理脚本

    如何编写呢?本文我给出了一个概述。

    注册事件处理程序

    第一步就是注册事件处理程序。但必须保证你选择的事件发生时浏览器会执行你的脚本。

    注册事件处理器有四种模型:  内敛模型( inline), 传统模型(traditional), W3C模型和微软模型(W3C and Microsoft)。

    最好的办法是使用传统模式,因为它是完全兼容的,并给出予很大的自由度和多样性。 注册事件处理程序,使用以下方法

    element.onclick = doSomething;
    if (element.captureEvents) element.captureEvents(Event.CLICK);
    

    现在函数 doSomething() 就被注册成为了HTML 元素element 的click 事件处理程序。一旦用户点击这个元素, doSomething() 就会被执行。

    访问事件

    注册了事件处理器之后就可以开始书写实际的脚本了。在通常情况下,你需要访问事件本身( access the event itself),这样就可以读取有关的事件信息。

    通常事件处理程序都这样写:

    function doSomething(e) {
    	if (!e) var e = window.event
    	// e refers to the event
    }
    

    其中 e 指的是所有浏览器中可以访问的事件。

    访问 HTML 元素

    有时你也需要访问事件发生在其上的HTML元素。 有两种方法:使用this 关键字,或者使用 target/srcElement 属性。

    访问 HTML 元素最稳妥的方法是使用this 。 this  并不能始终指向正确的 HTML 元素,但是结合传统模型可以良好地工作。

    function doSomething(e) {
    	if (!e) var e = window.event
    	// e refers to the event
    	// this refers to the HTML element which currently handles the event
    	// target/srcElement refer to the HTML element the event originally took place on
    }
    

    target/srcElement 属性包含了一个引用,指向事件最初发生的 HTML 元素。很有用,但是当事件被捕获或冒泡( is captured or bubbles up)的时候, target/srcElement 并不会随之改变:它仍指向事件最初发生的 HTML 元素。 target/srcElement 相关内容详见 Event properties 页面,this 关键字相关内容详见 this )

    读取属性

    读取事件属性( event properties)是浏览器兼容性的软肋。参考这个表格( event compatibility tables ) 来编写自己的脚本,读取想要的信息。

    确保尽可能地使用最详细的对象检测。 首先检测每个属性是否存在,然后读取它的值。例如:

    function doSomething(e) {
    	if (!e) var e = window.event
    	if (e.keyCode) code = e.keyCode;
    	else if (e.which) code = e.which;
    }
    

    其中 code 表示浏览器中按下的按键。

    事件顺序

    最好,你要决定是否想让事件冒泡( bubble up)。如果不想让其发生,就阻止事件的传播:

    function doSomething(e) {
    	if (!e) var e = window.event
    	// handle event
    	e.cancelBubble = true;
    	if (e.stopPropagation) e.stopPropagation();
    }
    

    编写脚本

    现在你可以开始正式写事件处理的脚本。利用上面那些代码片段得到的信息,来决定事件发生时到底发生了什么,以及你的脚本应如何应对。 

    注意:时刻保持交互的逻辑思维,不然用户就麻爪了。


    原文:Introduction to Events

    展开全文
  • Kubernetes(K8s)Events介绍(上)

    万次阅读 2016-12-22 16:55:53
    Kubernetes Events虽不常被提起,却意义非凡。它存储在Etcd里,记录了集群运行所遇到的各种大事件。本系列文章将一步一步地揭开Kubernetes Events的神秘面纱。 师出有名 前些天群里有位同学(@二东)提问说...

    Kubernetes Events虽不常被提起,却意义非凡。它存储在Etcd里,记录了集群运行所遇到的各种大事件。本系列文章将一步一步地揭开Kubernetes Events的神秘面纱。

    师出有名

    前些天群里有位同学(@二东)提问说怎么通过API得到kubectl describe pod的结果,我立刻找到了Kubernetes相关的API并回复他,但他说这不是他要的东西。经过一番描述,我才了解到他想要的是原来如下图中红框里的信息:

     

    20161219150015

     

    Message属于Kubernetes的一种特殊的资源:Events。老实讲,我以前是没有怎么注意过这个Events是怎么来的,甚至一直觉得它应该是Pod的一部分。那么这个Events到底是什么样的资源?它从何而来?下面随我一起踏上捉妖之路。

    真身难觅

    熟悉Kubernetes的小伙伴应该对于它的资源比较有体会,作为调度基本单元的Pod是一种资源,控制Pod更新、扩容、副本数量的ReplicaSet是一种资源,作为发布单位的Deployment也是一种资源,哦,还有Service,Endpoints等等。它们有这么一些共同点:

    • 都可以通过kubectl get $ResourceName的方式获取
    • 都有对应的RESTful API定义的操作

    Events亦如此,kubectl get events的结果为下图:

     

    20161219150024

     

    就像kubectl get pods一样,通过kubectl get events获得当前命名空间下所有Events的列表。如果想查看某条Events的详细信息,是否也可以使用kubectl describe events $EventsName进行获取呢?我尝试了下,得到了下面的失败信息:

     

    20161219150032

     

    甚至连kubectl get events $EventsName也变得没那么好使了:

     

    20161219150039

     

    另外,Events的RESTful API为下图:

     

    20161219150048

     

    而通过最朴素的curl 之刃也没能找出Events的真身:

     

    20161219150055

     

    这着实让人“大吃一斤”。

    踏破铁鞋

    那么这个Events到底是何方神圣?常规手段居然拿它没一丁点办法了?不,还有一招json宝典待我祭出使用。我们知道kubectl get一些资源的时候可以通过它的-o json参数得到该资源的json格式的信息描述,那么对上面的Events进行kubectl get events -o json > /tmp/events.json,得到了一个json数组,里面的每一条都对应着一个Events对象:

     

    20161219150104

     

    Bingo!这就是我们要找的Events对应的实体json。仔细观察,图中红框里的名字正是kubectl get events里得到的Events名字,然而实际上它并不是真正的Events的名字。这是为何?在Kubernetes资源的数据结构定义中,一般都会包含一个metav1.TypeMeta和一个ObjectMeta成员,比如:

     

    20161219150115

     

    TypeMeta里定义了该资源的类别和版本,对应我们平时写json文件或者yaml文件时的kind: Pod和apiVersion: v1。OjbectMeta里定义了该资源的元信息,包括名称、命名空间、UID、创建时间、标签组等。

    Events的数据结构定义里同样包含了metav1.TypeMeta和ObjectMeta,那么从前面的json图中可以确定红框里的名字并不是该Events对象的真实名字,它对应的是InvolvedObject的名字,而蓝框里对应的才是Events的真实名字。然后使用kubectl get和curl进行验证:

     

    20161219150124

     

    到此,我们已经探明了Events的真名。仔细观察它的名字,发现它由三部分构成:”发生该Events的Pod名称” + “.” + “神秘数字串”。发生该Events的Pod名称倒是好理解,而后面的神秘数字串却不知从何而来。既然这个Events是来自这个Pod的状态变化,那么想必这个数字串也可以在Pod的详情里找到吧。出乎意料的是在Pod的详情json未曾找到这个神秘数字串,甚至把这个Pod祖上的ReplicaSet和Deployment也翻了个底朝天也是没有一点线索。捉妖行动陷入僵局。

    星宿Kubelet

    道高一尺,魔高一丈。纵使齐天大圣也得经常搬救兵,而不少时候这个妖怪就是某个星宿的坐骑或童子。拿起这个Events的json仔细观察,发现里面有个不起眼的component: kubelet:

     

    20161219150133

     

    回想一下kubelet的作用是:负责管理和维护在这台主机上运行着的所有容器,维持pod的运行状态(status)和它的期望值(spec)一致。kubelet启动时,会加载它本身的配置信息、接入容器运行时(Docker或Rkt)、以及定义kubelet与整个集群进行交互所需的信息。在启动后,会进行一系列的初始化工作,创建ContainerManager、设置OOMScoreAdj值、创建DiskSpaceManager、PodManager等等。那么会不会是kubelet为这个Pod创建了该Events呢?

    为了解答这个问题,不得不拿出尘封已久的究极“源码大法”。

    果然在Kubernetes源码的kubernetes/pkg/kubelet/events/event.go里有了一些收获。event.go里定义了是Events资源常用的一些常量,挑选列出如下:

    const (
    FailedToStartContainer = “Failed”
    BackOffStartContainer = “BackOff”
    ErrImageNeverPullPolicy = “ErrImageNeverPull”
    BackOffPullImage = “BackOff”
    FailedSync = “FailedSync”

    )

    这里面的不少我们平时都会经常遇到。它们是各种事件的原因列表,包含容器事件(创建、启动、失败等)、镜像事件(镜像拉取失败等)、kubelet事件(节点失效、节点不可调度等)、Pod Worker事件(同步失败)等。随便拿出一条进行暴力搜寻,比如”FailedToStartContainer”,发现除了在此处的定义进行了引用外,还在kubernetes/pkg/kubelet/dockertools/docker_manager.go里711行进行了引用:

    dm.recorder.Eventf(ref, api.EventTypeWarning, events.FailedToStartContainer, “Failed to start container with docker id %v with error: %v”, utilstrings.ShortenString(createResp.ID, 12), err)

    由此更加确认的是Events跟Kubelet密不可分。循着这条线索一直往下,还会有什么惊奇的发现?

    火眼金睛

    上面引用了docker_manager.go里的一行,除开事件本身外,里面还有一些关键词值得琢磨:dm, recorder, Eventf。

    dm是结构体DockerManager的实例,该结构体定义也在这个文件中。定义比较长,这里就不贴出来了,它包含了DockerInterface的成员、EventRecorder的成员、OSInterface的成员以及cadvisorapi.MachineInfo的成员等等。这个EventRecorder的定义在k8s.io/kubernetes/pkg/client/record/event.go里,是一个接口,可以按照EventSource的表现记录相应的事件。
    type EventRecorder interface {
    Event(object runtime.Object, eventtype, reason, message string)
    Eventf(object runtime.Object, eventtype, reason, messageFmt string, args …interface{})
    PastEventf(object runtime.Object, timestamp unversioned.Time, eventtype, reason, messageFmt string, args …interface{})
    }

    在这个文件的285~295行有对这个三个接口的实现:

    func (recorder *recorderImpl) Event(object runtime.Object, eventtype, reason, message string) {
    recorder.generateEvent(object, unversioned.Now(), eventtype, reason, message)
    }
    func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args …interface{}) {
    recorder.Event(object, eventtype, reason, fmt.Sprintf(messageFmt, args…))
    }
    func (recorder *recorderImpl) PastEventf(object runtime.Object, timestamp unversioned.Time, eventtype, reason, messageFmt string, args …interface{}) {
    recorder.generateEvent(object, timestamp, eventtype, reason, fmt.Sprintf(messageFmt, args…))
    }

    不管是PastEventf()、Eventf()还是Event()最终都指向了辅助函数generateEvent(),它的实现在255行:

    func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp unversioned.Time, eventtype, reason, message string) { // 获取发生事件的对象,比如前面说到的Pod
    ref, err := api.GetReference(object) if err != nil {
    glog.Errorf(“Could not construct reference to: ‘%#v’ due to: ‘%v’. Will not report event: ‘%v’ ‘%v’ ‘%v'”, object, err, eventtype, reason, message) return
    }
    // 验证事件类型
    if !validateEventType(eventtype) {
    glog.Errorf(“Unsupported event type: ‘%v'”, eventtype) return
    }
    // 生成Event
    event := recorder.makeEvent(ref, eventtype, reason, message)
    event.Source = recorder.source

    go func() {
    // NOTE: events should be a non-blocking operation
    defer utilruntime.HandleCrash()
    // 将Event进行广播
    recorder.Action(watch.Added, event)
    }()
    }

    recorder.makeEvent()就是这个Events的真正来源:

    func (recorder *recorderImpl) makeEvent(ref *api.ObjectReference, eventtype, reason, message string) *api.Event { t := unversioned.Time{Time: recorder.clock.Now()} namespace := ref.Namespace
    if namespace == “” {
    namespace = api.NamespaceDefault
    }
    return &api.Event{
    ObjectMeta: api.ObjectMeta{
    // 事件的命名规则
    Name: fmt.Sprintf(“%v.%x”, ref.Name, t.UnixNano()),
    Namespace: namespace,
    },
    InvolvedObject: *ref,
    Reason: reason,
    Message: message,
    FirstTimestamp: t,
    LastTimestamp: t,
    Count: 1,
    Type: eventtype,
    }
    }

    到此恍然大悟,原来前面所说的Events的命名规则:”发生该Events的Pod名称” + “.” + “神秘数字串”实际上是”ref.Name” + “.” + “t.UnixNano())”。

    终于找到了Events的真身,原来它是Kubelet负责用来记录多个容器运行过程中的事件,命名由被记录的对象和时间戳构成。前面看起来难以捉摸的表现最终还是逃不过火眼金睛。到此上篇解决了Events从哪儿来的问题,暂告一段落。在下篇中将对Events关于到哪儿去、怎么根据Pod找到对应的Events等进行深度拷问。欢迎继续关注!

    本文中出现的curl 之刃、json宝典、源码大法均属于为了轻松阅读体验而凭空捏造的词汇,分别对应用命令行工具curl进行访问和实验、查看该对象的json信息、阅读源码寻找答案释疑。

    来源:Kubernetes(K8s)Events介绍(上)

    展开全文
  • Nginx配置晋级之路(四)---events模块

    千次阅读 2018-07-19 16:38:30
    本文介绍events模块。如果对你有用请加关注。 #全局配置 events { accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off #...
  • OSAL消息机制及使用示例

    千次阅读 2015-08-05 15:50:11
    上一次我们讲到OSAL通过定时器循环产生事件来触发任务,  接下来分析一下消息机制,我们通过一个简单的例子来说明消息任何使用 /***********消息有效数据缓冲区结构***********/ typedef struct ...
  • Server-Sent Events 教程

    千次阅读 2018-05-04 21:02:06
    服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(以下简称 SSE)。本文介绍它的用法。一、SSE 的本质严格地说,HTTP 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是...
  • Nodejs源码解析之events

    千次阅读 2015-12-04 09:27:07
    Nodejs中的events模块是很常见的模块,其实现了事件注册,通知等功能,是...var events = require('events'); // 创建EventEmitter对象 var eventEmitter = new events.EventEmitter();//回调函数1 var listener1 = fun
  • 一、pointer-events:none是? pointer-events是CSS3中又一冉冉的属性,其支持的值牛毛般多,不过大多都与SVG相关,我们可以不用理会。当下,对于偶们来讲,与SVG划开界线值得一提的就是[none|auto]两个属性值了。...
  • 前段时间,为客户定制了一个类似看板的东西,用户可以通过看板了解任务的处理情况,通过APP扫面页面上的二维码就可以领取任务,而当任务被领取以后需要通知当前页面刷新。原本这是一个相对简单的需求,可是因为APP端...
  • Kubernetes Events介绍(中)

    千次阅读 2017-02-06 16:17:03
    上一回,历经千辛万苦终于破解了Events的姓名之谜,(Kubernetes(K8s)Events介绍(上))寻得Events真身。那么Events的身世究竟如何?根据Pod怎样才能找到对应的Events?本回将一一揭开谜底。 顺藤摸瓜 前面说...
  • CSS3 pointer-events:none

    千次阅读 2012-05-10 19:41:46
    « ... JS前端验证与用户自由...CSS3 pointer-events:none应用举例及扩展 by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=2091 一、pointer-events:none是? p
  • alter system set events

    千次阅读 2012-01-23 14:29:04
    system set events 格式: alter system|session set events ‘[eventnumber|immediate] trace name eventname [forever] [, level levelnumber] : …….’   通过:符号,...
  • alter session set events 详解

    千次阅读 2013-04-01 15:23:30
    一、Oracle跟踪文件  Oracle跟踪文件分为三种类型,一种是后台报警日志文件,记录数据库在启动、关闭和运行期间后台进程的活动情况,如表空间创建、回滚段创建、某些alter命令、日志切换、错误消息等。...
  • events模块只提供了一个对象,events.EventEmitter 他的核心是 事件发射 和 事件监听 功能   每个事件由一个事件名(用于标识事件),和多个参数组成。   事件名:字符串,通常表达一定的语义;   事件...
  • nodejs中的事件events

    千次阅读 2018-01-09 16:58:18
    1.Events 例子,一个绑定了一个监听器的 EventEmitter 实例。 eventEmitter.on() 方法用于注册监听器,eventEmitter.emit() 方法用于触发事件。 const EventEmitter = require('events'); class MyEmitter ...
  • jQuery - Events事件 - click单击

    万次阅读 2007-11-13 22:25:00
    jQuery - Events事件 - click单击jQuery支持绑定HTML元素的click事件, 函数的第一个参数是event对象,在IE中,使用event.srcElement获取触发事件的对象,而在Firefox中,使用 event.target获取触发事件的对象,...
  • dataEvents:[{ type:'change',fn: function(e) { alert('') } }] 发现不执行这个方法。我是用addRowData的方式增加一行的,但是dataEvents方法无法执行,请问是不是用...
  • 模块: events 源码: events.js EventEmitter类, 是node中事件的基础, 实现了事件模型需要的接口, 包括addListener,removeListener, emit及其ta工具方法. 同原生javascript事件类似, 采用了发布/订阅(观察者)的...
  • title: 【概率论】2-2:独立事件(Independent Events) categories: Mathematic Probability keywords: Independent Events 独立事件 Independent of Several Events 多个事件独立 Coditionally ...

空空如也

1 2 3 4 5 ... 20
收藏数 382,440
精华内容 152,976
关键字:

events