【图解 Knative】剖析 Eventing Broker-Trigger 实现原理
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
的格式。简要介绍下图中的流程:
事件由事件源
Source
产生, Knative 支持多种事件源,如GitHub
、Heartbeats
、k8s
、ContainerSource
等,更多Source
可在官网查阅 https://knative.dev/docs/eventing/sources/,也可以自定义Source
,参考之前发的一篇公众号为 Serverless 平台插上腾飞的翅膀--自定义 Faas 事件驱动事件源。图中 事件源产生
type
为foo
的事件,发送到Broker
,其中 有三个Trigger
绑定了Broker
,两个Trigger
的filter
是type:foo
,也就是会关注type=foo
的事件,然后发送给对应的消费者。Service1
和Service3
只是单纯的消费,并不回复事件Service2
收到事件后回复type=bar
的事件,事件重新传递到 Broker上,此时只有一个 Trigger 过滤了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: defaultnamespace: default
status:address:url: http://broker-ingress.knative-eventing.svc.cluster.local/default/defaultannotations:knative.dev/channelAPIVersion: messaging.knative.dev/v1beta1knative.dev/channelAddress: http://default-kne-trigger-kn-channel.default.svc.cluster.localknative.dev/channelKind: NatssChannelknative.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-triggernamespace: default
spec:subscribers:- generation: 1replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/defaultsubscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger2/c0f3f1bb-9a25-4fb2-b803-fc5cd74e57dauid: 9b4c991a-8912-4333-aa5a-caf053e5ee9c- generation: 1replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/defaultsubscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger3/28e7ba73-d514-4aea-a0de-7946fc21e7ccuid: 56d00260-e69f-4d7a-bd05-c81479774a95- generation: 1replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/defaultsubscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger1/3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3uid: 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: trigger1namespace: default
spec:broker: defaultfilter:attributes:type: dev.knative.sources.pingsubscriber:ref:apiVersion: serving.knative.dev/v1kind: Servicename: service1namespace: default
status:subscriberUri: http://service1.default.svc.cluster.local
至此数据面的通信流就完成了,接下来看控制面的数据流。
3.2 控制平面
控制平面主要看上图中的实线部分,此处再贴一下图
接下来按流程讲解
1.1
mt-broker-controller
watchBroker
的创建1.2
mt-broker-controller
根据Broker
的配置,创建对应的Channel
,此处为NatssChannel
1.3
Natss-ch-controller
watchNatssChannel
的创建,更新Natss-Streaming
的服务端状态到NatssChannel
的 status1.4
Natss-ch-controller
创建 svc,externalname指向natss-ch-dispatcher
1.5
mt-broker-controller
watchNatssChannel
的status1.6
mt-broker-controller
更新Broker 的status,
其中包含:Broker
的address
(broker-ingress
的地址),channel
的address
,供broker-ingress
使用2.1
mt-broker-controller
watchTrigger
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-1970b6ab73e3namespace: default
spec:channel:apiVersion: messaging.knative.dev/v1beta1kind: NatssChannelname: default-kne-triggerreply:ref:apiVersion: eventing.knative.dev/v1kind: Brokername: defaultnamespace: defaultsubscriber:uri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger1/3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3
2.3
eventing-controller
watchsubscription
,解析subcriber
和replyUri
的地址(broker-ingress
的地址)2.4
eventing-controller
根据subcription
更新Natss-Channel
:subsriberUrl
和replyUrl
spec:subscribers:- generation: 1replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/defaultsubscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger2/c0f3f1bb-9a25-4fb2-b803-fc5cd74e57dauid: 9b4c991a-8912-4333-aa5a-caf053e5ee9c- generation: 1replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/defaultsubscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger3/28e7ba73-d514-4aea-a0de-7946fc21e7ccuid: 56d00260-e69f-4d7a-bd05-c81479774a95- generation: 1replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/defaultsubscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger1/3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3uid: 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
:
broker-ingress
watchBroker
,从Broker
的status
中获取channel
的地址(natss-ch-dispatch
的svc
的地址)broker-filter
watchTrigger
,根据 trigger 中subscriber 地址,将event filter 后决定是否发送到 对应的 target
至此,整个流程都讲完了,可以按照附录中的资源,创建一下,看看其中的资源。
附录
broker.yaml
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:name: defaultnamespace: default
trigger1.yaml
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:name: trigger1
spec:filter:attributes:type: foosubscriber:ref:apiVersion: serving.knative.dev/v1kind: Servicename: service1
trigger2.yaml
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:name: trigger2
spec:filter:attributes:type: foosubscriber:ref:apiVersion: serving.knative.dev/v1kind: Servicename: service2
trigger3.yaml
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:name: trigger3
spec:filter:attributes:type: barsubscriber:ref:apiVersion: serving.knative.dev/v1kind: Servicename: 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 技术大佬探讨技术,探讨人生。
【图解 Knative】剖析 Eventing Broker-Trigger 实现原理相关推荐
- 透过 In-memory Channel 看 Knative Eventing 中 Broker/Trigger 工作机制
In-memory Channel是当前Knative Eventing中默认的Channel, 也是一般刚接触Knative Eventing首先了解到的Channel.本文通过分析 In-memo ...
- 深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)
原文:http://www.cnblogs.com/artech/archive/2007/05/21/753620.html Microsoft 的Visual Studio为我们在应用开发中提供的 ...
- NGUI所见即所得之深入剖析UIPanel,UIWidget,UIDrawCall底层原理
NGUI所见即所得之深入剖析UIPanel,UIWidget,UIDrawCall底层原理 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 之 ...
- 深入剖析ASP.NET的编译原理之二:预编译(Precompilation)
(转载)在本篇文章的第一部分:[原创]深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation),详细讨论了ASP.NET如何进行动态编译的,现在我们来谈谈另外一种重 ...
- Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理
为什么80%的码农都做不了架构师?>>> Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理 本书使用高分辨率精心绘制的300多张图片,帮助大家理解操作系统特有 ...
- 万字长文剖析清楚 Go 语言 defer 原理
大纲 编译器怎么编译 defer `struct _defer` 数据结构 `struct _defer` 内存分配 执行 defer 函数链( `deferreturn` ) defer 怎么传递 ...
- (转)编码剖析@Resource注解的实现原理
http://blog.csdn.net/yerenyuan_pku/article/details/52860046 上文我们已经学会使用@Resource注解注入属性.学是学会了,但也仅限于会使用 ...
- (转)编码剖析Spring装配基本属性的原理
http://blog.csdn.net/yerenyuan_pku/article/details/52856465 上回我们已经讲到了Spring依赖注入的第一种方式,现在我们来详解第二种方式,须 ...
- (转)编码剖析Spring依赖注入的原理
http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...
最新文章
- 2017 OWASP十大安全趋势榜单变化解析
- Android中WebView的跨域漏洞分析和应用被克隆问题情景还原(免Root获取应用沙盒数据)...
- CVPR 2019 | 针对人脸识别系统的高效黑盒对抗攻击算法
- grootjs 简明教程
- 【转】C++从零实现神经网络
- [置顶]献给写作者的 Markdown 新手指南
- 如何在Win7旗舰版中安装并设置IIS
- 软考软件设计师(知识产权)
- 国外最流行的Bootstrap后台管理模板
- java smtp.126.com_java实现邮件发送
- 东北大学《传输原理》随堂练习
- 最长等差数列_算法题10 最长等差序列问题
- Padavan 路由器的入门级技巧
- 里氏代换和依赖倒转原则(二)
- HTML5新特性_笔记
- 牛刀:房价泡沫的破灭只是人性的回归
- emacs常用操作笔记
- 360个人图书馆 轻松解除网页防复制
- VS中的工程文件组织
- 夜神模拟器运行微信闪退如何解决?