APISIX网关系列之介绍与安装(一)
1.概述
从这篇文章开始介绍下微服务架构中网关组件,选择APISIX网关是因为我们后面应用的对象是python项目,不像JAVA项目出生就有Spring家庭提供了GateWay网关。
我们介绍APISIX网关不会只介绍下他是什么,怎么用就完结了,恰恰相反介绍这些只是一个开始,我们学习某个知识的根本不在知识本身,而是它能解决实际问题这才是学习的根本。
因此我在这篇博客的标题上用了一个系列
名词,这篇文章介绍APISIX是什么,后面还有几篇文章要介绍怎么把它与项目结合,解决实际的问题。
2.APISIX网关介绍
在Apache官网中已经详细的介绍了APISIX,为什么还要在写一篇文章来介绍它那?官网介绍的目的是让大家全面了解它,因此篇幅会很长增加了学习的成本,而且官方文字比较呆板不好理解。
Apache官方介绍文档:https://apisix.apache.org/zh/docs/apisix/getting-started/
我们日常使用中又不会将它每个功能都使用到,因此有了这篇文章将APISIX的精华整理精简到一篇文章中,缩短时间提升学习效率。
2.1.什么是 ApacheAPISIX
1.Apache APISIX是什么
Apache APISIX 是 Apache 软件基金会下的云原生 API 网关,它兼具动态、实时、高性能等特点,提供了负载均衡、动态上游、灰度发布(金丝雀发布)、服务熔断、身份认证、可观测性等丰富的流量管理功能。
我们可以使用 Apache APISIX 来处理传统的南北向流量,也可以处理服务间的东西向流量。同时,它也支持作为 K8s Ingress Controller 来使用。
2.主要特性
多平台支持
:APISIX 提供了多平台解决方案,它不但支持裸机运行,也支持在 Kubernetes 中使用,还支持与 AWS Lambda、Azure Function、Lua 函数和 Apache OpenWhisk 等云服务集成。全动态能力
:APISIX 支持热加载,这意味着你不需要重启服务就可以更新 APISIX 的配置。请访问为什么 Apache APISIX 选择 Nginx + Lua 这个技术栈?以了解实现原理。精细化路由
:APISIX 支持使用 NGINX 内置变量做为路由的匹配条件,你可以自定义匹配函数来过滤请求,匹配路由。运维友好
:APISIX 支持与以下工具和平台集成:HashiCorp Vault、Zipkin、Apache SkyWalking、Consul、Nacos、Eureka。通过 APISIX Dashboard,运维人员可以通过友好且直观的 UI 配置 APISIX。多语言插件支持
:APISIX 支持多种开发语言进行插件开发,开发人员可以选择擅长语言的 SDK 开发自定义插件。
2.2.APISIX架构和主要组件
1.APISIX上层架构
APASIX架构设计如上图
APISIX架构采用了数据和控制分层设计理念,并将它分为两个面数据面(Data Plane)简称DP和控制面(Control Plane)简称CP
数据面DP
数据面是真正去处理来自客户端请求的一个组件,接收客户端发送来的请求,并对请求做一些处理例如路由转发、身份验证、日志分析、等业务逻辑处理。数据面只处理业务逻辑流不存储任何数据,所以他是无状态的。
总结:DP只处理请求业务逻辑
控制面板CP
APISIX在控制面包含两个职责API和存储数据,它有一套完整的API接口用来配置APISIX,同时使用etcd数据库来存储所有的数据。
使用etcd数据库存储数据对网关来说就向赛车的引擎,转速越高速度越快。它的优点如下:
- 能够融合云原生态技术体系
- 更符合网关API存放数据类型
- 效率更高能够毫秒级发出变化通知
对于数据面而言只需要监听etcd的变化即可,检测到配置变更就可以在毫秒级别内达到时时生效的效果。
APISIX业务流
1.客户端发送请求到达APISIX网关
2.APISIX网关DP面接收到请求,路由和插件开始处理逻辑,逻辑处理完成后向CP面的的etcd数据库获取目标服务节点地址,将请求转发到目标服务器的服务处理。
3.CP面的Manager API用来配置网关路由和服务之间映射关系,为路由配置插件完成一些高级功能。
4.
2.APISIX主要组件
路由route
:通过路由定义规则来匹配客户端请求,根据匹配结果加载并执行相应的插件,最后把请求转发给到指定的上游应用。
服务Service
:是某类 API 的抽象(也可以理解为一组 Route 的抽象)。它通常与上游服务抽象是一一对应的,但与路由之间,通常是 1:N 即一对多的关系。
Service作为router路由和Upstream中间层,它的作用就是减少路由重复配置工作量,它是可有可无的。
这么说有些官方不好理解,下面通过一个例子了解Service。
需要service场景:
假如有三个路由ABC他们都要配置限流插件,而且他们访问同一个API微服务都部署在同一个Upstream上游节点主机。
1.首先创建一个Upstream,配置后端的API微服务。
2.创建一个Service,添加并配置限流插件策略和创建好的Upstream的ID
3.ABC三个路由配置时只要指定上面的Service即可,如果没有配置Service那么每个路由直接配置Upstream就要配置三遍,同时插件也要配置三次。有了Service作为路由和Upstream中间层,路由只需要配置一次就可以了。这个就是典型的路由与Service是 N:1关系,Service与Upstream是 1:1关系。
不需要service场景:
三个路由ABC访问不同的API微服务,且他们部署在不同的Upstream上,就不能使用Service,路由直接配置Upstream,路由与上游绑定映射关系实现路由访问微服务API。
上游Upstream
:上游的作用是按照配置规则对服务节点进行负载均衡,他的绑定对象可以是路由或者Service。
例如将多个提供相同服务的后端docker微服务地址配置到同一个Upstream,Upstream就能根据负载均衡策略将请求转发到不同地址的服务处理。
Admin API
:用户可以通过 Admin API 接口配置 APISIX
3.APISIX底层架构
APISIX底层架构如上图
观察上图能够发现在OpenResty上面有个分界线,它的架构划成了两个部分,分界线以下是 APISIX依赖的 NGINX + ngx_lua 为支撑的路由组件,分界线以上才是APISIX通过lua开发语言封装扩展的功能。
2.3.APISIX优势
1.无数据库依赖
在 APISIX 项目出现之前,也有非常多的商业 API 网关或开源 API 网关产品,但这些产品大多数都把 API 数据、路由、证书和配置等信息存放在一个关系型数据库中。
将这些数据存储在关系型数据库的优势非常明显,用户可以更加方便地使用 SQL 语句进行灵活查询,也方便用户进行备份及后续维护。
但是网关作为一个基础中间件,它处理了所有来自客户端的流量,这种情况下对于可用性的要求便会非常高。如果你的 API 网关依赖了一个关系型数据库,也就意味着关系型数据库一旦出现了故障(比如宕机、丢失数据),API 网关也会因此受到影响,整个业务系统的可用性也会大打折扣。
APISIX 在设计之初,就从底层架构上避免了宕机、丢失数据等情况的发生。因为在控制面上,APISIX 使用了 etcd 存储配置信息,而不是使用关系型数据库,这样做的好处主要有以下几点:
- 与产品架构的云原生技术体系更统一;
- 更贴合 API 网关存放的数据类型;
- 能更好地体现高可用特性;
- 拥有低于毫秒级别的变化通知。
使用 etcd 存储配置信息后,对于数据面而言只需监听 etcd 的变化即可。如果采用轮询数据库的方式,可能需要 5-10 秒才能获取到最新的配置信息;如果监听 etcd 的配置信息变更,APISIX 就可以将获取最新配置的时间控制在毫秒级别之内,达到实时生效。 因此使用 etcd 作为存储,不仅让 APISIX 在底层上更加贴合云原生,也让它在系统高可用的体现上带来了更多优势。
2.高性能路由匹配算法
API 网关需要从每个请求的 Host、URI、HTTP 方法等特征中匹配到目标规则,以决定如何对该请求进行处理,因此一个优秀的匹配算法是必不可少的。Hash 算法性能不错,但无法实现模糊匹配;正则可以模糊匹配,但性能不好,因此 Apache APISIX 选择使用树这样一种高效且支持模糊匹配的搜索数据结构。
Apache APISIX 使用的是 RadixTree,它提供了 KV 存储查找的数据结构并对只有一个子节点的中间节点进行了压缩,因此它又被称为压缩前缀树。
此外,在已知 API 网关产品中 Apache APISIX 首次将 RadixTree 应用到了路由匹配中,支持一个前缀下有多个不同路由的场景,具体实现见 lua-resty-radixtree。
当对某个请求进行匹配时,RadixTree 将采用层层递进的方式进行匹配,其复杂度为 O(K)(K 是路由中 URI 的长度,与 API 数量多少无关),该算法非常适合公有云、CDN以及路由数量比较多的场景,可以很好地满足路由数量快速增长的需求。
3.高性能 IP 匹配算法
IP 地址有 2 种记法:标准 IP 表示方法与 CIDR 表示方法,以 32 位的 IPv4 为例:
标准 IP 记法:192.168.1.1
CIDR 记法:192.168.1.1/8
Apache APISIX 的 IP 匹配算法与路由匹配算法所使用的原理以及原始数据是不一样的。以 192.168.1.1 这个 IP 为例,由于每个 IP 段的范围是 0 到 255,因此在对 IP 进行匹配时我们可以认为 IP 地址是由 4 个16 位整数型的数构成的,IP 长度是固定的。那么我们可以采用更高效的算法完成匹配。
假设现在有一个包含 500 条 IPv4 记录的 IP 库,APISIX 会将 500 条 IPv4 的记录缓存在 Hash 表中,当进行 IP 匹配时使用 Hash 的方式进行查找,时间复杂度为 O(1)。而其他 API 网关则是通过遍历的方式完成 IP 匹配,发送到网关每个请求将逐个遍历最多 500 次是否相等后才能知道计算结果。所以 APISIX 的 高精度 IP 匹配算法大大提高了需要进行海量 IP 黑白名单匹配场景(如 WAF)的效率。
4.精细化路由
API 网关通过请求中的流量特征完成预设规则的匹配,常见特征包含了请求中的 Host、URI 路径、URI 查询参数、URI 路径参数、HTTP 请求方法、请求头等,这些特征是大部分 API 网关产品所支持的。相较于其它产品,Apache APISIX 支持了更多特征以解决复杂多变的使用场景。
首先,Apache APISIX 支持 NGINX 内置变量,意味着我们可以将诸如 uri、server_name 、server_addr、request_uri、remote_port、remote_addr、query_string、host、hostname、arg_name等数十种 Nginx 内置变量作为匹配参数,以支持更复杂多变的匹配场景。NGINX 内置变量列表请参考 NGINX 变量。
其次,Apache APISIX 支持将条件表达式作为匹配规则,其结构是 [var, operator, val], …]],其中:
- var 值可使用 Nginx 内置变量;
- operator 支持相等、不等、大于、小于、正则、包含等操作符。
假设表达式为 [“arg_name”, “==”, “json”],它意味着当前请求的 URI 查询参数中,是否有一个为 name 的参数值等于 json。Apache APISIX 是通过自研的库 lua-resty-expr 实现该能力的,具体请参考 lua-resty-expr。该特性将选择权交给了用户,可扩展性强。
Apache APISIX 支持设置路由 ttl 存活时间:
$ curl http://127.0.0.1:9080/apisix/admin/routes/2?ttl=60 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d ' { "uri": "/aa/index.html", "upstream": { "type": "roundrobin", "nodes": { "39.97.63.215:80": 1 } } }'
以上配置表示,在 60s 后 APISIX 会自动删除该路由配置,非常适合一些临时验证的场景,比如金丝雀发布、监控输出等。对于线上的流量分流非常方便,是其它网关产品所不具备的能力
Apache APISIX 支持自定义过滤函数,你可以通过在 filter_func 参数中编写自定义 Lua 函数,例如:
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d ' { "uri": "/index.html", "hosts": ["http://foo.com", "*.http://bar.com"], "filter_func": "function(vars) return vars['host'] == 'api7.ai' end", "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }'
其中 filter_func 入参是 vars,可从 vars 获取 Nginx 变量,然后实现自定义过滤逻辑。
5.支持多语言插件
虽然 API 网关、数据库或其他中间件都属于基础组件,但是更多时候用户是根据使用场景对 API 网关进行一些定制化地开发和系统集成。
APISIX 目前已经支持了 80 多种插件,但仍然难以涵盖用户的所有使用场景。在实际使用场景中,很多企业都会针对具体业务进行定制化的插件开发,通过网关去集成更多的协议或者系统,最终在网关层实现统一管理。
3.APISIX 网关V3.1版本安装
3.1.centos宿主机安装
1.安装ETCD
APISIX使用了ETCD数据库,因此我们先安装下这个数据库
# 1.设置版本变量
ETCD_VERSION='3.5.7'
# 下载
wget https://github.com/etcd-io/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
# 解压安装
tar -xvf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz && \
cd etcd-v${ETCD_VERSION}-linux-amd64 && \
sudo cp -a etcd etcdctl /usr/bin/
# 启动
nohup etcd >/tmp/etcd.log 2>&1 &
2.添加OpenResty和APISIX仓库
我们在APISIX底层架构中介绍了它是在OpenResty和nginx上构建的网关,因此要先安装底层组件,使用以下命令来安装 OpenResty 和 APISIX 仓库。
sudo yum install -y https://repos.apiseven.com/packages/centos/apache-apisix-repo-1.0-1.noarch.rpm
查看仓库中最新的 apisix 软件包的信息
sudo yum info -y apisix
# 当前最新版本3.1.0
可安装的软件包
名称 : apisix
版本 : 3.1.0
发布 : 0.el8
架构 : x86_64
大小 : 2.4 M
查看apisix所有可安装版本
yum list apisix --showduplicates | sort -r
# 输出可安装版本信息
apisix.x86_64 3.1.0-0.el8 release
apisix.x86_64 3.0.0-0.el8 release
apisix.x86_64 2.99.0-0.el8 release
apisix.x86_64 2.15.2-0.el8 release
apisix.x86_64 2.15.1-0.el8 release
3.安装APISIX
# 安装最新版本
sudo yum install apisix
# 安装指定版本
sudo yum install apisix-2.13.1
4.初始化
运行初始化命令将会初始化nginx和ectd
apisix init
5.启动和停止
如果你是通过 RPM 包安装 APISIX,配置文件已经自动安装,你可以直接使用以下命令
启动
systemctl start apisix
停止
# quit 命令正常停止apisix,确保在停止之前处理完所有收到的请求
systemctl apisix quit
# stop 命令强制关闭apisix
systemctl stop apisix
3.2.docker容器安装
前提是安装好docker和docker compose环境,在开始安装apisix.
- Docker安装:https://docs.docker.com/engine/install/
- Docker-Compose安装:https://docs.docker.com/compose/install/
注意:docker安装完一定要配置国内镜像源,否则在安装APISIX下载镜像会失败。
配置docker镜像源方法
# 编辑文件
vim /etc/docker/daemon.json
# 配置下面的镜像源
{
"registry-mirrors":["https://hub-mirror.c.163.com","https://registry.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn"]
}
# 重启docker服务
systemctl restart docker
1.下载APISIX源码
APISIX源码中包含了一个example文件夹,这个文件夹中有docker-compose.yml文件,通过这个文件启动APISIX服务,因此我们可以到官网下载指定版本的源码用docker方式安装。
下面提供两种方式下载APISIX源码
访问GitHub官网下载源码
访问官网选择一个release版本,例如选择3.1.0版本下载源码。
https://github.com/apache/apisix-docker
使用git命令下载源码
# 没有指定版本,默认下载最新的
git clone https://github.com/apache/apisix-docker.git
2.源码结构介绍
下载源码后除了example文件夹其他的都用不到,可以删除或保留。进入example目录,这里面的文件是和docker部署有关系的,下面来介绍下这些文件的作用。
目录 | 描述 | 作用 |
---|---|---|
apisix_conf | Apisix配置文件路径 | 1.配置apisix监听路径 2.配置后台默认账号及密码 3.配置ETCD相关配置 |
apisix_log | Apisix的日志目录 | |
dashboard_conf | Apisix可视化配置目录 | 1.设置登陆账号以及密码 2.设置产生日志路径 3.设置可视化访问的端口 4.设置默认开启的插件 |
etcd_conf | ETCD配置目录 | 1.配置成员信息 2.配置集群信息 3.Proxy 代理 4.相关安全设置 |
etcd_data | ETCD数据存放路径 | |
mkcert | 相关证书存放目录 | |
upstream | 关于nginx中Web服务的配置问存放目录 | |
docker-compose.yml | Docker-compose的相关配置 | 相关容器配置都放到此目录下,详细配置可以参考docker-compose官网配置 |
3.阅读dockercompose配置文件
下面是位于源码apisix-docker/example下的docker-compose.yml配置文件,阅读这个文件可以获取到如下信息:
1.分别下载apisix-dashboard、apisix、etcd、web1、web2、prometheus、grafana 组件镜像,并安装他们。
2.每个组件都配置了数据卷映射到本地的目录,因此不用担心docker服务重启后数据丢失问题。
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
version: "3"
services:
apisix-dashboard:
image: apache/apisix-dashboard:3.0.0-alpine
restart: always
volumes:
- ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
ports:
- "9000:9000"
networks:
apisix:
apisix:
image: apache/apisix:${APISIX_IMAGE_TAG:-3.1.0-debian}
restart: always
volumes:
- ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
depends_on:
- etcd
##network_mode: host
ports:
- "9180:9180/tcp"
- "9080:9080/tcp"
- "9091:9091/tcp"
- "9443:9443/tcp"
- "9092:9092/tcp"
networks:
apisix:
etcd:
image: bitnami/etcd:3.4.15
restart: always
volumes:
- etcd_data:/bitnami/etcd
environment:
ETCD_ENABLE_V2: "true"
ALLOW_NONE_AUTHENTICATION: "yes"
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ports:
- "2379:2379/tcp"
networks:
apisix:
web1:
image: nginx:1.19.0-alpine
restart: always
volumes:
- ./upstream/web1.conf:/etc/nginx/nginx.conf
ports:
- "9081:80/tcp"
environment:
- NGINX_PORT=80
networks:
apisix:
web2:
image: nginx:1.19.0-alpine
restart: always
volumes:
- ./upstream/web2.conf:/etc/nginx/nginx.conf
ports:
- "9082:80/tcp"
environment:
- NGINX_PORT=80
networks:
apisix:
prometheus:
image: prom/prometheus:v2.25.0
restart: always
volumes:
- ./prometheus_conf/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
networks:
apisix:
grafana:
image: grafana/grafana:7.3.7
restart: always
ports:
- "3000:3000"
volumes:
- "./grafana_conf/provisioning:/etc/grafana/provisioning"
- "./grafana_conf/dashboards:/var/lib/grafana/dashboards"
- "./grafana_conf/config/grafana.ini:/etc/grafana/grafana.ini"
networks:
apisix:
networks:
apisix:
driver: bridge
volumes:
etcd_data:
driver: local
3.dockercompose启动服务
上面阅读了example
文件夹中各个配置文件的作用,以及docker-compose.yml
文件。其中docker-compose.yml
文件中数据卷的映射都是将容器中的数据映射到宿主机example
文件夹所在的当前路径下
我们example
文件夹的位置就是在宿主机存放数据的位置,以后迁移数据只需要将这个文件夹拷贝即可。
所以我们在部署服务之前先将example
文件夹拷贝到我们指定的位置。例如下面的例子放到了/opt/apisix
路径
# 创建apisix安装路径
mkdir /opt/apisix-docker
# 复制example文件夹到apisix-docker目录
cp -r ./example /opt/apisix-docker/
# 进入example
cd /opt/apisix-docker/example
# 下载镜像启动服务
docker-compose -p docker-apisix up -d
4.APISIX配置
安装完APISIX后,下面介绍下他的常用配置。
4.1.APISIX配置文件
注意
1.APISIX 的默认配置可以在 ./conf/config-default.yaml 文件中看到,该文件与 APISIX 源码强绑定,请不要手动修改 ./conf/config-default.yaml 文件。
2.请不要手动修改 APISIX 安装目录下的 ./conf/nginx.conf 文件。当 APISIX 启动时,会根据 config.yaml 的配置自动生成新的 nginx.conf 并自动启动服务。
如果需要自定义任何配置,都应在 ./conf/config.yaml
文件中完成,并且修改配置后需要重启APISIX服务才会生效。
1.测试配置语法是否正确
当我们修改了配置文件后,可以运行下面的测试命令,APISIX根据config.yaml文件生成一个nginx.conf,检查nginx.conf语法是否正确。如果有错误则不能启动apisix,方便我们排查错误。
# 检测配置文件语法是否正确
apisix test
# 输出configuration test is successful表示语法正确,就可以启动apisix了。
/usr/local/openresty//luajit/bin/luajit /usr/local/apisix/apisix/cli/apisix.lua test
Warning! Current maximum number of open file descriptors [1024] is not greater than 1024, please increase user limits by execute 'ulimit -n <new user limits>' , otherwise the performance is low.
configuration test is successful
4.2.配置Admin API key
安装APISIX后在配置文件中会配置一个默认的Key用来访问Admin API,比如通过API方式配置路由,就需要这个key它就是请求Admin API接口的token。为了安全我们自己定义一个key,这样只有我们才能操作APISIX
# 进入配置文件
vim /usr/local/apisix/conf/config.yaml
在配置文件中找到admin_key,并修改它的key。可以使用字母+数字形式,例如: wangguan123
deployment:
role: traditional
role_traditional:
config_provider: etcd
admin:
admin_key:
- name: admin
key: edd1c9f034335f136f87ad84b625c8f1 # using fixed API token has security risk, please update it when you deploy to production environment
role: admin
验证新key是否能访问Admin API
使用新的 key 访问 Admin API,测试访问是否成功。
curl http://127.0.0.1:9180/apisix/admin/routes?api_key=newsupersecurekey -i
# 输出下面信息,key修改成功
HTTP/1.1 200 OK
Date: Thu, 23 Feb 2023 07:20:37 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/3.1.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: *
Access-Control-Max-Age: 3600
X-API-VERSION: v3
{"total":0,"list":[]}