新聞中心
我今天就在和大家探討一下 API Gateway。在微服務(wù)的架構(gòu)下,API 網(wǎng)關(guān)是一個(gè)常見(jiàn)的架構(gòu)設(shè)計(jì)模式。

目前創(chuàng)新互聯(lián)已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機(jī)、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、關(guān)嶺網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶(hù)導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶(hù)和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
以下是微服務(wù)中常見(jiàn)的問(wèn)題,需要引入 API 網(wǎng)關(guān)來(lái)協(xié)助解決:
- 微服務(wù)提供的 API 的粒度通常與客戶(hù)端所需的粒度不同。微服務(wù)通常提供細(xì)粒度的 API,這意味著客戶(hù)端需要與多個(gè)服務(wù)進(jìn)行交互。例如,如上所述,需要產(chǎn)品詳細(xì)信息的客戶(hù)需要從眾多服務(wù)中獲取數(shù)據(jù)。
- 不同的客戶(hù)端需要不同的數(shù)據(jù)。例如,產(chǎn)品詳細(xì)信息頁(yè)面桌面的桌面瀏覽器版本通常比移動(dòng)版本更為詳盡。
- 對(duì)于不同類(lèi)型的客戶(hù)端,網(wǎng)絡(luò)性能是不同的。例如,與非移動(dòng)網(wǎng)絡(luò)相比,移動(dòng)網(wǎng)絡(luò)通常要慢得多并且具有更高的延遲。而且,當(dāng)然,任何 WAN 都比 LAN 慢得多。
- 這意味著本機(jī)移動(dòng)客戶(hù)端使用的網(wǎng)絡(luò)性能與服務(wù)器端 Web 應(yīng)用程序使用的 LAN 的性能差異很大。服務(wù)器端 Web 應(yīng)用程序可以向后端服務(wù)發(fā)出多個(gè)請(qǐng)求,而不會(huì)影響用戶(hù)體驗(yàn),而移動(dòng)客戶(hù)端只能提供幾個(gè)請(qǐng)求。
- 微服務(wù)實(shí)例數(shù)量及其位置(主機(jī)+端口)動(dòng)態(tài)變化。
- 服務(wù)劃分會(huì)隨著時(shí)間的推移而變化,應(yīng)該對(duì)客戶(hù)端隱藏。
- 服務(wù)可能會(huì)使用多種協(xié)議,其中一些協(xié)議可能對(duì)網(wǎng)絡(luò)不友好。
常見(jiàn)的API網(wǎng)關(guān)主要提供以下的功能:
- 反向代理和路由:大多數(shù)項(xiàng)目采用網(wǎng)關(guān)的解決方案的最主要的原因。給出了訪問(wèn)后端 API 的所有客戶(hù)端的單一入口,并隱藏內(nèi)部服務(wù)部署的細(xì)節(jié)。
- 負(fù)載均衡:網(wǎng)關(guān)可以將單個(gè)傳入的請(qǐng)求路由到多個(gè)后端目的地。
- 身份驗(yàn)證和授權(quán):網(wǎng)關(guān)應(yīng)該能夠成功進(jìn)行身份驗(yàn)證并僅允許可信客戶(hù)端訪問(wèn) API,并且還能夠使用類(lèi)似 RBAC 等方式來(lái)授權(quán)。
- IP 列表白名單/黑名單:允許或阻止某些 IP 地址通過(guò)。
- 性能分析:提供一種記錄與 API 調(diào)用相關(guān)的使用和其他有用度量的方法。
- 限速和流控:控制 API 調(diào)用的能力。
- 請(qǐng)求變形:在進(jìn)一步轉(zhuǎn)發(fā)之前,能夠在轉(zhuǎn)發(fā)之前轉(zhuǎn)換請(qǐng)求和響應(yīng)(包括 Header 和 Body)。
- 版本控制:同時(shí)使用不同版本的 API 選項(xiàng)或可能以金絲雀發(fā)布或藍(lán)/綠部署的形式提供慢速推出 API。
- 斷路器:微服務(wù)架構(gòu)模式有用,以避免使用中斷。
- 多協(xié)議支持:WebSocket/GRPC。
- 緩存:減少網(wǎng)絡(luò)帶寬和往返時(shí)間消耗,如果可以緩存頻繁要求的數(shù)據(jù),則可以提高性能和響應(yīng)時(shí)間
- API 文檔:如果計(jì)劃將 API 暴露給組織以外的開(kāi)發(fā)人員,那么必須考慮使用 API 文檔,例如 Swagger 或 OpenAPI。
有很多的開(kāi)源軟件可以提供 API 網(wǎng)關(guān)的支持,下面我們就看看他們各自的架構(gòu)和功能。
為了對(duì)這些開(kāi)源網(wǎng)關(guān)進(jìn)行基本功能的驗(yàn)證,我創(chuàng)建了一些代碼,使用 OpenAPI 生成了四個(gè)基本的 API 服務(wù),包含 Golang,Nodejs,Python Flask 和 Java Spring。
API 使用了常見(jiàn)的寵物商店的樣例,聲明如下:
- openapi: "3.0.0"
- info:
- version: 1.0.0
- title: Swagger Petstore
- license:
- name: MIT
- servers:
- - url: http://petstore.swagger.io/v1
- paths:
- /pets:
- get:
- summary: List all pets
- operationId: listPets
- tags:
- - pets
- parameters:
- - name: limit
- in: query
- description: How many items to return at one time (max 100)
- required: false
- schema:
- type: integer
- format: int32
- responses:
- '200':
- description: A paged array of pets
- headers:
- x-next:
- description: A link to the next page of responses
- schema:
- type: string
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/Pets"
- default:
- description: unexpected error
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/Error"
- post:
- summary: Create a pet
- operationId: createPets
- tags:
- - pets
- responses:
- '201':
- description: Null response
- default:
- description: unexpected error
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/Error"
- /pets/{petId}:
- get:
- summary: Info for a specific pet
- operationId: showPetById
- tags:
- - pets
- parameters:
- - name: petId
- in: path
- required: true
- description: The id of the pet to retrieve
- schema:
- type: string
- responses:
- '200':
- description: Expected response to a valid request
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/Pet"
- default:
- description: unexpected error
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/Error"
- components:
- schemas:
- Pet:
- type: object
- required:
- - id
- - name
- properties:
- id:
- type: integer
- format: int64
- name:
- type: string
- tag:
- type: string
- Pets:
- type: array
- items:
- $ref: "#/components/schemas/Pet"
- Error:
- type: object
- required:
- - code
- - message
- properties:
- code:
- type: integer
- format: int32
- message:
- type: string
構(gòu)建好的 Web 服務(wù)通過(guò) Docker Compose 來(lái)進(jìn)行容器化的部署。
- version: "3.7"
- services:
- goapi:
- container_name: goapi
- image: naughtytao/goapi:0.1
- ports:
- - "18000:8080"
- deploy:
- resources:
- limits:
- cpus: '1'
- memory: 256M
- reservations:
- memory: 256M
- nodeapi:
- container_name: nodeapi
- image: naughtytao/nodeapi:0.1
- ports:
- - "18001:8080"
- deploy:
- resources:
- limits:
- cpus: '1'
- memory: 256M
- reservations:
- memory: 256M
- flaskapi:
- container_name: flaskapi
- image: naughtytao/flaskapi:0.1
- ports:
- - "18002:8080"
- deploy:
- resources:
- limits:
- cpus: '1'
- memory: 256M
- reservations:
- memory: 256M
- springapi:
- container_name: springapi
- image: naughtytao/springapi:0.1
- ports:
- - "18003:8080"
- deploy:
- resources:
- limits:
- cpus: '1'
- memory: 256M
- reservations:
- memory: 256M
我們?cè)趯W(xué)習(xí)這些開(kāi)源網(wǎng)關(guān)架構(gòu)的同時(shí),也會(huì)對(duì)其最基本的路由轉(zhuǎn)發(fā)功能作出驗(yàn)證。
這里用戶(hù)發(fā)送的請(qǐng)求 server/service_name/v1/ 會(huì)發(fā)送給 API 網(wǎng)關(guān),網(wǎng)關(guān)通過(guò) service name 來(lái)路由到不同的后端服務(wù)。
我們使用 K6 用 100 個(gè)并發(fā)跑 1000 次測(cè)試的結(jié)果如上圖,我們看到直連的綜合響應(yīng),每秒可以處理的請(qǐng)求數(shù)量大概是 1100+。
Nginx
Nginx 是異步框架的網(wǎng)頁(yè)服務(wù)器,也可以用作反向代理、負(fù)載平衡器和 HTTP 緩存。
該軟件由伊戈?duì)枴べ愃饕騽?chuàng)建并于 2004 年首次公開(kāi)發(fā)布。2011 年成立同名公司以提供支持。2019 年 3 月 11 日,Nginx 公司被 F5 Networks 以 6.7 億美元收購(gòu)。
Nginx 有以下的特點(diǎn):
- 由 C 編寫(xiě),占用的資源和內(nèi)存低,性能高。
- 單進(jìn)程多線程,當(dāng)啟動(dòng) Nginx 服務(wù)器,會(huì)生成一個(gè) master 進(jìn)程,master 進(jìn)程會(huì) fork 出多個(gè) worker 進(jìn)程,由 worker 線程處理客戶(hù)端的請(qǐng)求。
- 支持反向代理,支持 7 層負(fù)載均衡(拓展負(fù)載均衡的好處)。
- 高并發(fā),Nginx 是異步非阻塞型處理請(qǐng)求,采用的 epollandqueue 模式。
- 處理靜態(tài)文件速度快。
- 高度模塊化,配置簡(jiǎn)單。社區(qū)活躍,各種高性能模塊出品迅速。
如上圖所示,Nginx 主要由 Master,Worker 和 Proxy Cache 三個(gè)部分組成。
Master 主控:NGINX 遵循主從架構(gòu)。它將根據(jù)客戶(hù)的要求為 Worker 分配工作。
將工作分配給 Worker 后,Master 將尋找客戶(hù)的下一個(gè)請(qǐng)求,因?yàn)樗粫?huì)等待 Worker 的響應(yīng)。一旦響應(yīng)來(lái)自 Worker,Master 就會(huì)將響應(yīng)發(fā)送給客戶(hù)端。
Worker 工作單元:Worker 是 NGINX 架構(gòu)中的 Slave。每個(gè)工作單元可以單線程方式一次處理 1000 個(gè)以上的請(qǐng)求。
一旦處理完成,響應(yīng)將被發(fā)送到主服務(wù)器。單線程將通過(guò)在相同的內(nèi)存空間而不是不同的內(nèi)存空間上工作來(lái)節(jié)省 RAM 和 ROM 的大小。多線程將在不同的內(nèi)存空間上工作。
Cache 緩存:Nginx 緩存用于通過(guò)從緩存而不是從服務(wù)器獲取來(lái)非??焖俚爻尸F(xiàn)頁(yè)面。在第一個(gè)頁(yè)面請(qǐng)求時(shí),頁(yè)面將被存儲(chǔ)在高速緩存中。
為了實(shí)現(xiàn) API 的路由轉(zhuǎn)發(fā),需要只需要對(duì) Nginx 作出如下的配置:
- server {
- listen 80 default_server;
- location /goapi {
- rewrite ^/goapi(.*) $1 break;
- proxy_pass http://goapi:8080;
- }
- location /nodeapi {
- rewrite ^/nodeapi(.*) $1 break;
- proxy_pass http://nodeapi:8080;
- }
- location /flaskapi {
- rewrite ^/flaskapi(.*) $1 break;
- proxy_pass http://flaskapi:8080;
- }
- location /springapi {
- rewrite ^/springapi(.*) $1 break;
- proxy_pass http://springapi:8080;
- }
- }
我們基于不同的服務(wù) goapi,nodeapi,flaskapi 和 springapi,分別配置一條路由,在轉(zhuǎn)發(fā)之前,需要利用 rewrite 來(lái)去掉服務(wù)名,并發(fā)送給對(duì)應(yīng)的服務(wù)。
使用容器把 Nginx 和后端的四個(gè)服務(wù)部署在同一個(gè)網(wǎng)絡(luò)下,通過(guò)網(wǎng)關(guān)連接路由轉(zhuǎn)發(fā)的。
Nginx 的部署如下:
- version: "3.7"
- services:
- web:
- container_name: nginx
- image: nginx
- volumes:
- - ./templates:/etc/nginx/templates
- - ./conf/default.conf:/etc/nginx/conf.d/default.conf
- ports:
- - "8080:80"
- environment:
- - NGINX_HOST=localhost
- - NGINX_PORT=80
- deploy:
- resources:
- limits:
- cpus: '1'
- memory: 256M
- reservations:
- memory: 256M
K6 通過(guò) Nginx 網(wǎng)關(guān)的測(cè)試結(jié)果如下:
每秒處理的請(qǐng)求數(shù)量是 1093,和不通過(guò)網(wǎng)關(guān)轉(zhuǎn)發(fā)相比非常接近。
從功能上看,Nginx 可以滿(mǎn)足用戶(hù)對(duì)于 API 網(wǎng)關(guān)的大部分需求,可以通過(guò)配置和插件的方式來(lái)支持不同的功能,性能非常優(yōu)秀。
缺點(diǎn)是沒(méi)有管理的 UI 和管理 API,大部分的工作都需要手工配置 config 文件的方式來(lái)進(jìn)行。商業(yè)版本的功能會(huì)更加完善。
Kong
Kong 是基于 NGINX 和 OpenResty 的開(kāi)源 API 網(wǎng)關(guān)。
Kong 的總體基礎(chǔ)結(jié)構(gòu)由三個(gè)主要部分組成:NGINX 提供協(xié)議實(shí)現(xiàn)和工作進(jìn)程管理,OpenResty 提供 Lua 集成并掛鉤到 NGINX 的請(qǐng)求處理階段。
而 Kong 本身利用這些掛鉤來(lái)路由和轉(zhuǎn)換請(qǐng)求。數(shù)據(jù)庫(kù)支持 Cassandra 或 Postgres 存儲(chǔ)所有配置。
Kong 附帶各種插件,提供訪問(wèn)控制,安全性,緩存和文檔等功能。它還允許使用 Lua 語(yǔ)言編寫(xiě)和使用自定義插件。
Kong 也可以部署為 Kubernetes Ingress 并支持 GRPC 和 WebSockets 代理。
NGINX 提供了強(qiáng)大的 HTTP 服務(wù)器基礎(chǔ)結(jié)構(gòu)。它處理 HTTP 請(qǐng)求處理,TLS 加密,請(qǐng)求日志記錄和操作系統(tǒng)資源分配(例如,偵聽(tīng)和管理客戶(hù)端連接以及產(chǎn)生新進(jìn)程)。
NGINX 具有一個(gè)聲明性配置文件,該文件位于其主機(jī)操作系統(tǒng)的文件系統(tǒng)中。
雖然僅通過(guò) NGINX 配置就可以實(shí)現(xiàn)某些 Kong 功能(例如,基于請(qǐng)求的 URL 確定上游請(qǐng)求路由),但修改該配置需要一定級(jí)別的操作系統(tǒng)訪問(wèn)權(quán)限,以編輯配置文件并要求 NGINX 重新加載它們。
而 Kong 允許用戶(hù)執(zhí)行以下操作:通過(guò) RESTful HTTP API 更新配置。Kong 的 NGINX 配置是相當(dāng)基本的:除了配置標(biāo)準(zhǔn)標(biāo)頭,偵聽(tīng)端口和日志路徑外,大多數(shù)配置都委托給 OpenResty。
在某些情況下,在 Kong 的旁邊添加自己的 NGINX 配置非常有用,例如在 API 網(wǎng)關(guān)旁邊提供靜態(tài)網(wǎng)站。在這種情況下,您可以修改 Kong 使用的配置模板。
NGINX 處理的請(qǐng)求經(jīng)過(guò)一系列階段。NGINX 的許多功能(例如,使用 C 語(yǔ)言編寫(xiě)的模塊)都提供了進(jìn)入這些階段的功能(例如,使用 gzip 壓縮的功能)。
雖然可以編寫(xiě)自己的模塊,但是每次添加或更新模塊時(shí)都必須重新編譯 NGINX。為了簡(jiǎn)化添加新功能的過(guò)程,Kong 使用了 OpenResty。
OpenResty 是一個(gè)軟件套件,捆綁了 NGINX,一組模塊,LuaJIT 和一組 Lua 庫(kù)。
其中最主要的是 ngx_http_lua_module一個(gè)NGINX 模塊,該模塊嵌入 Lua 并為大多數(shù) NGINX 請(qǐng)求階段提供 Lua 等效項(xiàng)。
這有效地允許在 Lua 中開(kāi)發(fā) NGINX 模塊,同時(shí)保持高性能(LuaJIT 相當(dāng)快),并且 Kong 用它來(lái)提供其核心配置管理和插件管理基礎(chǔ)結(jié)構(gòu)。
Kong 通過(guò)其插件體系結(jié)構(gòu)提供了一個(gè)框架,可以掛接到上述請(qǐng)求階段。從上面的示例開(kāi)始,Key Auth 和 ACL 插件都控制客戶(hù)端(也稱(chēng)為使用者)是否應(yīng)該能夠發(fā)出請(qǐng)求。
每個(gè)插件都在其處理程序中定義了自己的訪問(wèn)函數(shù),并且該函數(shù)針對(duì)通過(guò)給定路由或服務(wù)啟用的每個(gè)插件執(zhí)行 kong.access()。
執(zhí)行順序由優(yōu)先級(jí)值決定,如果 Key Auth 的優(yōu)先級(jí)為 1003,ACL 的優(yōu)先級(jí)為 950,則 Kong 將首先執(zhí)行 Key Auth 的訪問(wèn)功能,如果它不放棄請(qǐng)求,則將執(zhí)行 ACL,然后再通過(guò)將該 ACL 傳遞給上游 proxy_pass。
由于 Kong 的請(qǐng)求路由和處理配置是通過(guò)其 admin API 控制的,因此可以在不編輯底層 NGINX 配置的情況下即時(shí)添加和刪除插件配置。
因?yàn)?Kong 本質(zhì)上提供了一種在 API 中注入位置塊(通過(guò) API 定義)和配置的方法。它們通過(guò)將插件,證書(shū)等分配給這些 API。
我們使用以下的配置部署 Kong 到容器中(省略四個(gè)微服務(wù)的部署):
- version: '3.7'
- volumes:
- kong_data: {}
- networks:
- kong-net:
- external: false
- services:
- kong:
- image: "${KONG_DOCKER_TAG:-kong:latest}"
- user: "${KONG_USER:-kong}"
- depends_on:
- - db
- environment:
- KONG_ADMIN_ACCESS_LOG: /dev/stdout
- KONG_ADMIN_ERROR_LOG: /dev/stderr
- KONG_ADMIN_LISTEN: '0.0.0.0:8001'
- KONG_CASSANDRA_CONTACT_POINTS: db
- KONG_DATABASE: postgres
- KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong}
- KONG_PG_HOST: db
- KONG_PG_USER: ${KONG_PG_USER:-kong}
- KONG_PROXY_ACCESS_LOG: /dev/stdout
- KONG_PROXY_ERROR_LOG: /dev/stderr
- KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password
- secrets:
- - kong_postgres_password
- networks:
- - kong-net
- ports:
- - "8080:8000/tcp"
- - "127.0.0.1:8001:8001/tcp"
- - "8443:8443/tcp"
- - "127.0.0.1:8444:8444/tcp"
- healthcheck:
- test: ["CMD", "kong", "health"]
- interval: 10s
- timeout: 10s
- retries: 10
- restart: on-failure
- deploy:
- restart_policy:
- condition: on-failure
- db:
- image: postgres:9.5
- environment:
- POSTGRES_DB: ${KONG_PG_DATABASE:-kong}
- POSTGRES_USER: ${KONG_PG_USER:-kong}
- POSTGRES_PASSWORD_FILE: /run/secrets/kong_postgres_password
- secrets:
- - kong_postgres_password
- healthcheck:
- test: ["CMD", "pg_isready", "-U", "${KONG_PG_USER:-kong}"]
- interval: 30s
- timeout: 30s
- retries: 3
- restart: on-failure
- deploy:
- restart_policy:
- condition: on-failure
- stdin_open: true
- tty: true
- networks:
- - kong-net
- volumes:
- - kong_data:/var/lib/postgresql/data
- secrets:
- kong_postgres_password:
- file: ./POSTGRES_PASSWORD
數(shù)據(jù)庫(kù)選擇了 PostgreSQL,開(kāi)源版本沒(méi)有 Dashboard,我們使用 RestAPI 創(chuàng)建所有的網(wǎng)關(guān)路由:
- curl -i -X POST http://localhost:8001/services \
- --data name=goapi \
- --data url='http://goapi:8080'
- curl -i -X POST http://localhost:8001/services/goapi/routes \
- --data 'paths[]=/goapi' \
- --data name=goapi
需要先創(chuàng)建一個(gè) service,然后在該 service 下創(chuàng)建一條路由。
使用 K6 壓力測(cè)試的結(jié)果如下:
每秒請(qǐng)求數(shù) 705 要明顯弱于 Nginx,所以所有的功能都是有成本的。
APISIX
Apache APISIX 是一個(gè)動(dòng)態(tài)、實(shí)時(shí)、高性能的 API 網(wǎng)關(guān), 提供負(fù)載均衡、動(dòng)態(tài)上游、灰度發(fā)布、服務(wù)熔斷、身份認(rèn)證、可觀測(cè)性等豐富的流量管理功能。
APISIX 于 2019 年 4 月由中國(guó)的支流科技創(chuàng)建,于 6 月開(kāi)源,并于同年 10 月進(jìn)入 Apache 孵化器。
支流科技對(duì)應(yīng)的商業(yè)化產(chǎn)品的名字叫 API7 。APISIX 旨在處理大量請(qǐng)求,并具有較低的二次開(kāi)發(fā)門(mén)檻。
APISIX 的主要功能和特點(diǎn)有:
- 云原生設(shè)計(jì),輕巧且易于容器化。
- 集成了統(tǒng)計(jì)和監(jiān)視組件,例如 Prometheus,Apache Skywalking 和 Zipkin。
- 支持 gRPC,Dubbo,WebSocket,MQTT 等代理協(xié)議,以及從 HTTP 到 gRPC 的協(xié)議轉(zhuǎn)碼,以適應(yīng)各種情況。
- 擔(dān)當(dāng) OpenID 依賴(lài)方的角色,與 Auth0,Okta 和其他身份驗(yàn)證提供程序的服務(wù)連接。
- 通過(guò)在運(yùn)行時(shí)動(dòng)態(tài)執(zhí)行用戶(hù)功能來(lái)支持無(wú)服務(wù)器,從而使網(wǎng)關(guān)的邊緣節(jié)點(diǎn)更加靈活。
- 支持插件熱加載。
- 不鎖定用戶(hù),支持混合云部署架構(gòu)。
- 網(wǎng)關(guān)節(jié)點(diǎn)無(wú)狀態(tài),可以靈活擴(kuò)展。
從這個(gè)角度來(lái)看,API 網(wǎng)關(guān)可以替代 Nginx 來(lái)處理南北流量,也可以扮演 Istio 控制平面和 Envoy 數(shù)據(jù)平面的角色來(lái)處理東西向流量。
APISIX 的架構(gòu)如下圖所示:
APISIX 包含一個(gè)數(shù)據(jù)平面,用于動(dòng)態(tài)控制請(qǐng)求流量;一個(gè)用于存儲(chǔ)和同步網(wǎng)關(guān)數(shù)據(jù)配置的控制平面,一個(gè)用于協(xié)調(diào)插件的 AI 平面,以及對(duì)請(qǐng)求流量的實(shí)時(shí)分析和處理。
它構(gòu)建在 Nginx 反向代理服務(wù)器和鍵值存儲(chǔ) etcd 的之上,以提供輕量級(jí)的網(wǎng)關(guān)。
它主要用 Lua 編寫(xiě),Lua 是類(lèi)似于 Python 的編程語(yǔ)言。它使用 Radix 樹(shù)進(jìn)行路由,并使用前綴樹(shù)進(jìn)行 IP 匹配。
使用 etcd 而不是關(guān)系數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)配置可以使它更接近云原生,但是即使在任何服務(wù)器宕機(jī)的情況下,也可以確保整個(gè)網(wǎng)關(guān)系統(tǒng)的可用性。
所有組件都是作為插件編寫(xiě)的,因此其模塊化設(shè)計(jì)意味著功能開(kāi)發(fā)人員只需要關(guān)心自己的項(xiàng)目即可。
內(nèi)置的插件包括流控和速度限制,身份認(rèn)證,請(qǐng)求重寫(xiě),URI 重定向,開(kāi)放式跟蹤和無(wú)服務(wù)器。
APISIX 支持 OpenResty 和 Tengine 運(yùn)行環(huán)境,并且可以在 Kubernetes 的裸機(jī)上運(yùn)行。它同時(shí)支持 X86 和 ARM64。
我們同樣使用 Docker Compose 來(lái)部署 APISIX:
- version: "3.7"
- services:
- apisix-dashboard:
- image: apache/apisix-dashboard:2.4
- restart: always
- volumes:
- - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
- ports:
- - "9000:9000"
- networks:
- apisix:
- ipv4_address: 172.18.5.18
- apisix:
- image: apache/apisix:2.3-alpine
- restart: always
- volumes:
- - ./apisix_log:/usr/local/apisix/logs
- - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
- depends_on:
- - etcd
- ##network_mode: host
- ports:
- - "8080:9080/tcp"
- - "9443:9443/tcp"
- networks:
- apisix:
- ipv4_address: 172.18.5.11
- deploy:
- resources:
- limits:
- cpus: '1'
- memory: 256M
- reservations:
- memory: 256M
- etcd:
- image: bitnami/etcd:3.4.9
- user: root
- restart: always
- volumes:
- - ./etcd_data:/etcd_data
- environment:
- ETCD_DATA_DIR: /etcd_data
- 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"
- ports:
- - "2379:2379/tcp"
- networks:
- apisix:
- ipv4_address: 172.18.5.10
- networks:
- apisix:
- driver: bridge
- ipam:
- config:
- - subnet: 172.18.0.0/16
開(kāi)源的 APISIX 支持 Dashboard 的方式來(lái)管理路由,而不是像 KONG 把儀表盤(pán)功能限制在商業(yè)版本中。
但是 APISIX 的儀表盤(pán)不支持對(duì)路由 URI 進(jìn)行改寫(xiě),所以我們只好使用 RestAPI 來(lái)創(chuàng)建路由。
創(chuàng)建一個(gè)服務(wù)的路由的命令如下:
- curl --location --request PUT 'http://127.0.0.1:8080/apisix/admin/routes/1' \
- --header 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
- --header 'Content-Type: text/plain' \
- --data-raw '{
- "uri": "/goapi/*",
- "plugins": {
- "proxy-rewrite": {
- "regex_uri": ["^/goapi(.*)$","$1"]
- }
- },
- "upstream": {
- "type": "roundrobin",
- "nodes": {
- "goapi:8080": 1
- }
- }
- }'
使用 K6 壓力測(cè)試的結(jié)果如下:
APISix 取得了 1155 的好成績(jī),表現(xiàn)出接近不經(jīng)過(guò)網(wǎng)關(guān)的性能,可能緩存起到了很好的效果。
Tyk
Tyk 是一款基于 Golang 和 Redis 構(gòu)建的開(kāi)源 API 網(wǎng)關(guān)。它于 2014 年創(chuàng)建,比 AWS 的 API 網(wǎng)關(guān)即服務(wù)功能早。Tyk 用 Golang 編寫(xiě),并使用 Golang 自己的 HTTP 服務(wù)器。
Tyk 支持不同的運(yùn)行方式:云,混合(在自己的基礎(chǔ)架構(gòu)中為 GW)和本地。
Tyk 由 3 個(gè)組件組成:
- 網(wǎng)關(guān):處理所有應(yīng)用流量的代理。
- 儀表板:可以從中管理 Tyk,顯示指標(biāo)和組織 API 的界面。
- Pump:負(fù)責(zé)持久保存指標(biāo)數(shù)據(jù),并將其導(dǎo)出到 MongoDB(內(nèi)置),ElasticSearch 或 InfluxDB 等。
我們同樣使用 Docker Compose 來(lái)創(chuàng)建 Tyk 網(wǎng)關(guān)來(lái)進(jìn)行功能驗(yàn)證。
- version: '3.7'
- services:
- tyk-gateway:
- image: tykio/tyk-gateway:v3.1.1
- ports:
- - 8080:8080
- volumes:
- - ./tyk.standalone.conf:/opt/tyk-gateway/tyk.conf
- - ./apps:/opt/tyk-gateway/apps
- - ./middleware:/opt/tyk-gateway/middleware
- - ./certs:/opt/tyk-gateway/certs
- environment:
- - TYK_GW_SECRET=foo
- depends_on:
- - tyk-redis
- tyk-redis:
- image: redis:5.0-alpine
- ports:
- - 6379:6379
Tyk 的 Dashboard 也是屬于商業(yè)版本的范疇,所我們又一次需要借助 API 來(lái)創(chuàng)建路由,Tyk 是通過(guò) app 的概念來(lái)創(chuàng)建和管理路由的,你也可以直接寫(xiě) app 文件。
- curl --location --request POST 'http://localhost:8080/tyk/apis/' \
- --header 'x-tyk-authorization: foo' \
- --header 'Content-Type: application/json' \
- --data-raw '{
- "name": "GO API",
- "slug": "go-api",
- "api_id": "goapi",
- "org_id": "goapi",
- "use_keyless": true,
- "auth": {
- "auth_header_name": "Authorization"
- },
- "definition": {
- "location": "header",
- "key": "x-api-version"
- },
- "version_data": {
- "not_versioned": true,
- "versions": {
- "Default": {
- "name": "Default",
- "use_extended_paths": true
- }
- }
- },
- "proxy": {
- "listen_path": "/goapi/",
- "target_url": "http://host.docker.internal:18000/",
- "strip_listen_path": true
- },
- "active": true
- }'
使用 K6 壓力測(cè)試的結(jié)果如下:
Tyk 的結(jié)果在 400-600 左右,性能上和 KONG 接近。
Zuul
Zuul 是 Netflix 開(kāi)源的基于 Java 的 API 網(wǎng)關(guān)組件。
Zuul 包含多個(gè)組件:
- zuul-core:該庫(kù)包含編譯和執(zhí)行過(guò)濾器的核心功能。
- zuul-simple-webapp:該 Webapp 展示了一個(gè)簡(jiǎn)單的示例,說(shuō)明如何使用 zuul-core 構(gòu)建應(yīng)用程序。
- zuul-netflix:將其他 NetflixOSS 組件添加到 Zuul 的庫(kù),例如,使用 Ribbon 路由請(qǐng)求。
- zuul-netflix-webapp:將 zuul-core 和 zuul-netflix 打包到一個(gè)易于使用的程序包中的 webapp。
Zuul 提供了靈活性和彈性,部分是通過(guò)利用其他 Netflix OSS 組件進(jìn)行的:
- Hystrix 用于流控。包裝對(duì)始發(fā)地的呼叫,這使我們可以在發(fā)生問(wèn)題時(shí)丟棄流量并確定流量的優(yōu)先級(jí)。
- Ribbon 是來(lái)自 Zuul 的所有出站請(qǐng)求的客戶(hù),它提供有關(guān)網(wǎng)絡(luò)性能和錯(cuò)誤的詳細(xì)信息,并處理軟件負(fù)載平衡以實(shí)現(xiàn)均勻的負(fù)載分配。
- Turbine 實(shí)時(shí)匯總細(xì)粒度的指標(biāo),以便我們可以快速觀察問(wèn)題并做出反應(yīng)。
- Archaius 處理配置并提供動(dòng)態(tài)更改屬性的能力。
Zuul 的核心是一系列過(guò)濾器,它們能夠在路由 HTTP 請(qǐng)求和響應(yīng)期間執(zhí)行一系列操作。
以下是 Zuul 過(guò)濾器的主要特征:
- 類(lèi)型:通常定義路由流程中應(yīng)用過(guò)濾器的階段。(盡管它可以是任何自定義字符串)
- 執(zhí)行順序:在類(lèi)型中應(yīng)用,定義跨多個(gè)過(guò)濾器的執(zhí)行順序。
- 準(zhǔn)則:執(zhí)行過(guò)濾器所需的條件。
- 動(dòng)作:如果符合條件,則要執(zhí)行的動(dòng)作。
- class DeviceDelayFilter extends ZuulFilter {
- def static Random rand = new Random()
- @Override
- String filterType() {
- return 'pre'
- }
- @Override
- int filterOrder() {
- return 5
- }
- @Override
- boolean shouldFilter() {
- return RequestContext.getRequest().
- getParameter("deviceType")?equals("BrokenDevice"):false
- }
- @Override
- Object run() {
- sleep(rand.nextInt(20000)) // Sleep for a random number of
- // seconds between [0-20]
- }
- }
Zuul 提供了一個(gè)框架來(lái)動(dòng)態(tài)讀取,編譯和運(yùn)行這些過(guò)濾器。過(guò)濾器不直接相互通信。
而是通過(guò)每個(gè)請(qǐng)求唯一的 RequestContext 共享狀態(tài)。過(guò)濾器使用 Groovy 編寫(xiě)。
有幾種與請(qǐng)求的典型生命周期相對(duì)應(yīng)的標(biāo)準(zhǔn)過(guò)濾器類(lèi)型:
- Pre 過(guò)濾器在路由到原點(diǎn)之前執(zhí)行。示例包括請(qǐng)求身份驗(yàn)證,選擇原始服務(wù)器以及記錄調(diào)試信息。
- Route 路由過(guò)濾器處理將請(qǐng)求路由到源。這是使用 Apache HttpClient 或 Netflix Ribbon 構(gòu)建和發(fā)送原始 HTTP 請(qǐng)求的地方。
- 在將請(qǐng)求路由到源之后,將執(zhí)行 Post 過(guò)濾器。示例包括將標(biāo)準(zhǔn) HTTP 標(biāo)頭添加到響應(yīng),收集統(tǒng)計(jì)信息和指標(biāo)以及將響應(yīng)從源流傳輸?shù)娇蛻?hù)端。
- 在其他階段之一發(fā)生錯(cuò)誤時(shí),將執(zhí)行 Error 過(guò)濾器。
Spring Cloud 創(chuàng)建了一個(gè)嵌入式 Zuul 代理,以簡(jiǎn)化一個(gè)非常常見(jiàn)的用例的開(kāi)發(fā),在該用例中,UI 應(yīng)用程序希望代理對(duì)一個(gè)或多個(gè)后端服務(wù)的調(diào)用。
此功能對(duì)于用戶(hù)界面代理所需的后端服務(wù)很有用,從而避免了為所有后端獨(dú)立管理 CORS 和身份驗(yàn)證問(wèn)題的需求 。
要啟用它,請(qǐng)使用 @EnableZuulProxy 注解一個(gè) Spring Boot 主類(lèi),這會(huì)將本地調(diào)用轉(zhuǎn)發(fā)到適當(dāng)?shù)姆?wù)。
Zuul 是 Java 的一個(gè)庫(kù),他并不是一款開(kāi)箱即用的 API 網(wǎng)關(guān),所以需要用 Zuul 開(kāi)發(fā)一個(gè)應(yīng)用來(lái)對(duì)其功能進(jìn)行測(cè)試。
對(duì)應(yīng)的 Java 的 POM 如下:
- xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0 naughtytao.apigateway - &n
新聞標(biāo)題:開(kāi)源API網(wǎng)關(guān),到底哪個(gè)強(qiáng)?
當(dāng)前路徑:http://www.dlmjj.cn/article/cdpgdhi.html


咨詢(xún)
建站咨詢(xún)
