Apache APISIX 是 Apache 軟件基金會下的云原生 API 網(wǎng)關(guān),它具有動態(tài)、實時、高性能等特點,提供了負載均衡、動態(tài)上游、灰度發(fā)布(金絲雀發(fā)布)、服務熔斷、限速、防御惡意攻擊、身份認證、可觀測性等豐富的流量管理功能。我們可以使用 Apache APISIX 來處理傳統(tǒng)的南北向流量,也可以處理服務間的東西向流量。同時,它也支持作為 Kubernetes Ingress Controller 來使用。
APISIX 基于 Nginx 和 etcd,與傳統(tǒng) API 網(wǎng)關(guān)相比,APISIX 具有動態(tài)路由和熱加載插件功能,避免了配置之后的 reload 操作,同時 APISIX 支持 HTTP(S)、HTTP2、Dubbo、QUIC、MQTT、TCP/UDP 等更多的協(xié)議。而且還內(nèi)置了 Dashboard,提供強大而靈活的界面。同樣也提供了豐富的插件支持功能,而且還可以讓用戶自定義插件。
主要具有以下幾個特點:
- 多平臺支持 :APISIX 提供了多平臺解決方案,它不但支持裸機運行,也支持在 Kubernetes 中使用,還支持與 AWS Lambda、Azure Function、Lua 函數(shù)和 Apache OpenWhisk 等云服務集成。
- 全動態(tài)能力 :APISIX 支持熱加載,這意味著你不需要重啟服務就可以更新 APISIX 的配置。請訪問為什么 Apache APISIX 選擇 Nginx + Lua 這個技術(shù)棧?以了解實現(xiàn)原理。
- 精細化路由 :APISIX 支持使用 NGINX 內(nèi)置變量做為路由的匹配條件,你可以自定義匹配函數(shù)來過濾請求,匹配路由。
- 運維友好 :APISIX 支持與以下工具和平臺集成:HashiCorp Vault、Zipkin、Apache SkyWalking、Consul、Nacos、Eureka。通過 APISIX Dashboard,運維人員可以通過友好且直觀的 UI 配置 APISIX。
- 多語言插件支持 :APISIX 支持多種開發(fā)語言進行插件開發(fā),開發(fā)人員可以選擇擅長語言的 SDK 開發(fā)自定義插件。
安裝 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?,F(xiàn)在我們就可以使用 docker-compose 來進行一鍵啟動:
? docker-compose -f docker-compose.yml up -d
另外兩個 nginx 容器是用于測試的:
docker-compose
請確保其他系統(tǒng)進程沒有占用 9000、9080、9091、9092、9180、9443 和 2379 端口。如果啟動有錯誤,可以嘗試為 examples 目錄設(shè)置成 777 權(quán)限,保證 etcd 數(shù)據(jù)有權(quán)限寫入。
當 APISIX 啟動完成后我們就可以通過 curl 來訪問正在運行的 APISIX 實例。比如,可以發(fā)送一個簡單的 HTTP 請求來驗證 APISIX 運行狀態(tài)是否正常。
? 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
現(xiàn)在,你已經(jīng)成功安裝并運行了 APISIX !
功能測試
接下來我們來了解下 APISIX 的一些功能。在了解之前我們需要對 APISIX 的幾個主要概念和組件簡單了解下:
上游
Upstream 也稱為上游,上游是對虛擬主機的抽象,即應用層服務或節(jié)點的抽象。
上游的作用是按照配置規(guī)則對服務節(jié)點進行負載均衡,它的地址信息可以直接配置到路由或服務上。當多個路由或服務引用同一個上游時,可以通過創(chuàng)建上游對象,在路由或服務中使用上游的 ID 方式引用上游,減輕維護壓力。
路由
Route 也稱為路由,是 APISIX 中最基礎(chǔ)和最核心的資源對象。
APISIX 可以通過路由定義規(guī)則來匹配客戶端請求,根據(jù)匹配結(jié)果加載并執(zhí)行相應的插件,最后把請求轉(zhuǎn)發(fā)給到指定的上游服務。路由中主要包含三部分內(nèi)容:匹配規(guī)則、插件配置和上游信息。
服務
Service 也稱為服務,是某類 API 的抽象(也可以理解為一組 Route 的抽象)。它通常與上游服務抽象是一一對應的,Route 與 Service 之間,通常是 N:1
的關(guān)系。
消費者
Consumer 是某類服務的消費者,需要與用戶認證配合才可以使用。當不同的消費者請求同一個 API 時,APISIX 會根據(jù)當前請求的用戶信息,對應不同的 Plugin 或 Upstream 配置。如果 Route、Service、Consumer 和 Plugin Config 都綁定了相同的插件,只有消費者的插件配置會生效。插件配置的優(yōu)先級由高到低的順序是:Consumer > Route > Plugin Config > Service。
對于 API 網(wǎng)關(guān)而言,一般情況可以通過請求域名、客戶端 IP 地址等字段識別到某類請求方,然后進行插件過濾并轉(zhuǎn)發(fā)請求到指定上游。但有時候該方式達不到用戶需求,因此 APISIX 支持了 Consumer 對象。
插件
Plugin 也稱之為插件,它是擴展 APISIX 應用層能力的關(guān)鍵機制,也是在使用 APISIX 時最常用的資源對象。插件主要是在 HTTP 請求或響應生命周期期間執(zhí)行的、針對請求的個性化策略。插件可以與路由、服務或消費者綁定。
如果路由、服務、插件配置或消費者都綁定了相同的插件,則只有一份插件配置會生效,插件配置的優(yōu)先級由高到低順序是:消費者 > 路由 > 插件配置 > 服務。同時在插件執(zhí)行過程中也會涉及 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 來獲取、創(chuàng)建、更新以及刪除資源。同時得益于 APISIX 的熱加載能力,資源配置完成后 APISIX 將會自動更新配置,無需重啟服務,具體的架構(gòu)原理可以查看下面的架構(gòu)圖:
APISIX 架構(gòu)圖
主要分為兩個部分:
- APISIX 核心 :包括 Lua 插件、多語言插件運行時(Plugin Runner)、Wasm 插件運行時等;
- 功能豐富的各種內(nèi)置插件 :包括可觀測性、安全、流量控制等。
APISIX 在其核心中,提供了路由匹配、負載均衡、服務發(fā)現(xiàn)、API 管理等重要功能,以及配置管理等基礎(chǔ)性模塊。除此之外,APISIX 插件運行時也包含其中,提供原生 Lua 插件的運行框架和多語言插件的運行框架,以及實驗性的 Wasm 插件運行時等。APISIX 多語言插件運行時提供多種開發(fā)語言的支持,比如 Golang、Java、Python、JS 等。
APISIX 目前也內(nèi)置了各類插件,覆蓋了 API 網(wǎng)關(guān)的各種領(lǐng)域,如認證鑒權(quán)、安全、可觀測性、流量管理、多協(xié)議接入等。當前 APISIX 內(nèi)置的插件使用原生 Lua 實現(xiàn),關(guān)于各個插件的介紹與使用方式,后續(xù)我們再介紹。
創(chuàng)建路由
下面的示例中我們先使用 Admin API 來創(chuàng)建一個 Route 并與 Upstream 綁定,當一個請求到達 APISIX 時,APISIX 會將請求轉(zhuǎn)發(fā)到指定的上游服務中。
以下示例代碼中,我們將為路由配置匹配規(guī)則,以便 APISIX 可以將請求轉(zhuǎn)發(fā)到對應的上游服務:
? 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'
# 正常會得到如下所示的結(jié)果
{"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
下面。
該配置意味著,當請求滿足下述的所有規(guī)則時,請求將被轉(zhuǎn)發(fā)到上游服務(httpbin.org:80
):
- 請求的 HTTP 方法為 GET。
- 請求頭包含 host 字段,且它的值為
youdianzhishi.com
。 - 請求路徑匹配
/anything/*
,*
意味著任意的子路徑,例如/anything/foo?arg=10
。
當路由創(chuàng)建完成后,現(xiàn)在我們就可以通過以下命令訪問上游服務了:
? 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 轉(zhuǎn)發(fā)到 http://httpbin.org:80/anything/foo?arg=10
,我們可以和直接訪問上游數(shù)據(jù)進行對比。
httpbin數(shù)據(jù)
使用上游服務創(chuàng)建路由
我們還可以通過以下命令創(chuàng)建一個上游,并在路由中使用它,而不是直接將其配置在路由中:
? 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"}
該上游配置與上一節(jié)配置在路由中的上游相同。同樣使用了 roundrobin
作為負載均衡機制,并設(shè)置了 httpbin.org:80
為上游服務。為了將該上游綁定到路由,此處需要把 upstream_id
設(shè)置為 "1"。
上游服務創(chuàng)建完成后,現(xiàn)在我們可以通過以下命令將其綁定到指定的 /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"}
我們已經(jīng)創(chuàng)建了路由與上游服務,現(xiàn)在可以通過以下命令訪問上游服務:
? 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 轉(zhuǎn)發(fā)到 http://httpbin.org:80/anything/foo?arg=10
。
使用 Dashboard
同樣我們還可以使用 APISIX Dashboard 創(chuàng)建和配置類似于上述步驟中所創(chuàng)建的路由。
如果你已經(jīng)完成上述操作步驟,正常現(xiàn)在我們已經(jīng)可以通過 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 中也已經(jīng)啟動了 Grafana,所以登錄后我們也可以在首頁儀表盤上配置 Grafana,地址為 http://localhost:3000
。
Grafana
登錄后單擊側(cè)邊欄中的路由,可以查看已經(jīng)配置的路由列表,可以看到在上述步驟中使用 Admin API 創(chuàng)建的路由。
路由列表
你也可以通過單擊創(chuàng)建按鈕并按照提示創(chuàng)建新路由:
如果想利用 APISIX 實現(xiàn)身份驗證、安全性、限流限速和可觀測性等功能,可通過添加插件實現(xiàn)。
限流限速和安全插件
在很多時候,我們的 API 并不是處于一個非常安全的狀態(tài),它隨時會收到不正常的訪問,一旦訪問流量突增,可能就會導致你的 API 發(fā)生故障,這個時候我們就可以通過速率限制來保護 API 服務,限制非正常的訪問請求。對此,我們可以使用如下方式進行:
- 限制請求速率;
- 限制單位時間內(nèi)的請求數(shù);
- 延遲請求;
- 拒絕客戶端請求;
- 限制響應數(shù)據(jù)的速率。
APISIX 提供了多個內(nèi)置的限流限速的插件,包括 limit-conn
、limit-count
和 limit-req
。
limit-conn
插件主要用于限制客戶端對服務的并發(fā)請求數(shù)。limit-req
插件使用漏桶算法限制對用戶服務的請求速率。limit-count
插件主要用于在指定的時間范圍內(nèi),限制每個客戶端總請求個數(shù)。
這里我們就以 limit-count
插件為例,來說明如何通過限流限速插件保護我們的 API 服務。如下所示。
使用下面的命令首先創(chuàng)建一條路由:
? 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'
這里我們直接使用前面已經(jīng)創(chuàng)建的上游(ID 為 1)來創(chuàng)建/更新一條路由,并且在 plugins
中啟用了 limit-count
插件,該插件僅允許客戶端在 60 秒內(nèi),訪問上游服務 2 次,超過兩次,就會返回 503 錯誤碼。
上面的指令執(zhí)行成功后,接下來我們連續(xù)使用下面的命令訪問三次后,則會出現(xiàn)如下錯誤。
? 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
正常情況下就會出現(xiàn)如下所示的 503 錯誤,則表示 limit-count
插件已經(jīng)配置成功。
<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>
緩存響應
當我們在構(gòu)建一個 API 時,肯定希望他能夠盡量保持簡單和快速,一旦讀取相同數(shù)據(jù)的并發(fā)需求增加,可能會面臨一些問題,一般我們直接的辦法就是引入緩存,當然我們可以在不同層面去進行緩存的。
- 邊緣緩存或 CDN
- 數(shù)據(jù)庫緩存
- 服務器緩存(API 緩存)
- 瀏覽器緩存
反向代理緩存是另一種緩存機制,通常在 API 網(wǎng)關(guān)內(nèi)實現(xiàn)。它可以減少對你的端點的調(diào)用次數(shù),也可以通過緩存上游的響應來改善對你的 API 請求的延遲。如果 API Gateway 的緩存中有所請求資源的新鮮副本,它就會使用該副本直接滿足請求,而不是向端點發(fā)出請求。如果沒有找到緩存的數(shù)據(jù),請求就會轉(zhuǎn)到預定的上游服務(后端服務)。
我們這里主要了解的是 API 網(wǎng)關(guān)層的緩存,也就是 APISIX 提供的 API 緩存,它也可以和其他插件一起使用,目前支持基于磁盤的緩存,也可以在插件配置中指定緩存過期時間或內(nèi)存容量等。
比如我們現(xiàn)在有一個 /products
的 API 接口,通常每天只更新一次,而該端點每天都會收到重復的數(shù)十億次請求,以獲取產(chǎn)品列表數(shù)據(jù),現(xiàn)在我們就可以使用 APISIX 提供的一個名為 proxy-cache
的插件來緩存該接口的響應。
這里我們還是使用前面 ID 為 1 的上游對象,使用 /anything/products
來模擬產(chǎn)品接口,直接執(zhí)行下面的命令來更新路由的插件:
? 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"
}'
更新完成后現(xiàn)在我們來對該接口發(fā)起幾次請求:
? 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
,這意味著當請求第一次進入路由時,響應還沒有被緩存。而后面的幾次請求會得到一個緩存的響應,緩存指標變?yōu)榱?HIT
,表示我們的響應緩存成功了。
-
API
+關(guān)注
關(guān)注
2文章
1502瀏覽量
62080 -
nginx
+關(guān)注
關(guān)注
0文章
150瀏覽量
12184 -
MQTT
+關(guān)注
關(guān)注
5文章
651瀏覽量
22528 -
zetcd
+關(guān)注
關(guān)注
0文章
3瀏覽量
2825
發(fā)布評論請先 登錄
相關(guān)推薦
評論