一,概念
Apisix是一个开源的,动态的,可扩展的,高性能云原生API网关,用于所有的API和微服务
与其他API网关的不同之处:
- 具有平台无关性和完全动态的特性,如支持多种协议、细粒度路由和多语言支持
- 使用 etcd 来保存和同步配置,而不是使用如 PostgreSQL 或 MySQL 这类的关系数据库。etcd 中的实时事件通知系统比这些替代方案更容易扩展。这允许 APISIX 实时同步配置,使代码简洁,并避免单点故障
- 支持热加载插件
- 提供了更好的性能
完全动态是指当你在更改一个配置后,只需要重新加载配置文件就可以使其生效
- 重新加载插件
- 代理重写
- 对请求进⾏镜像复制
- 对请求进⾏修改
- 健康状态的检查
- 动态控制指向不同上游服务的流量⽐
API网关
API 网关是位于客户端与后端服务集之间的 API 管理工具。API 网关相当于反向代理,用于接受所有 API 的调用、整合处理这些调用所需的各种服务,并返回相应的结果。API 网关通常会处理跨 API 服务系统使用的常见任务,并统一接入进行管理。通过 API 网关的统一拦截,可以实现对 API 接口的安全、日志等共性需求,如用户身份验证、速率限制和统计信息。
Route
路由负责根据定义的规则匹配客户端的请求,根据匹配结果加载和执行相应的插件,以及将请求转发到指定的上游服务
路由中主要包含三部分内容:
- 匹配规则:比如 uri、host、remote_addr 等等,你也可以自定义匹配规则
- 插件配置:你可以根据业务需求,在路由中配置相应的插件来实现功能。
- 上游信息:路由会根据配置的负载均衡信息,将请求按照规则转发至相应的上游。
Upstream
上游是一组具有相同工作的目标节点。它是对虚拟主机的抽象,即应用层服务或节点的抽象。
上游的作用是按照配置规则对服务节点进行负载均衡,它的地址信息可以直接配置到路由或服务上。当多个路由或服务引用同一个上游时,可以通过创建上游对象,在路由或服务中使用上游 ID 的方式引用上游,减轻维护压力。
APISIX 的 Upstream 对象除了基本的负载均衡算法外,还支持对上游做主被动健康检查、重试等逻辑。
Load balancing
负载均衡管理客户端和服务器之间的流量。它是一种用于决定哪个服务器处理特定请求的机制,从而提高性能、可伸缩性和可靠性。
Consumer
消费者是指消费API的应用或开发者,需要一个唯一的用户名和认证插件。需要与用户认证体系配合才能使用
Consumer Group
消费组对象用于管理后端服务对开发人员的可见性。后端服务首先对组可见,然后这些组中的开发人员可以查看和订阅与这些组关联的产品。
Service
Service 也称为服务,是某类 API 的抽象(也可以理解为一组 Route 的抽象)。它通常与上游服务抽象是一一对应的,Route 与 Service 之间,通常是 N:1 的关系。
Plugin
Plugin 也称之为插件,它是扩展 APISIX 应用层能力的关键机制,也是在使用 APISIX 时最常用的资源对象。插件主要是在 HTTP 请求或响应生命周期期间执行的、针对请求的个性化策略。插件可以与路由、服务或消费者绑定。
插件配置只有一份会生效,其优先级由高到低顺序是:消费者 > 路由 > 插件配置 > 服务
在插件执行过程中也会涉及 6 个阶段,分别是 rewrite、access、before_proxy、header_filter、body_filter 和 log
Plugin Config
属于一组通用插件配置的抽象。
二、软件架构
构建于 NGINX + ngx_lua 的技术基础之上,充分利用了 LuaJIT 所提供的强大性能
APISIX 主要分为两个部分:
- APISIX 核心:包括 Lua 插件、多语言插件运行时(Plugin Runner)、Wasm 插件运行时等;
- 功能丰富的各种内置插件:包括可观测性、安全、流量控制等。
APISIX 在其核心中,提供了路由匹配、负载均衡、服务发现、API 管理等重要功能,以及配置管理等基础性模块。除此之外,APISIX 插件运行时也包含其中,提供原生 Lua 插件的运行框架和多语言插件的运行框架,以及实验性的 Wasm 插件运行时等。APISIX 多语言插件运行时提供多种开发语言的支持,比如 Golang、Java、Python、JS 等。
APISIX 目前也内置了各类插件,覆盖了 API 网关的各种领域,如认证鉴权、安全、可观测性、流量管理、多协议接入等。当前 APISIX 内置的插件使用原生 Lua 实现
插件加载流程
filtered plugins判断是否满足过滤条件,此配置由一个或多个 {var, operator, val} 元素组成列表,例如{"arg_version", "==", "v2"}
插件内部结构
APISIX(Apache APISIX)的执行阶段是指API Gateway在处理请求时,将请求和响应分为不同的处理阶段,并在每个阶段触发自定义插件的执行。这允许开发者在请求流经API Gateway时执行各种自定义操作。以下是APISIX的主要执行阶段:
- Init(初始化)阶段:在初始化阶段,APISIX加载配置并准备处理请求。这个阶段不包括插件执行,但允许你设置全局的配置,例如路由配置和全局插件。
- Access(访问)阶段:在访问阶段,API Gateway处理请求之前触发自定义插件的
access
回调。这是处理请求之前执行逻辑的理想时机,例如身份验证、请求转换或鉴权。 - Rewrite(重写)阶段:在重写阶段,APISIX执行请求重写操作。这允许你修改请求的URL、标头和查询参数。自定义插件的
rewrite
回调在这个阶段执行。 - Balancer(负载均衡)阶段:在负载均衡阶段,APISIX执行负载均衡操作,决定将请求路由到哪个上游服务节点。这个阶段通常由内置的负载均衡插件处理,例如
round-robin
或chash
。 - Proxy(代理)阶段:在代理阶段,APISIX代理请求到上游服务。这是请求实际被转发到后端服务的阶段。
- Log(日志)阶段:在日志阶段,APISIX记录请求和响应的日志。这包括请求、响应头、请求体等信息。你可以使用日志插件来扩展或自定义日志记录。
- Header Filter(头部过滤)阶段:在头部过滤阶段,API Gateway执行任何与响应头相关的过滤操作。这是响应头部被处理的地方,通常由自定义插件的
header_filter
回调执行。 - Body Filter(正文过滤)阶段:在正文过滤阶段,APISIX执行与响应正文相关的过滤操作。这允许你修改响应体,通常由自定义插件的
body_filter
回调执行。 - Log(日志)阶段(再次):在完成所有其他阶段后,APISIX执行最终的日志记录操作。这包括响应的日志信息。
- Admin(管理)阶段:在管理阶段,APISIX允许执行管理操作,例如配置更改或查看API Gateway的状态。这通常是通过管理员API执行的操作,而不是HTTP请求。
三、API
保护API的方法:
- 限制请求速率;
- 限制单位时间内的请求数;
- 延迟请求;
- 拒绝客户端请求;
- 限制响应数据的速率。
control API
用于
- 暴露 APISIX 内部状态信息
- 控制单个 APISIX 的数据平面的行为
默认情况下,control API 是启用的,监听 127.0.0.1:9090
admin API
Admin API 是一组用于配置 Apache APISIX 路由、上游、服务、SSL 证书等功能的 RESTful API。
你可以通过 Admin API 来获取、创建、更新以及删除资源。同时得益于 APISIX 的热加载能力,资源配置完成后 APISIX 将会自动更新配置,无需重启服务
当 APISIX 启动时,Admin API 默认情况下将会监听 9180 端口,并且会占用前缀为 /apisix/admin 的 API
四、插件
APISIX 的插件是热加载的,不管你是新增、删除还是修改插件,都不需要重启服务
General
插件名 |
描述 |
备注 |
batch-requests |
可以一次接受多个请求并以 HTTP pipeline 的方式在网关发起多个 HTTP 请求,合并结果后再返回客户端 |
/apisix/batch-requests |
redirect |
可用于配置 URI 重定向 |
http_to_https、uri 和 regex_uri 只能配置其中一个属性。 http_to_https、和 append_query_string 只能配置其中一个属性。 |
echo |
可以帮助用户尽可能地全面了解如何开发 APISIX 插件 |
echo 插件只能用作示例,并不能处理一些特别的场景,不能用在生产环境 |
gzip |
能动态设置 NGINX 的压缩行为 |
该插件要求 Apache APISIX 运行在 APISIX-Base 上 |
real-ip |
用于动态改变传递到 Apache APISIX 的客户端的 IP 地址和端口 |
该插件要求 Apache APISIX 运行在 APISIX-Base 上 |
server-info |
可以定期将服务基本信息上报至 etcd |
该插件在 Control API 下暴露了一个 API 接口 /v1/server_info |
ext-plugin-pre-req |
用于在执行内置 Lua 插件之前和在 Plugin Runner 内运行特定的 External Plugin |
|
ext-plugin-post-req |
在内置 Lua 插件执行之后且在请求到达上游之前工作 |
|
ext-plugin-post-resp |
将在请求获取到上游的响应之后执行 |
|
inspect |
在任何Lua文件中设置任意断点以检查上下文信息 |
此插件支持在interpretd函数和jit编译函数中设置断点。断点可以位于函数中任何位置 |
workflow |
引入 lua-resty-expr 来提供复杂的流量控制功能 |
Transformation
插件名 |
描述 |
备注 |
response-rewrite |
支持修改上游服务或 APISIX 返回的 Body 和 Header 信息 |
适用场景:通过设置 Access-Control-Allow-* 字段实现 CORS(跨域资源共享)的功能。通过设置标头中的 status_code 和 Location 字段实现重定向 优先级:add > remove > set |
proxy-rewrite |
处理上游代理信息重写的插件,支持对 scheme、uri、host 等信息进行重写 |
|
grpc-transcode |
可以在 HTTP 和 gRPC 请求之间进行转换 |
|
grpc-web |
是一个代理插件,可以处理从 JavaScript 客户端到 gRPC Service 的 gRPC Web 请求 |
|
fault-injection |
是故障注入插件,该插件可以和其他插件一起使用,并在其他插件执行前被执行 |
|
mocking |
用于模拟 API。当执行该插件时,它将随机返回指定格式的模拟数据,并且请求不会转发到上游 |
|
degraphql |
用于支持解码RESTful API 到GraphQL |
|
body-transformer |
用于将请求和/或响应主体从一种格式转换为另一种格式,例如JSON到XML。 |
Authentication
当认证插件与 Consumer 一起使用时,需要提供用户名、密码等信息;当认证插件与 Route 或 Service 绑定时,则不需要任何参数,因为此时 APISIX 是根据用户请求数据来判断用户对应的是哪个 Consumer
插件名 |
描述 |
备注 |
key-auth |
用于向 Route 或 Service 添加身份验证密钥(API key) 通过 Consumer 将其密钥添加到查询字符串参数或标头中以验证其请求 |
不同的 Consumer 应有不同的 key 验证:-H 'apikey: key_val' |
jwt-auth |
用于将 JWT 身份验证添加到 Service 或 Route 中 通过 Consumer 将其密匙添加到查询字符串参数、请求头或 cookie 中用来验证其请求 |
Consumer 的 access_key 必须是唯一的 jwt-auth 默认使用 HS256 算法 该插件会增加 /apisix/plugin/jwt/sign 接口,获取token 验证:-H 'Authorization: token_val', 还可放在参数或cookie中 |
basic-auth |
可以将 Basic_access_authentication 添加到 Route 或 Service 中 API 的消费者可以将密钥添加到请求头中以验证其请求 |
必填username和password 验证:-u用户名:密码 |
authz-keycloak |
可用于通过 Keycloak Identity Server 添加身份验证 |
|
authz-casdoor |
可添加 Casdoor 集中认证方式 |
|
wolf-rbac |
为 role-based access control 系统提供了添加 wolf 到 Route 或 Service 的功能 |
|
openid-connect |
OpenID Connect(OIDC)是基于 OAuth 2.0 的身份认证协议,APISIX 可以与支持该协议的身份认证服务对接,如 Okta、Keycloak、Ory Hydra、Authing 等,实现对客户端请求的身份认证 |
提供两种使用场景:应用之间认证授权,浏览器中认证授权 |
cas-auth |
可用于从SP(服务提供商)的角度访问cas(中央身份验证服务2.0)IdP(身份提供商)以进行身份验证 |
|
hmac-auth |
可以将 HMAC authentication 添加到 Route 或者 Service API 的使用者必须将密匙添加到请求头中以验证其请求 |
配对使用access_key和secret_key 会涉及签名 |
authz-casbin |
是一个基于 Lua Casbin 的访问控制插件,该插件支持各种 access control models 的强大授权场景 |
|
ldap-auth |
可用于给路由或服务添加 LDAP 身份认证,该插件使用 lua-resty-ldap 连接 LDAP 服务器 |
|
opa |
可用于与 Open Policy Agent 进行集成,实现后端服务的认证授权与访问服务等功能解耦,减少系统复杂性 |
|
forward-auth |
使用的是经典外部认证。当身份认证失败时,可以实现自定义错误或者重定向到认证页面的场景 |
Security
插件名 |
描述 |
备注 |
cors |
为服务端启用 CORS(Cross-Origin Resource Sharing,跨域资源共享)的返回头 |
|
uri-blocker |
通过指定一系列 block_rules 来拦截用户请求 |
|
ip-restriction |
可以通过将 IP 地址列入白名单或黑名单来限制对服务或路由的访问 支持对单个IP 地址、多个 IP 地址和类似 10.10.10.0/24 的 CIDR范围的限制 |
whitelist 和 blacklist 属性无法同时在同一个服务或路由上使用,只能使用其中之一 |
ua-restriction |
可以通过将指定 User-Agent 列入白名单或黑名单的方式来限制对服务或路由的访问 |
一种常见的场景是用来设置爬虫规则 |
referer-restriction |
允许用户将 Referer 请求头中的域名列入白名单或黑名单来限制该域名对服务或路由的访问 |
|
consumer-restriction |
允许用户根据 Route、Service 或 Consumer 来设置相应的访问限制 |
|
csrf |
基于 Double Submit Cookie 的方式,保护用户的 API 免于 CSRF 攻击 |
GET、HEAD 和 OPTIONS 会被定义为 safe-methods,其他的请求方法则定义为 unsafe-methods |
public-api |
可用于通过创建路由的方式暴露用户自定义的 API |
|
gm |
能启用国密相关的功能 |
Traffic
插件名 |
描述 |
备注 |
limit-req |
使用漏桶算法限制单个客户端对服务的请求速率 |
在 Consumer 上启用 limit-req 插件需要与认证插件一起配合使用。 |
limit-conn |
用于限制客户端对单个服务的并发请求数。当客户端对路由的并发请求数达到限制时,可以返回自定义的状态码和响应信息。 |
|
limit-count |
使用固定时间窗口算法,主要用于限制单个客户端在指定的时间范围内对服务的总请求数,并且会在 HTTP 响应头中返回剩余可以请求的个数 |
|
proxy-cache |
提供缓存后端响应数据的能力,它可以和其他插件一起使用。该插件支持基于磁盘和内存的缓存 |
|
request-validation |
用于提前验证向上游服务转发的请求 使用JSON Schema机制进行数据验证,可以验证请求的body及header数据 |
|
proxy-mirror |
提供了镜像客户端请求的能力。流量镜像是将线上真实流量拷贝到镜像服务中,以便在不影响线上服务的情况下,对线上流量或请求内容进行具体的分析 |
镜像请求返回的响应会被忽略 |
api-breaker |
该插件实现了 API 熔断功能,从而帮助我们保护上游业务服务 |
|
traffic-split |
该插件使用户可以逐步引导各个上游之间的流量百分比 可以使用该插件实现蓝绿发布,灰度发布 |
|
request-id |
通过 APISIX 为每一个请求代理添加 unique ID 用于追踪 API 请求 |
使用 snowflake 算法生成 unique ID |
proxy-control |
动态地控制 NGINX 代理的相关行为 |
|
client-control |
通过设置客户端请求体大小的上限来动态地控制 NGINX 处理客户端的请求 |