HTTP 请求流¶
虽然 概述 描述了 Knative Serving 的逻辑组件,架构 描述了其整体架构,但本文档解释了 HTTP 请求流向在 Knative Serving 上运行的应用程序的行为和流程。
下图显示了 Knative Serving 的不同请求流和控制平面循环。请注意,某些组件(如自动伸缩器和 apiserver)不会在每次请求时更新,而是定期度量系统(这被称为控制平面)。

HTTP 路由器、激活器(activator)和自动伸缩器都是共享的集群级资源;这使得新的 Knative 服务在不使用时只需进行元数据开销,并允许更有效地管理和升级这些共享组件。
路由决策是在 HTTP 路由器(可插拔的入口层)上基于每个请求的级别进行的,并记录在请求的内部标头中。一旦请求被分配给一个 Revision,后续的路由就取决于度量的流量流;在低流量或零流量时,传入的请求被路由到激活器,而在高流量级别(可用突发容量大于 target-burst-capacity)时,流量被直接路由到应用程序 Pod。
从零开始扩展¶
当特定 Revision 的流量很低或为零时,HTTP 路由器会将流量发送到激活器,其中包含指示所选 Revision 的标头。激活器充当传入请求的缓冲区或队列——如果请求被路由到一个当前没有可用容量的 Revision,激活器会延迟该请求,并向自动伸缩器发出信号,表示需要额外的容量。
当自动伸缩器检测到 Revision 的可用容量低于请求的容量时,它会向 Kubernetes 请求增加 Pod 数量。
当这些新 Pod 准备就绪或现有 Pod 有容量时,激活器会将延迟的请求转发到就绪的 Pod。如果需要启动新 Pod 来处理请求,这就称为“冷启动”。
高流量¶
当一个 Revision 具有大量流量(可用突发容量大于 target-burst-capacity)时,入口路由器直接使用 Revision 的 Pod 地址进行编程,并且激活器从流量流中移除。这降低了延迟并提高了效率,因为不需要激活器的额外缓冲。在所有情况下,queue-proxy 仍然在请求路径中。
如果流量降至突发容量阈值以下(计算方式为:current_demand + target-burst-capacity > (pods * concurrency-target)),则入口路由器将被重新编程,以将流量发送到激活器 Pod。
入口和激活器之间的流量路由是通过将激活器端点的子集写入 Revision 服务的 Endpoints 来完成的。与 Revision 对应的 Kubernetes Service 是无选择器(selectorless)的,它可以包含 Revision 的 Pod 端点或激活器端点。使用无选择器服务的原因如下:
-
某些入口实现不允许跨命名空间的服务引用。激活器运行在
knative-serving命名空间中。 -
某些入口实现不能无缝处理路由端点所依赖的 Kubernetes 服务的更改。
-
通过基于每个 Revision 进行子集划分,传入的请求被引导到一个少量激活器,这些激活器可以更有效地做出就绪/未就绪容量决策。每个 Revision 的有效激活器数量少不是一个扩展问题,因为当 Revision 扩展以接收更多流量时,激活器将从请求路径中移除。
队列代理¶
queue-proxy 组件实现了一些功能来提高 Knative 的可靠性和扩展性
-
为自动伸缩器度量并发请求,特别是在从请求路径中移除激活器时。
-
如果请求,则实现
containerConcurrency请求并发的硬限制。 -
处理 Pod 终止时的优雅关闭(拒绝新请求,使就绪性检查失败,继续为现有请求提供服务)。
-
从用户容器外部报告 HTTP 指标和跟踪,以便可以度量基础架构延迟的贡献。
-
在启动期间(就绪之前),更积极地探测用户容器,以便比 Kubelet 探测(最快每秒一次)更早地提供服务。
-
为了支持此功能,Knative Serving 会将用户容器的
readinessProbe重写为 queue-proxy 的一个参数;queue-proxy 的就绪性检查结合了 queue-proxy 自身的就绪性和用户容器的就绪性。