4.3.5、notifications工作原理

通知(notifications)

registry支持webhook类型的通知架构。在manifest的推送和拉取、layer推送和拉取的时候,会触发通知。这些操作会被转换成一系列的事件。这些事件会被存放到一个registry内部的广播系统的有序队列中,等待被转发到端点中(Endpoints)。

注意:这个图片官网上没有显示。

端点(endpoints)

通知是通过HTTP请求方式发送给端点的。在每个registry实例里,每一个配置的端点都拥有独立的事件队列、重做配置和http目标。当在registry里进行一个操作时,它会转换成一个事件,下抛到一个内存队列中。当事件到达队列的末端时,会发起一个http请求将其发送到端点的队列中,这个发送的操作会持续到成功为止。事件的发送虽然是顺序的,但是不能保证它们在端点出的顺序。

配置(cofiguration)

让registry实例发送通知到端点,必须进行相应的设置。下面是一个简单的例子:

  notifications:
    endpoints:
      - name: alistener
        url: https://mylistener.example.com/event
        headers:
          Authorization: [Bearer <your token, if needed>]
        timeout: 500ms
        threshold: 5
        backoff: 1s

上面的例子中,在registry设置了一个端点https://mylistener.example.com/event来接收事件,http请求头携带信息“Authorization: Bearer ”。这个请求500毫秒超时。如果连续5次请求失败,等待一秒后再重试。

想了解更加详细的设置,请看《registry配置参考》notifications

一个有效的端点配置在registry启动的时候会输出相关的日志信息:

INFO[0000] configuring endpoint alistener (https://mylistener.example.com/event), timeout=500ms, headers=map[Authorization:[Bearer <your token if needed>]]  app.id=812bfeb2-62d6-43cf-b0c6-152f541618a3 environment=development service=registry

事件(events)

事件是一个定义良好的JSON数据,其作为通知请求的body。发送一个或多个事件时,它们被封装在一个envelope的结构体中。每一个事件都有唯一的ID。一个活动(action)还提供一个target,用来记录事件过程的变化。

可以通过查看docker的源码,去了解event这个字段的详细信息。

下面是一个push操作的响应JSON信息清单:

{
   "id": "asdf-asdf-asdf-asdf-0",
   "timestamp": "2006-01-02T15:04:05Z",
   "action": "push",
   "target": {
      "mediaType": "application/vnd.docker.distribution.manifest.v1+json",
      "size": 1,
      "digest": "sha256:0123456789abcdef0",
      "length": 1,
      "repository": "library/test",
      "url": "http://example.com/v2/library/test/manifests/latest"
   },
   "request": {
      "id": "asdfasdf",
      "addr": "client.local",
      "host": "registrycluster.local",
      "method": "PUT",
      "useragent": "test/0.1"
   },
   "actor": {
      "name": "test-actor"
   },
   "source": {
      "addr": "hostname.local:port"
   }
}

注意:自2.1版本后,target中的length 属性已经被size 替代,来迎合命名的习惯。两种设置方式在很长的一段时间都可以兼容,不过在新的代码中更加钟爱size 。

Envelope

envelope用json数据结构封装了一个或多个事件信息:

{
	"events": [ ... ],
}

虽然多个事件可能通过同一个envelope发送,但是事件和envelope之间没有任何必然的关系。例如,registry可以选择一组没有关系的事件,通过一个envelope组装它们,然后发送出去以减少发送请求次数。

一个完整的数据包还包含媒体类型 “application/vnd.docker.distribution.events.v1+json”,它被设置在请求的头部发送到端点。.

下面是一个完整事件的信息清单:

GET /callback
Host: application/vnd.docker.distribution.events.v1+json
Authorization: Bearer <your token, if needed>
Content-Type: application/vnd.docker.distribution.events.v1+json

{
   "events": [
      {
         "id": "asdf-asdf-asdf-asdf-0",
         "timestamp": "2006-01-02T15:04:05Z",
         "action": "push",
         "target": {
            "mediaType": "application/vnd.docker.distribution.manifest.v1+json",
            "length": 1,
            "digest": "sha256:0123456789abcdef0",
            "repository": "library/test",
            "url": "http://example.com/v2/library/test/manifests/latest"
         },
         "request": {
            "id": "asdfasdf",
            "addr": "client.local",
            "host": "registrycluster.local",
            "method": "PUT",
            "useragent": "test/0.1"
         },
         "actor": {
            "name": "test-actor"
         },
         "source": {
            "addr": "hostname.local:port"
         }
      },
      {
         "id": "asdf-asdf-asdf-asdf-1",
         "timestamp": "2006-01-02T15:04:05Z",
         "action": "push",
         "target": {
            "mediaType": "application/vnd.docker.container.image.rootfs.diff+x-gtar",
            "length": 2,
            "digest": "tarsum.v2+sha256:0123456789abcdef1",
            "repository": "library/test",
            "url": "http://example.com/v2/library/test/manifests/latest"
         },
         "request": {
            "id": "asdfasdf",
            "addr": "client.local",
            "host": "registrycluster.local",
            "method": "PUT",
            "useragent": "test/0.1"
         },
         "actor": {
            "name": "test-actor"
         },
         "source": {
            "addr": "hostname.local:port"
         }
      },
      {
         "id": "asdf-asdf-asdf-asdf-2",
         "timestamp": "2006-01-02T15:04:05Z",
         "action": "push",
         "target": {
            "mediaType": "application/vnd.docker.container.image.rootfs.diff+x-gtar",
            "length": 3,
            "digest": "tarsum.v2+sha256:0123456789abcdef2",
            "repository": "library/test",
            "url": "http://example.com/v2/library/test/manifests/latest"
         },
         "request": {
            "id": "asdfasdf",
            "addr": "client.local",
            "host": "registrycluster.local",
            "method": "PUT",
            "useragent": "test/0.1"
         },
         "actor": {
            "name": "test-actor"
         },
         "source": {
            "addr": "hostname.local:port"
         }
      }
   ]
}

响应(responses)

registry只是接受端点返回的响应码。如果端点返回一2xx或3xx的响应码(之后做重定向),消息将被视为交付和丢弃。

监控(monitoring)

端点的状态信息是通过一个http接口debug/vars进行报告,通常配置为“http://localhost:5001/debug/vars"

下面提供一个几个端点经历失败到自动恢复的例子:

"notifications":{
   "endpoints":[
      {
         "name":"local-5003",
         "url":"http://localhost:5003/callback",
         "Headers":{
            "Authorization":[
               "Bearer \u003can example token\u003e"
            ]
         },
         "Timeout":1000000000,
         "Threshold":10,
         "Backoff":1000000000,
         "Metrics":{
            "Pending":76,
            "Events":76,
            "Successes":0,
            "Failures":0,
            "Errors":46,
            "Statuses":{

            }
         }
      },
      {
         "name":"local-8083",
         "url":"http://localhost:8083/callback",
         "Headers":null,
         "Timeout":1000000000,
         "Threshold":10,
         "Backoff":1000000000,
         "Metrics":{
            "Pending":0,
            "Events":76,
            "Successes":76,
            "Failures":0,
            "Errors":28,
            "Statuses":{
               "202 Accepted":76
            }
         }
      }
   ]
}

如果在一个大型的应用中使用通知(notification),检测断点队列的"Pending"参数的大小是一个关键点。如果“failures”或队列的大小不断的增长,这表明有一更大的问题。

日志也是一个很有价值的监控信息。一个失败的端点将会输出下面类似的日志:

ERRO[0340] retryingsink: error writing events: httpSink{http://localhost:5003/callback}: error posting: Post http://localhost:5003/callback: dial tcp 127.0.0.1:5003: connection refused, retrying
WARN[0340] httpSink{http://localhost:5003/callback} encountered too many errors, backing off

上面的日志信息表明几个错误导致一个重试休眠,registry休眠结束后尝试重做。

注意事项

目前,队列都是常驻内存的,所以端点还是相当的可靠的。虽然,它们采用"尽力而为"思想去设计的消息发送,但是如果一个实例丢失了,消息还是会有被丢弃的风险。如果一个端点宕掉了,应该要确保在端点恢复之前不要让registry实例停止工作或者丢失端点的信息。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值