1. 背景介紹
我們都知道,
Knative
有兩個主要的子項目:
Serving
和
Eventing
。其中 關于
Serviing
可以檢視之前的一篇公衆号文章 【超詳細】深入探究 Knative 擴縮容的奧秘。
Eventing
将系統中的服務以事件驅動的方式松耦合的綁定在一起:即事件發送者不關注誰來消費事件,事件消費者也不關注事件是由誰産生的。
Eventing
中有多種事件組合的方式,比如:
- 最簡單的
->Source
直接綁定Service
- 通過
與channel
訂閱的方式subscriptions
- 并行事件流處理 的方式
,以及串行事件流處理的方式Parallel
Sequence
- 以及支援事件過濾的
也是本文将要重點介紹的模式Broker & Trigger
✅注:對于其他幾種事件組合的方式,感興趣的可以在官網查閱 https://knative.dev/docs/eventing/
2. 工作原理介紹
上圖展示的是
Broker & Trigger
模型的中
Event
傳遞的基本方式,其中事件傳遞的格式是标準的
CLoudEvent
的格式。簡要介紹下圖中的流程:
- 事件由事件源
産生, Knative 支援多種事件源,如Source
、GitHub
、Heartbeats
、k8s
等,更多ContainerSource
可在官網查閱 https://knative.dev/docs/eventing/sources/,也可以自定義Source
,參考之前發的一篇公衆号為 Serverless 平台插上騰飛的翅膀--自定義 Faas 事件驅動事件源。Source
- 圖中 事件源産生
為type
的事件,發送到foo
,其中 有三個Broker
綁定了Trigger
,兩個Broker
的Trigger
是filter
,也就是會關注type:foo
的事件,然後發送給對應的消費者。type=foo
-
和Service1
隻是單純的消費,并不回複事件Service3
-
收到事件後回複Service2
的事件,事件重新傳遞到 Broker上,此時隻有一個 Trigger 過濾了type=bar
事件被傳送到type:bar
消費。Service3
- 其中消費者是否回複事件是可選的。
關于圖中的執行個體 yaml,可參考 附錄
章節
3. 底層實作原理
上面介紹了
Broker & Trigger
的工作原理,現在從底層實作的角度進一步講解。
Knative Eventing 事件傳遞過程中依賴消息通道 Channel,為了便于持久化,生産環境使用可持久化的消息通過( 本文以 NatsStreaming 為例) 來做事件的消息通道,如果是開發調試,則直接用 InMemoryChannel 即可(隻會儲存在記憶體中,不會持久化)
先上圖
- 圖中包含控制平面與資料平面,圖中箭頭:控制平面為實線,資料平面為虛線
- 實線的方框為 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 控制平面
控制平面主要看上圖中的實線部分,此處再貼一下圖
接下來按流程講解
- 1.1
watchmt-broker-controller
的建立Broker
- 1.2
根據mt-broker-controller
的配置,建立對應的Broker
,此處為Channel
NatssChannel
- 1.3
watchNatss-ch-controller
的建立,更新NatssChannel
的服務端狀态到Natss-Streaming
的 statusNatssChannel
- 1.4
建立 svc,externalname指向Natss-ch-controller
natss-ch-dispatcher
- 1.5
watchmt-broker-controller
的statusNatssChannel
- 1.6
更新mt-broker-controller
其中包含:Broker 的status,
的Broker
(address
的位址),broker-ingress
的channel
,供address
使用broker-ingress
- 2.1
watchmt-broker-controller
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
watcheventing-controller
,解析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
:
-
watchbroker-ingress
,從Broker
的Broker
中擷取status
的位址(channel
的natss-ch-dispatch
的位址)svc
-
watchbroker-filter
,根據 trigger 中subscriber 位址,将event filter 後決定是否發送到 對應的 targetTrigger
至此,整個流程都講完了,可以按照附錄中的資源,建立一下,看看其中的資源。
附錄
- broker.yaml
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
name: default
namespace: default
- 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
- 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
- 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
- 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
- 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 技術大佬探讨技術,探讨人生。