天天看點

【圖解 Knative】剖析 Eventing Broker-Trigger 實作原理1. 背景介紹

1. 背景介紹

我們都知道,

Knative

有兩個主要的子項目:

Serving

Eventing

。其中 關于

Serviing

可以檢視之前的一篇公衆号文章 【超詳細】深入探究 Knative 擴縮容的奧秘。

Eventing

将系統中的服務以事件驅動的方式松耦合的綁定在一起:即事件發送者不關注誰來消費事件,事件消費者也不關注事件是由誰産生的。

Eventing

中有多種事件組合的方式,比如:

  • 最簡單的

    Source

    ->

    Service

    直接綁定
  • 通過

    channel

    subscriptions

    訂閱的方式
  • 并行事件流處理 的方式

    Parallel

    ,以及串行事件流處理的方式

    Sequence

  • 以及支援事件過濾的

    Broker & Trigger

    也是本文将要重點介紹的模式
✅注:對于其他幾種事件組合的方式,感興趣的可以在官網查閱 https://knative.dev/docs/eventing/

2. 工作原理介紹

【圖解 Knative】剖析 Eventing Broker-Trigger 實作原理1. 背景介紹

上圖展示的是

Broker & Trigger

模型的中

Event

傳遞的基本方式,其中事件傳遞的格式是标準的

CLoudEvent

的格式。簡要介紹下圖中的流程:

  1. 事件由事件源

    Source

    産生, Knative 支援多種事件源,如

    GitHub

    Heartbeats

    k8s

    ContainerSource

    等,更多

    Source

    可在官網查閱 https://knative.dev/docs/eventing/sources/,也可以自定義

    Source

    ,參考之前發的一篇公衆号為 Serverless 平台插上騰飛的翅膀--自定義 Faas 事件驅動事件源。
  2. 圖中 事件源産生

    type

    foo

    的事件,發送到

    Broker

    ,其中 有三個

    Trigger

    綁定了

    Broker

    ,兩個

    Trigger

    filter

    type:foo

    ,也就是會關注

    type=foo

    的事件,然後發送給對應的消費者。
  3. Service1

    Service3

    隻是單純的消費,并不回複事件
  4. Service2

    收到事件後回複

    type=bar

    的事件,事件重新傳遞到 Broker上,此時隻有一個 Trigger 過濾了

    type:bar

    事件被傳送到

    Service3

    消費。
  5. 其中消費者是否回複事件是可選的。
關于圖中的執行個體 yaml,可參考

附錄

章節

3. 底層實作原理

上面介紹了

Broker & Trigger

的工作原理,現在從底層實作的角度進一步講解。

Knative Eventing 事件傳遞過程中依賴消息通道 Channel,為了便于持久化,生産環境使用可持久化的消息通過( 本文以 NatsStreaming 為例) 來做事件的消息通道,如果是開發調試,則直接用 InMemoryChannel 即可(隻會儲存在記憶體中,不會持久化)

先上圖

【圖解 Knative】剖析 Eventing Broker-Trigger 實作原理1. 背景介紹
  • 圖中包含控制平面與資料平面,圖中箭頭:控制平面為實線,資料平面為虛線
  • 實線的方框為 Knative 元件,虛線的方框為 k8s CR 資源

下面分别從資料平面和控制平面分别講解

3.1 資料平面

EventSource------> Broker------>Trigger------->SubScriber

1. EventSource------> Broker

Broker

可以手動生成,或者通過給

namespace

打 label

eventing.knative.dev/injection:true

,讓

sugar-controller

會自動生成對應的

Broker

執行個體

EventSource

一般通過

SinkURI

環境變量将

Broker

的 位址傳入 。比如,

Broker

的位址為

http://broker-ingress.knative-eventing.svc.cluster.local/default/default

,該位址為

broker-ingress

的位址,而

broker-ingress

通過 請求

URL

path

可以得到

Broker

的資訊,比如

/default/default

表示

default namespace

下名為

default

Broker

# kubectl get broker
NAME      URL                                                                        AGE   READY   REASON
default   http://broker-ingress.knative-eventing.svc.cluster.local/default/default   46h   True
           

2.Broker------>Trigger

broker-ingress

****得到

Broker

的資訊(name namespace)之後,可以得到

Broker

status

資訊,如下得到

channelAddress

的位址

(http://default-kne-trigger-kn-channel.default.svc.cluster.local)

apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
  name: default
  namespace: default
status:
  address:
    url: http://broker-ingress.knative-eventing.svc.cluster.local/default/default
  annotations:
    knative.dev/channelAPIVersion: messaging.knative.dev/v1beta1
    knative.dev/channelAddress: http://default-kne-trigger-kn-channel.default.svc.cluster.local
    knative.dev/channelKind: NatssChannel
    knative.dev/channelName: default-kne-trigger
           

channelAddress

的位址是個svc 的位址,通過

externalName

指向

natss-ch-dispatcher

# kubectl get svc default-kne-trigger-kn-channel
NAME                             TYPE           CLUSTER-IP   EXTERNAL-IP                                              PORT(S)   AGE
default-kne-trigger-kn-channel   ExternalName   <none>       natss-ch-dispatcher.knative-eventing.svc.cluster.local   <none>    46h
           

natss-ch-dispatcher

負責将 消息(主題為

channel.Name + "." + channel.Namespace

) 釋出到

Natss-Streaming

元件

3. Trigger------->SubScriber

natss-ch-dispatcher

****不僅負責釋出,還負責訂閱消息,

natss-ch-dispatcher

****watch

natssChannel

(見下面的

NatssChannel

), 擷取

natssChannel

subscriber

的位址

subscriberUri

,通過

subscriberUri

發送消息給

broker-filter

,跟

broker-ingress

一樣,

subscriberUri

的位址是

broker-filter

的 位址,通過請求

path

區分哪個

trigger

,請求 path :

/triggers/<trigger namespace>/<trigger name>/<trigger UID>

apiVersion: messaging.knative.dev/v1beta1
kind: NatssChannel
metadata:
  name: default-kne-trigger
  namespace: default
spec:
  subscribers:
  - generation: 1
    replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default
    subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger2/c0f3f1bb-9a25-4fb2-b803-fc5cd74e57da
    uid: 9b4c991a-8912-4333-aa5a-caf053e5ee9c
  - generation: 1
    replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default
    subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger3/28e7ba73-d514-4aea-a0de-7946fc21e7cc
    uid: 56d00260-e69f-4d7a-bd05-c81479774a95
  - generation: 1
    replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default
    subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger1/3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3
    uid: 963fd671-097f-489a-a857-c1803ad3fb19
status:
  address:
    url: http://default-kne-trigger-kn-channel.default.svc.cluster.local
           

broker-filter

擷取到

Trigger

的資訊後,通過 根據 Trigger 的filter 将消息過濾,再決定是否将消息發給 對應的

subscriber

,

subscriber

可以從

Trigger

status

subcriberUri

擷取到,見下圖,對于

subscriber

Reply 的消息,

broker-filter

發送到

replyUri

位址上,

http://broker-ingress.knative-eventing.svc.cluster.local/default/default

,也就是發送給 Broker (實際是

broker-ingress

)。

apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: trigger1
  namespace: default
spec:
  broker: default
  filter:
    attributes:
      type: dev.knative.sources.ping
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: service1
      namespace: default
status:
  subscriberUri: http://service1.default.svc.cluster.local
           

至此資料面的通信流就完成了,接下來看控制面的資料流。

3.2 控制平面

控制平面主要看上圖中的實線部分,此處再貼一下圖
【圖解 Knative】剖析 Eventing Broker-Trigger 實作原理1. 背景介紹

接下來按流程講解

  • 1.1

    mt-broker-controller

    watch

    Broker

    的建立
  • 1.2

    mt-broker-controller

    根據

    Broker

    的配置,建立對應的

    Channel

    ,此處為

    NatssChannel

  • 1.3

    Natss-ch-controller

    watch

    NatssChannel

    的建立,更新

    Natss-Streaming

    的服務端狀态到

    NatssChannel

    的 status
  • 1.4

    Natss-ch-controller

    建立 svc,externalname指向

    natss-ch-dispatcher

  • 1.5

    mt-broker-controller

    watch

    NatssChannel

    的status
  • 1.6

    mt-broker-controller

    更新

    Broker 的status,

    其中包含:

    Broker

    address

    broker-ingress

    的位址),

    channel

    address

    ,供

    broker-ingress

    使用
  • 2.1

    mt-broker-controller

    watch

    Trigger

  • 2.2

    mt-broker-controller

    根據

    Trigger(含 subscriber 的資訊)

    建立

    subscription,

    其中包含

    subsciber(broker-filter)

    的位址

    和 Broker

    的資訊
apiVersion: messaging.knative.dev/v1
kind: Subscription
metadata:
  name: default-trigger1-3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3
  namespace: default
spec:
  channel:
    apiVersion: messaging.knative.dev/v1beta1
    kind: NatssChannel
    name: default-kne-trigger
  reply:
    ref:
      apiVersion: eventing.knative.dev/v1
      kind: Broker
      name: default
      namespace: default
  subscriber:
    uri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger1/3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3
           
  • 2.3

    eventing-controller

    watch

    subscription

    ,解析

    subcriber

    replyUri

    的位址(

    broker-ingress

    的位址)
  • 2.4

    eventing-controller

    根據

    subcription

    更新

    Natss-Channel

    :

    subsriberUrl

    replyUrl

spec:
  subscribers:
  - generation: 1
    replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default
    subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger2/c0f3f1bb-9a25-4fb2-b803-fc5cd74e57da
    uid: 9b4c991a-8912-4333-aa5a-caf053e5ee9c
  - generation: 1
    replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default
    subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger3/28e7ba73-d514-4aea-a0de-7946fc21e7cc
    uid: 56d00260-e69f-4d7a-bd05-c81479774a95
  - generation: 1
    replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default
    subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger1/3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3
    uid: 963fd671-097f-489a-a857-c1803ad3fb19
status:
  address:
    url: http://default-kne-trigger-kn-channel.default.svc.cluster.local
           

2.5

mt-broker-controller

根據 subscription 和 broker 的狀态 更新 Trigger 的狀态

控制面的邏輯就完了,和資料面的邏輯結合的地方在于:

broker-ingress

broker-filter

  1. broker-ingress

    watch

    Broker

    ,從

    Broker

    status

    中擷取

    channel

    的位址(

    natss-ch-dispatch

    svc

    的位址)
  2. broker-filter

    watch

    Trigger

    ,根據 trigger 中subscriber 位址,将event filter 後決定是否發送到 對應的 target

至此,整個流程都講完了,可以按照附錄中的資源,建立一下,看看其中的資源。

附錄

  1. broker.yaml
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
  name: default
  namespace: default
           
  1. trigger1.yaml
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: trigger1
spec:
  filter:
    attributes:
      type: foo
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: service1
           
  1. trigger2.yaml
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: trigger2
spec:
  filter:
    attributes:
      type: foo
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: service2
           
  1. trigger3.yaml
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: trigger3
spec:
  filter:
    attributes:
      type: bar
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: service3
           
  1. service1.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: service1
spec:
  template:
    spec:
      containers:
        - image: docker.io/zhaojizhuang66/event-display:v1
           

5.service3.yaml (service1和service3 一樣都是列印接收到的 event)

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: service1
spec:
  template:
    spec:
      containers:
        - image: docker.io/zhaojizhuang66/event-display:v1
           
  1. service2.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: service2
spec:
  template:
    spec:
      containers:
        - image: docker.io/zhaojizhuang66/event-display-with-reply:v1
           

關注公衆号: Knative,了解更多 Serverless 、Knative,雲原生相關資訊

關注公衆号,回複 "進群",即可進群與衆多雲原生 Serverless 技術大佬探讨技術,探讨人生。
【圖解 Knative】剖析 Eventing Broker-Trigger 實作原理1. 背景介紹

繼續閱讀