Apache APISIX 是 Apache 軟件基金會下的云原生 API 網關,它具有動態、實時、高性能等特點,提供了負載均衡、動態上游、灰度發布(金絲雀發布)、服務熔斷、限速、防御惡意攻擊、身份認證、可觀測性等豐富的流量管理功能。我們可以使用 Apache APISIX 來處理傳統的南北向流量,也可以處理服務間的東西向流量。同時,它也支持作為 Kubernetes Ingress Controller 來使用。
APISIX 基于 Nginx 和 etcd,與傳統 API 網關相比,APISIX 具有動態路由和熱加載插件功能,避免了配置之后的 reload 操作,同時 APISIX 支持 HTTP(S)、HTTP2、Dubbo、QUIC、MQTT、TCP/UDP 等更多的協議。而且還內置了 Dashboard,提供強大而靈活的界面。同樣也提供了豐富的插件支持功能,而且還可以讓用戶自定義插件。
主要具有以下幾個特點:
- 多平臺支持 :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 開發自定義插件。
安裝 APISIX
為了簡單,我們這里可以直接在本地使用 docker 方式來啟動 APISIX,首先 Clone 官方提供的 apisix-docker
倉庫:
? git clone https://github.com/apache/apisix-docker.git
? cd apisix-docker
在項目根目錄下面的 example
目錄中有啟動 APISIX 的 docker-compose 配置文件,如下所示:
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:3.2.0-debian
restart: always
volumes:
- ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
depends_on:
- etcd
ports:
- "9180:9180/tcp"
- "9080:9080/tcp"
- "9091:9091/tcp"
- "9443:9443/tcp"
- "9092:9092/tcp"
networks:
apisix:
etcd:
image: rancher/coreos-etcd:v3.4.15-arm64
user: root
restart: always
volumes:
- ./etcd_data:/etcd-data
environment:
ETCD_UNSUPPORTED_ARCH: "arm64"
ETCD_ENABLE_V2: "true"
ALLOW_NONE_AUTHENTICATION: "yes"
ETCD_ADVERTISE_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_DATA_DIR: "/etcd-data"
ports:
- "2379:2379/tcp"
networks:
apisix:
web1:
image: nginx:1.19.10-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.10-alpine
restart: always
volumes:
- ./upstream/web2.conf:/etc/nginx/nginx.conf
ports:
- "9082:80/tcp"
environment:
- NGINX_PORT=80
networks:
apisix:
networks:
apisix:
driver: bridge
該 compose 里面主要包含了 APISIX 的三個容器:apisix、etcd 以及 apisix-dashboard。現在我們就可以使用 docker-compose 來進行一鍵啟動:
? docker-compose -f docker-compose.yml up -d
另外兩個 nginx 容器是用于測試的:
docker-compose
請確保其他系統進程沒有占用 9000、9080、9091、9092、9180、9443 和 2379 端口。如果啟動有錯誤,可以嘗試為 examples 目錄設置成 777 權限,保證 etcd 數據有權限寫入。
當 APISIX 啟動完成后我們就可以通過 curl 來訪問正在運行的 APISIX 實例。比如,可以發送一個簡單的 HTTP 請求來驗證 APISIX 運行狀態是否正常。
? curl "http://127.0.0.1:9080" --head
HTTP/1.1 404 Not Found
Date: Tue, 21 Mar 2023 07:38:45 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
Server: APISIX/3.2.0
現在,你已經成功安裝并運行了 APISIX !
功能測試
接下來我們來了解下 APISIX 的一些功能。在了解之前我們需要對 APISIX 的幾個主要概念和組件簡單了解下:
上游
Upstream 也稱為上游,上游是對虛擬主機的抽象,即應用層服務或節點的抽象。
上游的作用是按照配置規則對服務節點進行負載均衡,它的地址信息可以直接配置到路由或服務上。當多個路由或服務引用同一個上游時,可以通過創建上游對象,在路由或服務中使用上游的 ID 方式引用上游,減輕維護壓力。
路由
Route 也稱為路由,是 APISIX 中最基礎和最核心的資源對象。
APISIX 可以通過路由定義規則來匹配客戶端請求,根據匹配結果加載并執行相應的插件,最后把請求轉發給到指定的上游服務。路由中主要包含三部分內容:匹配規則、插件配置和上游信息。
服務
Service 也稱為服務,是某類 API 的抽象(也可以理解為一組 Route 的抽象)。它通常與上游服務抽象是一一對應的,Route 與 Service 之間,通常是 N:1
的關系。
消費者
Consumer 是某類服務的消費者,需要與用戶認證配合才可以使用。當不同的消費者請求同一個 API 時,APISIX 會根據當前請求的用戶信息,對應不同的 Plugin 或 Upstream 配置。如果 Route、Service、Consumer 和 Plugin Config 都綁定了相同的插件,只有消費者的插件配置會生效。插件配置的優先級由高到低的順序是:Consumer > Route > Plugin Config > Service。
對于 API 網關而言,一般情況可以通過請求域名、客戶端 IP 地址等字段識別到某類請求方,然后進行插件過濾并轉發請求到指定上游。但有時候該方式達不到用戶需求,因此 APISIX 支持了 Consumer 對象。
插件
Plugin 也稱之為插件,它是擴展 APISIX 應用層能力的關鍵機制,也是在使用 APISIX 時最常用的資源對象。插件主要是在 HTTP 請求或響應生命周期期間執行的、針對請求的個性化策略。插件可以與路由、服務或消費者綁定。
如果路由、服務、插件配置或消費者都綁定了相同的插件,則只有一份插件配置會生效,插件配置的優先級由高到低順序是:消費者 > 路由 > 插件配置 > 服務。同時在插件執行過程中也會涉及 6 個階段,分別是
rewrite
、access
、before_proxy
、header_filter
、body_filter
和log
。
Admin API
APISIX 提供了強大的 Admin API 和 Dashboard 供用戶使用,Admin API 是一組用于配置 Apache APISIX 路由、上游、服務、SSL 證書等功能的 RESTful API。
我們可以通過 Admin API 來獲取、創建、更新以及刪除資源。同時得益于 APISIX 的熱加載能力,資源配置完成后 APISIX 將會自動更新配置,無需重啟服務,具體的架構原理可以查看下面的架構圖:
APISIX 架構圖
主要分為兩個部分:
- APISIX 核心 :包括 Lua 插件、多語言插件運行時(Plugin Runner)、Wasm 插件運行時等;
- 功能豐富的各種內置插件 :包括可觀測性、安全、流量控制等。
APISIX 在其核心中,提供了路由匹配、負載均衡、服務發現、API 管理等重要功能,以及配置管理等基礎性模塊。除此之外,APISIX 插件運行時也包含其中,提供原生 Lua 插件的運行框架和多語言插件的運行框架,以及實驗性的 Wasm 插件運行時等。APISIX 多語言插件運行時提供多種開發語言的支持,比如 Golang、Java、Python、JS 等。
APISIX 目前也內置了各類插件,覆蓋了 API 網關的各種領域,如認證鑒權、安全、可觀測性、流量管理、多協議接入等。當前 APISIX 內置的插件使用原生 Lua 實現,關于各個插件的介紹與使用方式,后續我們再介紹。
創建路由
下面的示例中我們先使用 Admin API 來創建一個 Route 并與 Upstream 綁定,當一個請求到達 APISIX 時,APISIX 會將請求轉發到指定的上游服務中。
以下示例代碼中,我們將為路由配置匹配規則,以便 APISIX 可以將請求轉發到對應的上游服務:
? curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT -d '
{
"methods": ["GET"],
"host": "youdianzhishi.com",
"uri": "/anything/*",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}' -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'
# 正常會得到如下所示的結果
{"value":{"create_time":1679392758,"methods":["GET"],"host":"youdianzhishi.com","status":1,"priority":0,"update_time":1679392758,"upstream":{"pass_host":"pass","hash_on":"vars","type":"roundrobin","nodes":{"httpbin.org:80":1},"scheme":"http"},"id":"1","uri":"/anything/*"},"key":"/apisix/routes/1"}
其中的
X-API-KEY
的值在 APISIX 的配置文件中apisix_config.yaml
中有配置,位于deployment.admin.admin_key
下面。
該配置意味著,當請求滿足下述的所有規則時,請求將被轉發到上游服務(httpbin.org:80
):
- 請求的 HTTP 方法為 GET。
- 請求頭包含 host 字段,且它的值為
youdianzhishi.com
。 - 請求路徑匹配
/anything/*
,*
意味著任意的子路徑,例如/anything/foo?arg=10
。
當路由創建完成后,現在我們就可以通過以下命令訪問上游服務了:
? curl -i -X GET "http://127.0.0.1:9080/anything/foo?arg=10" -H "Host: youdianzhishi.com"
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 443
Connection: keep-alive
Date: Tue, 21 Mar 2023 08:25:49 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.2.0
{
"args": {
"arg": "10"
},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "youdianzhishi.com",
"User-Agent": "curl/7.85.0",
"X-Amzn-Trace-Id": "Root=1-64196a0d-1d2b654b29cbed3f7a9302c7",
"X-Forwarded-Host": "youdianzhishi.com"
},
"json": null,
"method": "GET",
"origin": "172.22.0.1, 221.11.206.200",
"url": "http://youdianzhishi.com/anything/foo?arg=10"
}
該請求將被 APISIX 轉發到 http://httpbin.org:80/anything/foo?arg=10
,我們可以和直接訪問上游數據進行對比。
httpbin數據
使用上游服務創建路由
我們還可以通過以下命令創建一個上游,并在路由中使用它,而不是直接將其配置在路由中:
? curl "http://127.0.0.1:9180/apisix/admin/upstreams/1" -X PUT -d '
{
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}' -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'
# 正常會得到如下所示的輸出
{"value":{"type":"roundrobin","create_time":1679392818,"pass_host":"pass","hash_on":"vars","update_time":1679392818,"nodes":{"httpbin.org:80":1},"id":"1","scheme":"http"},"key":"/apisix/upstreams/1"}
該上游配置與上一節配置在路由中的上游相同。同樣使用了 roundrobin
作為負載均衡機制,并設置了 httpbin.org:80
為上游服務。為了將該上游綁定到路由,此處需要把 upstream_id
設置為 "1"。
上游服務創建完成后,現在我們可以通過以下命令將其綁定到指定的 /get
路由:
? curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT -d '
{
"uri": "/get",
"host": "httpbin.org",
"upstream_id": "1"
}' -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'
# 正常會得到如下所示的輸出
{"value":{"upstream_id":"1","status":1,"create_time":1679392758,"host":"httpbin.org","update_time":1679392834,"priority":0,"id":"1","uri":"/get"},"key":"/apisix/routes/1"}
我們已經創建了路由與上游服務,現在可以通過以下命令訪問上游服務:
? curl -i -X GET "http://127.0.0.1:9080/get?foo1=bar1&foo2=bar2" -H "Host: httpbin.org"
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 370
Connection: keep-alive
Date: Tue, 21 Mar 2023 08:40:19 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.2.0
{
"args": {
"foo1": "bar1",
"foo2": "bar2"
},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.85.0",
"X-Amzn-Trace-Id": "Root=1-64196d73-165daa124c362e5d4c6bb79d",
"X-Forwarded-Host": "httpbin.org"
},
"origin": "172.22.0.1, 221.11.206.200",
"url": "http://httpbin.org/get?foo1=bar1&foo2=bar2"
}
同樣該請求也會被 APISIX 轉發到 http://httpbin.org:80/anything/foo?arg=10
。
使用 Dashboard
同樣我們還可以使用 APISIX Dashboard 創建和配置類似于上述步驟中所創建的路由。
如果你已經完成上述操作步驟,正常現在我們已經可以通過 localhost:9000
來訪問 APISIX Dashboard 了。
dashboard
默認的用戶名和密碼均為 admin
,在 examples
目錄中 dashboard_conf
下面的 conf.yaml
進行配置:
authentication:
secret: secret
expire_time: 3600
users:
- username: admin
password: admin
- username: user
password: user
上面我們的 docker-compose 中也已經啟動了 Grafana,所以登錄后我們也可以在首頁儀表盤上配置 Grafana,地址為 http://localhost:3000
。
Grafana
登錄后單擊側邊欄中的路由,可以查看已經配置的路由列表,可以看到在上述步驟中使用 Admin API 創建的路由。
路由列表
你也可以通過單擊創建按鈕并按照提示創建新路由:
如果想利用 APISIX 實現身份驗證、安全性、限流限速和可觀測性等功能,可通過添加插件實現。
限流限速和安全插件
在很多時候,我們的 API 并不是處于一個非常安全的狀態,它隨時會收到不正常的訪問,一旦訪問流量突增,可能就會導致你的 API 發生故障,這個時候我們就可以通過速率限制來保護 API 服務,限制非正常的訪問請求。對此,我們可以使用如下方式進行:
- 限制請求速率;
- 限制單位時間內的請求數;
- 延遲請求;
- 拒絕客戶端請求;
- 限制響應數據的速率。
APISIX 提供了多個內置的限流限速的插件,包括 limit-conn
、limit-count
和 limit-req
。
limit-conn
插件主要用于限制客戶端對服務的并發請求數。limit-req
插件使用漏桶算法限制對用戶服務的請求速率。limit-count
插件主要用于在指定的時間范圍內,限制每個客戶端總請求個數。
這里我們就以 limit-count
插件為例,來說明如何通過限流限速插件保護我們的 API 服務。如下所示。
使用下面的命令首先創建一條路由:
? curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -X PUT -d '
{
"uri": "/index.html",
"plugins": {
"limit-count": {
"count": 2,
"time_window": 60,
"rejected_code": 503,
"key_type": "var",
"key": "remote_addr"
}
},
"upstream_id": "1"
}' -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'
這里我們直接使用前面已經創建的上游(ID 為 1)來創建/更新一條路由,并且在 plugins
中啟用了 limit-count
插件,該插件僅允許客戶端在 60 秒內,訪問上游服務 2 次,超過兩次,就會返回 503 錯誤碼。
上面的指令執行成功后,接下來我們連續使用下面的命令訪問三次后,則會出現如下錯誤。
? curl http://127.0.0.1:9080/index.html
? curl http://127.0.0.1:9080/index.html
? curl http://127.0.0.1:9080/index.html
正常情況下就會出現如下所示的 503 錯誤,則表示 limit-count
插件已經配置成功。
<html>
<head>
<title>503 Service Temporarily Unavailable<span class="hljs-name"title>
<span class="hljs-name"head>
<body>
<center><h1>503 Service Temporarily Unavailable<span class="hljs-name"h1><span class="hljs-name"center>
<hr />
<center>openresty<span class="hljs-name"center>
<p>
<em>Powered by <a href="https://apisix.apache.org/">APISIX<span class="hljs-name"a>.<span class="hljs-name"em>
<span class="hljs-name"p>
<span class="hljs-name"body>
<span class="hljs-name"html>
緩存響應
當我們在構建一個 API 時,肯定希望他能夠盡量保持簡單和快速,一旦讀取相同數據的并發需求增加,可能會面臨一些問題,一般我們直接的辦法就是引入緩存,當然我們可以在不同層面去進行緩存的。
- 邊緣緩存或 CDN
- 數據庫緩存
- 服務器緩存(API 緩存)
- 瀏覽器緩存
反向代理緩存是另一種緩存機制,通常在 API 網關內實現。它可以減少對你的端點的調用次數,也可以通過緩存上游的響應來改善對你的 API 請求的延遲。如果 API Gateway 的緩存中有所請求資源的新鮮副本,它就會使用該副本直接滿足請求,而不是向端點發出請求。如果沒有找到緩存的數據,請求就會轉到預定的上游服務(后端服務)。
我們這里主要了解的是 API 網關層的緩存,也就是 APISIX 提供的 API 緩存,它也可以和其他插件一起使用,目前支持基于磁盤的緩存,也可以在插件配置中指定緩存過期時間或內存容量等。
比如我們現在有一個 /products
的 API 接口,通常每天只更新一次,而該端點每天都會收到重復的數十億次請求,以獲取產品列表數據,現在我們就可以使用 APISIX 提供的一個名為 proxy-cache
的插件來緩存該接口的響應。
這里我們還是使用前面 ID 為 1 的上游對象,使用 /anything/products
來模擬產品接口,直接執行下面的命令來更新路由的插件:
? curl "http://127.0.0.1:9180/apisix/admin/routes/1" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '{
"name": "Route for API Caching",
"methods": [
"GET"
],
"uri": "/anything/*",
"plugins": {
"proxy-cache": {
"cache_key": [
"$uri",
"-cache-id"
],
"cache_bypass": [
"$arg_bypass"
],
"cache_method": [
"GET"
],
"cache_http_status": [
200
],
"hide_cache_headers": true,
"no_cache": [
"$arg_test"
]
}
},
"upstream_id": "1"
}'
更新完成后現在我們來對該接口發起幾次請求:
? curl http://localhost:9080/anything/products -i
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 398
Connection: keep-alive
Date: Tue, 21 Mar 2023 10:48:42 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.2.0
Apisix-Cache-Status: MISS
? curl http://localhost:9080/anything/products -i
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 398
Connection: keep-alive
Date: Tue, 21 Mar 2023 10:48:42 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.2.0
Apisix-Cache-Status: HIT
正常每次都應該收到 HTTP 200 OK 響應,但是第一次響應中的 Apisix-Cache-Status
顯示為 MISS
,這意味著當請求第一次進入路由時,響應還沒有被緩存。而后面的幾次請求會得到一個緩存的響應,緩存指標變為了 HIT
,表示我們的響應緩存成功了。
-
API
+關注
關注
2文章
1563瀏覽量
63585 -
nginx
+關注
關注
0文章
164瀏覽量
12509 -
MQTT
+關注
關注
5文章
671瀏覽量
23506 -
zetcd
+關注
關注
0文章
3瀏覽量
2865
發布評論請先 登錄
性能提升1倍,成本直降50%!基于龍蜥指令加速的下一代云原生網關
只需 6 步,你就可以搭建一個云原生操作系統原型
容器技術和云原生誕生的歷史背景

云原生應用中的“云”指的是什么?
引領云原生2.0時代,賦能新云原生企業
如何更好地構建云原生應用生態,推動業界更好地落地云原生
解讀騰訊云原生 鵝廠云原生的“新路”與“歷承”
華為云云原生入門級開發者認證概述
華為云中什么是云原生服務中心

評論