Apache APISIX 是一个云原生高性能 API 网关,同时也是 Apache 基金会下的顶级开源项目,自 2019 年开源以来社区高速发展,目前社区活跃贡献者已达到 300+,Github star 数 7.6K,可以说是目前最活跃的网关项目。

本篇文章将从 APISIX 的结构开始,带你在本地运行一个 APISIX,并使用官方的 Dashboard 创建一条测试路由,最后借助插件为该路由实现基本鉴权功能。

项目结构

APISIX 的结构如下图所示:

APISIX

从图中可以看出来,APISIX 的结构分为 数据面(Data Plane) 和 控制面(Control Plane)。数据面负责处理具体的 API 请求,控制面则主要通过读写配置信息以达到对 APISIX 的控制。

数据面和控制面之间通过 etcd 搭建起了桥梁,etcd 是一个用于分布式系统的键值对存储库。控制面只负责往 etcd 中读写配置信息,一旦配置信息数据更改了,etcd 就会即时通知数据面,这样数据面就可以使用更新后的规则对路由进行处理了。而且这期间 APISIX 是不需要重新启动的。

使用 APISIX 时还可以通过结合 Apache SkyWalkingPrometheusGrafana 等实现可观测性,APISIX 会将请求统计数据上报,这样就可以方便的看到统计数据。

安装体验

下面我们在自己的电脑上安装体验一下 APISIX。

首先打开 APISIX 的官方文档,在这个快速入门指南中官方给出了步骤,我们只需按照步骤执行即可。

处理依赖

APISIX 项目代码托管在 Github 上,首先我们需要将代码 clone 到本地。然后我们需要在机器上准备一下依赖,根据安装依赖的文档,我们只需要在项目目录下执行一下脚本就可以了。

bash utils/install-dependencies.sh

这个脚本会判断出执行环境,然后使用包管理工具自动安装依赖,在 macOS 下会调用 brew 安装

brew install openresty/brew/openresty luarocks lua@5.1 etcd curl git pcre openldap

然后启动 etcd 服务

brew services start etcd

安装完成之后可以检验一下 etcd 是否已经启动了

brew services

初始化 APISIX

首先需要安装运行时依赖的一些库,在项目目录下执行

make deps

然后需要初始化配置文件和 etcd

make init

完成后就可以启动了,运行

make run

之后可以看到

/Users/apisix/bin/apisix start
/usr/local/Cellar/openresty/1.19.9.1_1/luajit/bin/luajit ./apisix/cli/apisix.lua start
[ info ] run -> [ Done ]

这样 APISIX 就成功运行起来了。可以使用 make help 查看更多命令。

基本使用

APISIX 默认运行在 9080 端口,我们可以访问一下

curl 127.0.0.1:9080

默认会看到返回

{"error_msg":"404 Route Not Found"}

这是我们没有在 APISIX 中配置任何的路由规则,所以请求会匹配不到路径。

在 APISIX 中,使用 Route 表示一个路由匹配规则。Route 上可以绑定 PluginUpstream

Plugin 表示一个插件,它可以在配置路由时选择开启,不同的 `Plugin 有不同的功能,APISIX 有一个插件市场,里面有目前支持的所有的插件。

Upstream 表示上游服务,一般表示我们的后端服务。我们可以将其绑定到某个 Route 上,这样在访问这个 Route 时 APISIX 会将这个请求转发到该后端服务中。

APISIX 支持一个 Admin API 用来读写配置,这个功能是默认开启的,地址在 9080 端口,这个端口可以在配置文件 conf/conf.yaml 中修改 port_admin。除此之外该功能使用路径 /apisix/admin,在调用 Admin API 时需要传递一个 X-API-Key 请求头来鉴权,否则会得到 401 返回,这个KEY 的值在配置文件 conf/conf.yaml 中。详细资源 API 定义参考文档

APISIX 官方还支持一个 apisix-dashboard 项目,这是一个可视化控制面板,可以更直观的对 APISIX 做配置。

安装 Dashboard

我们使用 Docker 将 dashboard 运行起来。

首先获取到最新的镜像

docker pull apache/apisix-dashboard

运行镜像的时候有两个地方需要注意:

因为我们需要在宿主机上访问 dashboard 的服务,所以我们需要修改配置文件将地址暴露出来,然后我们的 dashboard 需要访问宿主机的 etcd 服务,这个也需要修改配置文件。所以我们需要在启动的时候将修改后的配置文件挂载进去。

默认的配置文件在 https://github.com/apache/apisix-dashboard/blob/master/api/conf/conf.yaml

将这个文件下载一份到本地,然后修改

conf:
  listen:
    host: 0.0.0.0
etcd:
    endpoints:
      - host.docker.internal:2379

修改完成后用这个配置文件替换掉 /usr/local/apisix-dashboard/conf/conf.yaml 即可

docker run -d -p 9000:9000 -v /path/to/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml --name apisix-dashboard apisix-dashboard:$tag

启动完成之后访问 http://127.0.0.1:9000 应该可以访问到控制台。

Dashboard

配置上游服务

我们需要在本地模拟一个上游服务,包含一个 /hello API,使用 GET 访问会返回一个 "Hello World"。

这个实现起来并不难,方式非常多,自己动手即可。

在 Dashboard 上选择上游 → 创建,名称自己命名一下即可,关键的是目标节点:

主机名需要填写上面创建的那个上游服务的地址,本地启动的服务多半可能 127.0.0.1,然后端口填写自己服务启动的端口即可。其他的用默认配置创建。

配置路由

选择 路由 → 创建,命名一个名称,然后路径需要填写我们上面创建的服务的 API 路径,其他保持默认。在下一步中上游服务选择我们上一步创建的上游服务,其他默认,创建即可。

到这里我们就完成了 API 的配置。

我们访问验证一下:

curl 127.0.0.1:9080/hello 

配置正确的话可以看到返回 "Hello World"。

高级配置

APISIX 的插件机制给路由的配置提供的很大的灵活性和功能的扩展,一些高级的功能比如:限流限速、鉴权等业务只需要开启一个插件即可。下面我们通过插件为路由添加上基本的身份验证功能。

basic-auth 是 APISIX 的一个认证插件,可以为我们的路由添加基础的用户名和密码验证。该插件作用于 Consumer ,我们需要先在 Dashboard 中创建一个 consumer,在配置中启用 basic-auth 插件,同时在插件配置信息中填写用户名和密码完成配置。

接着就可以在 Route 的配置中开启 basic-auth 插件,完成对该路由的认证。

之后直接访问该路由会返回 401 缺少权限:

{"message":"Missing authorization in request"}

只有在发请求时提供 basic auth 信息,并附带正确的用户名和密码才能返回正确结果。

如果使用的是 API 测试工具,可以在 Auth 选项中选择 basic auth,并填写正确的用户名和密码;如果使用 curl,则需要带上基本认证:

curl -i -u username:password http://127.0.0.1:9080/hello

到这里我们就完成了基本的上手使用。仔细翻看 APISIX 的插件市场就会发现各种各样的插件几乎涵盖了业务的方方面面,包括权限控制、流量控制、可观测性、serverless 等等。需要什么样的业务就配置对应的插件即可。

除此之外 APISIX 还提供了自定义插件的 API ,这样我们就可以根据具体的业务定制自己的插件了。如果不想使用 Lua 编写自定义插件, APISIX 还给出了其他语言编写插件的方案:RPC 调用和 wasm,他们都支持多语言编写插件。

RPC 调用的方式需要在 APISIX 上挂载一个目标语言的运行时,APISIX 会接管这个运行时进程的状态,然后插件在这一运行时内运行,当 APISIX 收到请求后,会将请求内容序列化通过 RPC 的方式送至插件中,插件对请求做出处理后再将结果返回给 APISIX。这种方式兼具性能与稳定性,是当下比较推崇的一种多语言插件方案。

另一种 wasm 的方式则比较激进,从长远来说也更现代化。wasm 全称为 WebAssembly,是一种编译型语言的编译目标。也就是说编译型语言除了可以编译为二进制文件外,也可以选择编译为 wasm。一个 wasm 模块通常是一个 .wasm 文件。当下主流的编译语言如 C++GoRust 等都支持通过对应的工具编译为 wasm 。wasm 的优点是执行效率高、安全性高,而且具有可移植性。缺点是目前还比较年轻,生态和适配还不够。比如 wasm 目前是不支持复杂的数据类型的,这也导致了跟其他语言结合时接口数据转换会牺牲掉很大一部分性能。 使用这种方式需要使用上述语言根据按照对应的 SDK 编写插件,然后将插件挂载进 APISIX 就行。这种方式当前不太建议放入生产环境,在开发环境体验下还是很有意思的。而且从性能上来说是优于 RPC 的方式的。期待随着 wasm 生态的进步,这种方式也能逐步完善。