跳到主要内容

APISIX 工作原理

本文介绍 APISIX 的主要组件如何协同处理请求,包括配置存储、路由器、插件引擎、请求生命周期和热更新模型。

文末的相关资源可帮助你进一步了解各主题。

概览

APISIX 是一个运行在 OpenResty 中的 Lua 应用。OpenResty 通过 lua-nginx-module 扩展 NGINX。NGINX 负责连接处理、工作进程模型和请求阶段机制;APISIX 通过挂载到各个阶段的 Lua 程序完成路由、插件执行和上游选择。

本页从请求流角度说明 APISIX。所有由 APISIX 处理的请求都会经过三个运行时组件:

  • 提供路由和插件定义的配置存储。
  • 将请求匹配到路由的路由器。
  • 在对应 NGINX 阶段运行匹配路由插件的插件引擎。

以下各节先介绍这些组件,再跟踪一个请求如何依次经过它们。负载均衡、服务发现和 Admin API 等其他组件会在请求流中的相关位置提及,并在各自页面中详细介绍。

下图展示默认传统部署模式中的请求流和配置流,其中 etcd 是配置来源。路由器、插件引擎、负载均衡器和内存配置均位于 APISIX 工作进程内:


独立部署模式保留相同的请求路径,但配置来源不同:磁盘上的 apisix.yaml(或 apisix.json)是配置来源,文件更改时各工作进程会重新加载配置:

配置存储

在默认部署模式中,APISIX 使用 etcd 作为路由、上游、服务、消费者、SSL 证书、插件配置和全局规则的事实来源。每个 NGINX 工作进程通过长轮询订阅 etcd,并在内存中保存一份配置副本。

通过 Admin API 创建或更新资源时,更改会写入 etcd。工作进程通过 watch 机制观察更改,并独立重建内存中的路由结构,不需要重新加载、重启或跨工作进程协调。配置更改会应用到运行中的工作进程,不会中断现有连接。

APISIX 支持两种采用不同配置来源的部署模式:

  • 传统模式(默认):etcd 是配置的事实来源,每个工作进程都会 watch etcd,即上图所示模式。
  • 独立部署模式:每个工作进程完全在内存中保存配置。配置从磁盘上的 apisix.yaml(或 apisix.json)加载,并在文件更改时重新加载,不使用 etcd。

本页其余部分介绍的请求处理行为在所有模式中相同,区别仅在于配置来源。有关支持的完整模式列表和配置方式,请参阅部署模式

路由器

路由器将传入请求匹配到路由。APISIX 使用 Radix Tree(压缩前缀树)作为匹配引擎。

配置路由时,路由会被插入树中。处理请求时,URI 的匹配时间与 URI 长度相关,而不是与已配置的路由数量相关。因此,即使路由数量增加,匹配开销也大致保持不变。

APISIX 内置三种 HTTP 路由器,它们使用不同的字段作为树的主索引:

  1. radixtree_host_uri(默认):使用 host + uri 作为主索引,同时匹配请求 Host 和 URI。
  2. radixtree_uri:仅使用 uri 作为主索引,Host 不属于索引。
  3. radixtree_uri_with_parameter:与 radixtree_uri 相同,同时支持 /user/:id 之类的路径参数。

当前使用的 HTTP 路由器通过 config.yaml 中的 apisix.router.http 配置选择。TLS 握手期间的 SSL 证书选择使用独立的 radixtree_sni 路由器,将客户端 SNI 与已配置的证书匹配。有关 HTTP 路由器的配置和功能对比,请参阅路由选项

插件引擎

路由器确定匹配路由后,插件引擎会运行适用于该请求的插件。待运行的插件集合来自:

  • 匹配的路由。
  • 路由关联的服务(如果有)。
  • 匹配的消费者和消费者组(如果有)。
  • 任何全局规则。

在每个 NGINX 阶段,引擎按照插件的 priority 字段排序(值越大越先执行),并依次调用各插件对应的阶段函数。插件可以修改请求或响应,也可以提前终止请求。例如,身份认证插件可以在请求到达上游前返回 401。

插件会定义一个或多个阶段函数。HTTP 流量会经过 rewriteaccessbefore_proxyheader_filterbody_filterlog 阶段。

大多数插件以 Lua 模块形式提供。APISIX 还支持通过外部插件运行器执行 Go、Java 和 Python 插件,并通过 WASM 运行器支持 WebAssembly 模块。有关阶段模型,以及如何组合路由、服务和消费者上的插件配置,请参阅插件

请求生命周期

下表按照 NGINX 阶段展示 APISIX 如何处理单个 HTTP 请求:

阶段APISIX 会做什么
ssl_client_hello / ssl_certificate使用客户端的 SNI 值,从 radixtree_sni 路由器中选择证书。
access使用 HTTP 路由器匹配请求并确定路由,然后按优先级运行该路由在 rewriteaccess 阶段的插件。插件可以在此提前终止请求,例如身份认证插件可直接返回 401。选定上游后,系统会在 NGINX 将请求转发到上游之前运行 before_proxy 阶段的插件。
balancer根据配置的负载均衡算法以及可选的主动健康检查状态,从路由的上游定义中选择一个上游节点。
header_filter在 NGINX 组装响应头时运行响应头处理插件。
body_filter在响应体以流式方式返回客户端时运行响应体处理插件。
log响应发送完成后运行日志插件。大多数日志插件使用 NGINX 定时器,因此客户端无需等待日志写入完成。

下图展示 APISIX 对单个 HTTP 请求执行路由、插件阶段、上游选择和代理的顺序:


Stream(四层)流量遵循类似但更精简的生命周期:

阶段APISIX 会做什么
preread根据流路由器匹配连接以识别路由,然后运行路由的prereadbefore_proxy插件. 插件可能在此关闭连接 。
balancer从路由的上游定义中选择一个单一的上游节点,使用配置的负载平衡算法,并选择主动健康检查状态.
log连接关闭后运行日志插件 。

热配置更新

每个工作进程都在内存中保存自己的配置副本,并从配置来源刷新。因此,应用配置变更时无需重新加载 NGINX、重启工作进程,也无需在工作进程之间进行协调。

在默认传统模式中,通过 Admin API 所做的更改会写入 etcd,并在各工作进程的下一个 watch 周期中获取,无需单独的应用步骤。在独立部署模式中,apisix.yaml(或 apisix.json)更改时也会自动应用。

额外资源