精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

通過實例理解API網關的主要功能特性

網絡 網絡管理
本文對已經相對成熟的API網關技術做了回顧,對API網關的演進階段、主流特性以及當前市面上的主流API網關進行了簡要說明,并以Go實現的Tyk Gateway社區開源版為例,以示例方式對API網關的主要功能做了介紹。

在當今的技術領域中,“下云”的概念正逐漸抬頭,像David Heinemeier Hansson[1](37signals公司的聯合創始人, Ruby on Rails的Creator)就直接將公司所有的業務都從公有云搬遷到了自建的數據中心[2]中。雖說大多數企業不會這么“極端”,但隨著企業對云原生架構采用的廣泛與深入,不可避免地面臨著對云服務的依賴。云服務在過去的幾年中被廣泛應用于構建靈活、可擴展的應用程序和基礎設施,為企業提供了許多便利和創新機會。然而,隨著業務規模的增長和數據量的增加,云服務的成本也隨之上升。企業開始意識到,對云服務的依賴已經成為一個值得重新評估的議題。云服務的開銷可能占據了企業可用的預算的相當大部分。為了保持競爭力并更好地控制成本,企業需要尋找方法來減少對云服務的依賴,尋找更經濟的解決方案,同時確保仍能獲得所需的性能、安全性和可擴展性。

在這樣的背景下,我們的關注點是選擇一款適宜的API網關,從主流功能特性的角度來評估候選者的支持。API網關作為現代云原生應用架構中的關鍵組件,扮演著連接前端應用和后端服務的中間層,負責管理、控制和保護API的訪問。它的功能特性對于確保API的安全性、可靠性和可擴展性至關重要。

盡管API網關并不是一個新鮮事物了,但對于那些長期依賴于云供應商的服務的人來說,它似乎變得有些“陌生”。因此,本文旨在幫助我們重新理解API網關的主要特性,并獲得對API網關選型的能力,以便在停止使用云供應商服務之前,找到一個合適的替代品^_^。

1. API網關回顧

API網關是現代應用架構中的關鍵組件之一,它的存在簡化了應用程序的架構,并為客戶端提供一個單一的訪問入口,并進行相關的控制、優化和管理。API網關可以幫助企業實現微服務架構、提高系統的可擴展性和安全性,并提供更好的開發者體驗和用戶體驗。

1.1 API網關的演化

隨著互聯網的快速發展和企業對API的需求不斷增長,API網關作為一種關鍵的中間層技術逐漸嶄露頭角并經歷了一系列的演進和發展。這里將API網關的演進歷史粗略分為以下幾個階段:

  • API網關之前的早期階段

在互聯網發展的早期階段,大多數應用程序都是以單體應用的形式存在[3]。后來隨著應用規模的擴大和業務復雜性的增加,單體應用的架構變得不夠靈活和可擴展,面向服務架構(Service-Oriented Architecture,SOA)逐漸興起,企業開始將應用程序拆分成一組獨立的服務。這個時期,每個服務都是獨立對外暴露API,客戶端也是通過這些API直接訪問服務,但這會導致一些安全性、運維和擴展性的問題。之后,企業也開始意識到需要一種中間層來管理和控制這種客戶端到服務的通信行為,并確保服務的可靠性和安全性,于是開始有了API網關的概念。

  • API網關的興起

早期的API網關,其主要功能就是單純的路由和轉發。API網關將請求從客戶端轉發到后端服務,并將后端服務的響應返回給客戶端。在這個階段,API網關的功能非常簡單,主要用于解決客戶端和后端服務之間的通信問題。

  • API網關的成熟

隨著微服務架構的興起和API應用的不斷發展,企業開始將應用程序進一步拆分成更小的、獨立部署的微服務。每個對外暴露的微服務都有自己的API,并通過API網關進行統一管理和訪問。API網關在微服務架構中的作用變得更加重要,它的功能也逐漸豐富起來了。

在這一階段,它不僅負責路由和轉發請求,API網關還增加了安全和治理的功能,可以滿足幾個不同領域的微服務需求。比如:API網關可以通過身份認證、授權、訪問控制等功能來保護API的安全;通過基于重試、超時、熔斷的容錯機制等來對API的訪問進行治理;通過日志記錄、基于指標收集以及Tracing等對API的訪問進行觀測與監控;支持實時的服務發現等。

API網關(圖來自網絡)API網關(圖來自網絡)

  • API網關的云原生化

隨著云原生技術的發展,如容器化和服務網格(Service Mesh)等,API網關也在不斷演進和適應新的環境。在云原生環境中,API網關實現了與容器編排系統(如Kubernetes)和服務網格集成,其自身也可以作為一個云原生服務來部署,以實現更高的可伸縮性、彈性和自動化。同時,新的技術和標準也不斷涌現,如GraphQL和gRPC等,API網關也增加了對這些新技術的集成和支持。

1.2 API網關的主要功能特性

從上面的演化歷史我們看到:API網關的演進使其從最初簡單的請求轉發角色,逐漸成為整個API管理和微服務架構中的關鍵組件。它不僅扮演著API管理層與后端服務層之間的適配器,也是云原生架構中不可或缺的基礎設施,使微服務管理更加智能化和自動化。下面是現代API網關承擔的主要功能特性,我們后續也會基于這些特性進行示例說明:

  • 請求轉發和路由
  • 身份認證和授權
  • 流量控制和限速
  • 高可用與容錯處理
  • 監控和可觀測性

2. 那些主流的API網關

下面是來自CNCF Landscape[4]中的主流API網關集合(截至2023.11月),圖中展示了關于各個網關的一些細節,包括star數量和背后開發的公司或組織:

圖片圖片

主流的API網關還有各大公有云提供商的實現,比如:Amazon的API Gateway[5]、Google Cloud的API Gateway[6]以及上圖中的Azure API Management等,但它們不在我們選擇范圍之內;雖然被CNCF收錄,但多數API網關受到的關注并不高,超過1k star的不到30%,這些不是很受關注或dev不是那么active的項目也無法在生產環境擔當關鍵角色;而像APISIX[7]Kong[8]這兩個受關注很高的網關,它們是建構在Nginx之上實現的,技術棧與我們不契合;而像EMISSARY INGRESS[9]、Gloo等則是完全云原生化或者說是Kubernetes Native的,無法在無Kubernetes的基于VM或裸金屬的環境下部署和運行。

好吧,剩下的只有幾個Go實現的API Gateway了,在它們之中,我們選擇用Tyk API網關[10]來作為后續API功能演示的示例。

注:這并不代表Tyk API網關就要比其他Go實現的API Gateway優秀[11],只是它的資料比較齊全,適合在本文中作演示罷了。

3. API網關主要功能特性示例(Tyk API網關版本)

3.1 Tyk API網關簡介

記得在至少5年前就知道Tyk API網關[12]的存在,印象中它是使用Go語言開發的早期的那批API網關之一。Tyk從最初的純開源項目,到如今由背后商業公司支持,以Open Core模式開源[13]的網關,一直保持了active dev的狀態。經過多年的演進,它已經一款功能強大的開源兼商業API管理和網關解決方案[14],提供了全面的功能和工具,幫助開發者有效地管理、保護和監控API。同時,Tyk API網關支持多種安裝部署方式,即可以單一程序的方式放在物理機或VM上運行,也可以支持容器部署,通過docker-compose[15]拉起,亦可以通過Kubernetes Operator[16]將其部署在Kubernetes中,這也讓Tyk API網關具備了在各大公有云上平滑遷移的能力。

圖片圖片

關于Tyk API網關開源版本的功能詳情[17],可以點擊左邊超鏈接到其官網查閱,這里不贅述。

3.2 安裝Tyk API網關

下面我們就來安裝一下Tyk API網關,我們直接在VM上安裝,VM上的環境是CentOS 7.9。Tyk API提供了很多中安裝方法,這里使用CentOS的yum包管理工具安裝Tyk API網關[18],大體步驟如下(演示均以root權限操作)。

3.2.1 創建tyk gateway軟件源

默認的yum repo中是不包含tyk gateway的,我們需要在/etc/yum.repos.d下面創建一個新的源,即新建一個tyk_tyk-gateway.repo文件,其內容如下:

[tyk_tyk-gateway]
name=tyk_tyk-gateway
baseurl=https://packagecloud.io/tyk/tyk-gateway/el/7/$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/tyk/tyk-gateway/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300

[tyk_tyk-gateway-source]
name=tyk_tyk-gateway-source
baseurl=https://packagecloud.io/tyk/tyk-gateway/el/7/SRPMS
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/tyk/tyk-gateway/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300

接下來我們執行下面命令來創建tyk_tyk-gateway這個repo的YUM緩存:

$yum -q makecache -y --disablerepo='*' --enablerepo='tyk_tyk-gateway'
導入 GPG key 0x5FB83118:
 用戶ID     : "https://packagecloud.io/tyk/tyk-gateway (https://packagecloud.io/docs#gpg_signing) <support@packagecloud.io>"
 指紋       : 9179 6215 a875 8c40 ab57 5f03 87be 71bd 5fb8 3118
 來自       : https://packagecloud.io/tyk/tyk-gateway/gpgkey

repo配置和緩存完畢后,我們就可以安裝Tyk API Gateway了:

$yum install -y tyk-gateway

安裝后的tky-gateway將以一個systemd daemon服務[19]的形式存在于主機上,程序意外退出或虛機重啟后,該服務也會被systemd自動拉起。通過systemctl status命令可以查看服務的運行狀態:

# systemctl status tyk-gateway
● tyk-gateway.service - Tyk API Gateway
   Loaded: loaded (/usr/lib/systemd/system/tyk-gateway.service; enabled; vendor preset: disabled)
   Active: active (running) since 日 2023-11-19 20:22:44 CST; 12min ago
 Main PID: 29306 (tyk)
    Tasks: 13
   Memory: 19.6M
   CGroup: /system.slice/tyk-gateway.service
           └─29306 /opt/tyk-gateway/tyk --conf /opt/tyk-gateway/tyk.conf

11月 19 20:34:54 iZ2ze18rmx2avqb5xgb4omZ tyk[29306]: time="Nov 19 20:34:54" level=error msg="Connection to Redis faile...b-sub
11月 19 20:35:04 iZ2ze18rmx2avqb5xgb4omZ tyk[29306]: time="Nov 19 20:35:04" level=error msg="cannot set key in pollerC...ured"
11月 19 20:35:04 iZ2ze18rmx2avqb5xgb4omZ tyk[29306]: time="Nov 19 20:35:04" level=error msg="Redis health check failed...=main
Hint: Some lines were ellipsized, use -l to show in full.

3.2.2 安裝redis

我們看到tyk-gateway已經成功啟動,但從其服務日志來看,它在連接redis時報錯了!tyk gateway默認將數據存儲在redis中,為了讓tyk gateway正常運行,我們還需要安裝redis!這里我們使用容器的方式安裝和運行一個redis服務:

$docker pull redis:6.2.14-alpine3.18
$docker run -d --name my-redis -p 6379:6379 redis:6.2.14-alpine3.18 
e5d1ec8d5f5c09023d1a4dd7d31d293b2d7147f1d9a01cff8eff077c93a9dab7

拉取并運行redis后,我們通過redis-cli驗證一下與redis server的連接:

# docker run -it --rm redis:6.2.14-alpine3.18  redis-cli -h 192.168.0.24
192.168.0.24:6379>

我們看到可以正常連接!但此時Tyk Gateway仍然無法與redis正常連接,我們還需要對Tyk Gateway做一些配置調整!

3.2.3 配置Tyk Gateway

yum默認將Tyk Gateway安裝到/opt/tyk-gateway下面,這個路徑下的文件布局如下:

$tree -F -L 2 .
.
├── apps/
│   └── app_sample.json
├── coprocess/
│   ├── api.h
│   ├── bindings/
│   ├── coprocess_common.pb.go
│   ├── coprocess_mini_request_object.pb.go
│   ├── coprocess_object_grpc.pb.go
│   ├── coprocess_object.pb.go
│   ├── coprocess_response_object.pb.go
│   ├── coprocess_return_overrides.pb.go
│   ├── coprocess_session_state.pb.go
│   ├── coprocess_test.go
│   ├── dispatcher.go
│   ├── grpc/
│   ├── lua/
│   ├── proto/
│   ├── python/
│   └── README.md
├── event_handlers/
│   └── sample/
├── install/
│   ├── before_install.sh*
│   ├── data/
│   ├── init_local.sh
│   ├── inits/
│   ├── post_install.sh*
│   ├── post_remove.sh*
│   ├── post_trans.sh
│   └── setup.sh*
├── middleware/
│   ├── ottoAuthExample.js
│   ├── sampleMiddleware.js
│   ├── samplePostProcessMiddleware.js
│   ├── samplePreProcessMiddleware.js
│   ├── testPostVirtual.js
│   ├── testVirtual.js
│   └── waf.js
├── policies/
│   └── policies.json
├── templates/
│   ├── breaker_webhook.json
│   ├── default_webhook.json
│   ├── error.json
│   ├── monitor_template.json
│   └── playground/
├── tyk*
└── tyk.conf

其中tyk.conf就是tyk gateway的配置文件,我們先看看其默認的內容:

$cat /opt/tyk-gateway/tyk.conf
{
  "listen_address": "",
  "listen_port": 8080,
  "secret": "xxxxxx",
  "template_path": "/opt/tyk-gateway/templates",
  "use_db_app_configs": false,
  "app_path": "/opt/tyk-gateway/apps",
  "middleware_path": "/opt/tyk-gateway/middleware",
  "storage": {
    "type": "redis",
    "host": "redis",
    "port": 6379,
    "username": "",
    "password": "",
    "database": 0,
    "optimisation_max_idle": 2000,
    "optimisation_max_active": 4000
  },
  "enable_analytics": false,
  "analytics_config": {
    "type": "",
    "ignored_ips": []
  },
  "dns_cache": {
    "enabled": false,
    "ttl": 3600,
    "check_interval": 60
  },
  "allow_master_keys": false,
  "policies": {
    "policy_source": "file"
  },
  "hash_keys": true,
  "hash_key_function": "murmur64",
  "suppress_redis_signal_reload": false,
  "force_global_session_lifetime": false,
  "max_idle_connections_per_host": 500
}

我們看到:storage下面存儲了redis的配置信息,我們需要將redis的host配置修改為我們的VM地址:

"host": "192.168.0.24",

然后重啟Tyk Gateway服務:

$systemctl daemon-reload
$systemctl restart tyk-gateway

之后,我們再查看tyk gateway的運行狀態:

systemctl status tyk-gateway
● tyk-gateway.service - Tyk API Gateway
   Loaded: loaded (/usr/lib/systemd/system/tyk-gateway.service; enabled; vendor preset: disabled)
   Active: active (running) since 一 2023-11-20 06:54:07 CST; 41s ago
 Main PID: 20827 (tyk)
    Tasks: 15
   Memory: 24.8M
   CGroup: /system.slice/tyk-gateway.service
           └─20827 /opt/tyk-gateway/tyk --conf /opt/tyk-gateway/tyk.conf

11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="Loading API configurations...=main
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="Tracking hostname" api_nam...=main
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="Initialising Tyk REST API ...=main
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="API bind on custom port:0"...=main
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="Checking security policy: ...fault
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="API Loaded" api_id=1 api_n...ip=--
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="Loading uptime tests..." p...k-mgr
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="Initialised API Definition...=main
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=warning msg="All APIs are protected ...=main
11月 20 06:54:07 iZ2ze18rmx2avqb5xgb4omZ tyk[20827]: time="Nov 20 06:54:07" level=info msg="API reload complete" prefix=main
Hint: Some lines were ellipsized, use -l to show in full.

從服務日志來看,現在Tyk Gateway可以正常連接redis并提供服務了!我們也可以通過下面的命令驗證網關的運行狀態:

$curl localhost:8080/hello
{"status":"pass","version":"5.2.1","description":"Tyk GW","details":{"redis":{"status":"pass","componentType":"datastore","time":"2023-11-20T06:58:57+08:00"}}}

“/hello”是Tyk Gateway的內置路由,由Tyk網關自己提供服務。

到這里Tyk Gateway的安裝和簡單配置就結束了,接下來,我們就來看看API Gateway的主要功能特性,并借助Tyk Gateway來展示一下這些功能特性。

注:查看Tyk Gateway的運行日志,可以使用journalctl -u tyk-gateway -f命令實時follow最新日志輸出。

3.3 功能特性:請求轉發與路由

請求轉發和路由是API Gateway的主要功能特性之一,API Gateway可以根據請求的路徑、方法、查詢參數等信息將請求轉發到相應的后端服務,其內核與反向代理類似,不同之處在于API Gateway增加了“API”這層抽象,更加專注于構建、管理和增強API。

下面我們來看看Tyk如何配置API路由,我們首先創建一個新API。

3.3.1 創建一個新API

Tyk開源版支持兩種創建API的方式,一種是通過調用Tyk的控制類API[20],一種則是通過傳統的配置文件,放入特定目錄下[21]。無論哪種方式添加完API,最終都要通過Tyk Gateway熱加載(hot reload)或重啟才能生效。

注:Tyk Gateway的商業版本提供Dashboard,可以以圖形化的方式管理API,并且商業版本的API定義會放在Postgres或MongoDB中,我們這里用開源版本,只能手工管理了,并且API定義只能放在文件中。

下面,我們就來在Tyk上創建一個新的API路由,該路由示例的示意圖如下:

圖片圖片

在未添加新API之前,我們使用curl訪問一下該API路徑:

$curl localhost:8080/api/v1/no-authn
Not Found

Tyk Gateway由于找不到API路由,返回Not Found。接下來,我們采用調用tyk gateway API的方式來添加路由:

$curl -v -H "x-tyk-authorization: {tyk gateway secret}" \
  -s \
  -H "Content-Type: application/json" \
  -X POST \
  -d '{
    "name": "no-authn-v1",
    "slug": "no-authn-v1",
    "api_id": "no-authn-v1",
    "org_id": "1",   
    "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": "/api/v1/no-authn",
      "target_url": "http://localhost:18081/",
      "strip_listen_path": true
    },   
    "active": true
}' http://localhost:8080/tyk/apis | python -mjson.tool 

* About to connect() to localhost port 8080 (#0)
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> POST /tyk/apis HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:8080
> Accept: */*
> x-tyk-authorization: {tyk gateway secret}
> Content-Type: application/json
> Content-Length: 797
> 
} [data not shown]
* upload completely sent off: 797 out of 797 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Wed, 22 Nov 2023 05:38:40 GMT
< Content-Length: 53
< 
{ [data not shown]
* Connection #0 to host localhost left intact
{
    "action": "added",
    "key": "no-authn-v1",
    "status": "ok"
}

從curl返回結果我們看到:API已經被成功添加。這時tyk gateway的安裝目錄/opt/tyk-gateway的子目錄apps下會新增一個名為no-authn-v1.json的配置文件,這個文件內容較多,有300行,這里就不貼出來了,這個文件就是新增的no-authn API的定義文件[22]。

不過此刻,Tyk Gateway還需熱加載后才能為新的API提供服務,調用下面API可以觸發Tyk Gateway的熱加載:

$curl -H "x-tyk-authorization: {tyk gateway secret}" -s http://localhost:8080/tyk/reload/group | python -mjson.tool
{
    "message": "",
    "status": "ok"
}

注:即便觸發熱加載成功,但如果body中的json格式錯,比如多了一個結尾逗號,Tyk Gateway是不會報錯的!

API路由創建完畢并生效后,我們再來訪問一下API:

$ curl localhost:8080/api/v1/no-authn
{
    "error": "There was a problem proxying the request"
}

我們看到:Tyk Gateway返回的已經不是“Not Found”了!現在我們創建一下no-authn這個API服務,考慮到適配更多后續示例,這里建立這樣一個http server:

// api-gateway-examples/httpserver

func main() {    
    // 解析命令行參數   
    port := flag.Int("p", 8080, "Port number")  
    apiVersion := flag.String("v", "v1", "API version")  
    apiName := flag.String("n", "example", "API name")   
    flag.Parse()                                         
                                                         
    // 注冊處理程序                                     
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {  
        fmt.Println(*r)                                                  
        fmt.Fprintf(w, "Welcome api: localhost:%d/%s/%s\n", *port, *apiVersion, *apiName)  
    })                                                                                     
                                                                                           
    // 啟動HTTP服務器                                                                      
    addr := fmt.Sprintf(":%d", *port)  
    log.Printf("Server listening on port %d\n", *port)  
    log.Fatal(http.ListenAndServe(addr, nil))           
}

我們啟動一個該http server的實例:

$go run main.go -p 18081 -v v1 -n no-authn
2023/11/22 22:02:42 Server listening on port 18081

現在我們再通過tyk gateway調用一下no-authn這個API:

$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18081/v1/no-authn

我們看到這次路由通了!no-authn API返回了期望的結果!

3.3.2 負載均衡

如果no-authn API存在多個服務實例,Tyk Gateway也可以將請求流量負載均衡到多個no-authn服務實例上去,下圖是Tyk Gateway進行請求流量負載均衡[23]的示意圖:


要實現負責均衡,我們需要調整no-authn API的定義,這次我們直接修改/opt/tyk-gateway/apps/no-authn-v1.json,變更的配置主要有三項:

// /opt/tyk-gateway/apps/no-authn-v1.json

  "proxy": {
    "preserve_host_header": false,
    "listen_path": "/api/v1/no-authn",
    "target_url": "",                  // (1) 改為""
    "disable_strip_slash": false,
    "strip_listen_path": true,
    "enable_load_balancing": true,     // (2) 改為true
    "target_list": [                   // (3) 填寫no-authn服務實例列表
      "http://localhost:18081/",
      "http://localhost:18082/",
      "http://localhost:18083/"
    ],

修改完配置后,調用Tyk的控制類API使之生效,然后我們啟動三個no-authn的API實例:

$go run main.go -p 18081 -v v1 -n no-authn
$go run main.go -p 18082 -v v1 -n no-authn
$go run main.go -p 18083 -v v1 -n no-authn

接下來,我們多次調用curl訪問no-authn API:

$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18081/v1/no-authn
$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18082/v1/no-authn
$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18083/v1/no-authn

$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18081/v1/no-authn
$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18082/v1/no-authn
$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18083/v1/no-authn

我們看到:Tyk Gateway在no-authn API的各個實例之間做了等權重的輪詢。如果我們停掉實例3,再來訪問該API,我們將得到下面結果:

$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18081/v1/no-authn
$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18082/v1/no-authn
$curl localhost:8080/api/v1/no-authn
Bad Request

$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18081/v1/no-authn
$curl localhost:8080/api/v1/no-authn
Welcome api: localhost:18082/v1/no-authn
$curl localhost:8080/api/v1/no-authn
Bad Request

注:Tyk Gateway商業版通過Dashboard支持配置帶權重的RR負載均衡算法[24]。

我們看到:實例3已經下線,但Tyk Gateway并不會跳過該已經下線的實例,這在生產環境會給客戶端帶來不一致的響應。

3.3.3 服務實例存活檢測(uptime test)

Tyk Gateway在開啟負載均衡的時候,也提供了對后端服務實例的存活檢測機制,當某個服務實例down了后,負載均衡機制會繞過該實例將請求發到下一個處于存活狀態的實例;而當down機實例恢復后,Tyk Gateway也能及時檢測到服務實例上線,并將其加入流量負載調度。

支持存活檢測(uptime test)的API定義配置如下:

// /opt/tyk-gateway/apps/no-authn-v1.json

"uptime_tests": {
    "disable": false,
    "poller_group":"",
    "check_list": [
      {
        "url": "http://localhost:18081/"
      },
      {
        "url": "http://localhost:18082/"
      },
      {
        "url": "http://localhost:18083/"
      }
    ],
    "config": {
      "enable_uptime_analytics": true,
      "failure_trigger_sample_size": 3,
      "time_wait": 300,
      "checker_pool_size": 50,
      "expire_utime_after": 0,
      "service_discovery": {
        "use_discovery_service": false,
        "query_endpoint": "",
        "use_nested_query": false,
        "parent_data_path": "",
        "data_path": "",
        "port_data_path": "",
        "target_path": "",
        "use_target_list": false,
        "cache_disabled": false,
        "cache_timeout": 0,
        "endpoint_returns_list": false
      },
      "recheck_wait": 0
    }
}

"proxy": {
    ... ...
    "enable_load_balancing": true,
    "target_list": [
      "http://localhost:18081/",
      "http://localhost:18082/",
      "http://localhost:18083/"
    ],
    "check_host_against_uptime_tests": true,
    ... ...
}

我們新增了uptime_tests的配置,uptime_tests的check_list中的url的值要與proxy中target_list中的值完全一樣,這樣Tyk Gateway才能將二者對應上。另外proxy的check_host_against_uptime_tests要設置為true。

這樣配置并生效后,等我們將服務實例3停掉后,后續到no-authn的請求就只會轉發到實例1和實例2了。而當恢復實例3運行后,Tyk Gateway又會將流量分擔到實例3上。

3.3.4 動態負載均衡

上面負載均衡示例中target_list中的目標實例的IP和端口的手工配置的,而在云原生時代,我們經常會基于容器承載API服務實例,當容器因故退出,并重新啟動一個新容器時,IP可能會發生變化,這樣上述的手工配置就無法滿足要求,這就對API Gateway提出了與服務發現組件集成的要求:通過服務發現組件動態獲取服務實例的訪問列表,進而實現動態負載均衡[25]。

Tyk Gateway內置了主流服務發現組件(比如Etcd、Consul、ZooKeeper等)的對接能力,鑒于環境所限,這里就不舉例了,大家可以在Tyk Gateway的服務發現示例文檔頁面[26]找到與不同服務發現組件對接時的配置示例。

3.3.5 IP訪問限制

針對每個API,API網關還提供IP訪問限制的特性,比如Tyk Gateway就提供了IP白名單[27]IP黑名單[28]功能,通常二選一開啟一種限制即可。

以白名單為例,即凡是在白名單中的IP才被允許訪問該API。下面是白名單配置樣例:

// /opt/tyk-gateway/apps/no-authn-v1.json

  "enable_ip_whitelisting": true,
  "allowed_ips": ["12.12.12.12", "12.12.12.13", "12.12.12.14"],

生效后,當我們訪問no-authn API時,會得到下面錯誤:

$curl localhost:8080/api/v1/no-authn
{
    "error": "access from this IP has been disallowed"
}

如果開啟的是黑名單,那么凡是在黑名單中的IP都被禁止訪問該API,下面是黑名單配置樣例:

// /opt/tyk-gateway/apps/no-authn-v1.json

  "enable_ip_blacklisting": true,
  "blacklisted_ips": ["12.12.12.12", "12.12.12.13", "12.12.12.14", "127.0.0.1"],

生效后,當我們訪問no-authn API時,會得到如下結果:

$curl 127.0.0.1:8080/api/v1/no-authn
{
    "error": "access from this IP has been disallowed"
}

到目前為止,我們的API網關和定義的API都處于“裸奔”狀態,因為沒有對客戶端進行身份認證,任何客戶端都可以訪問到我們的API,顯然這不是我們期望的,接下來,我們就來看看API網關的一個重要功能特性:身份認證與授權。

3.4 功能特性:身份認證和授權

在《通過實例理解Go Web身份認證的幾種方式[29]》一文中,我們提到過:建立全局的安全通道是任何身份認證方式的前提

3.4.1 建立安全通道,卸載TLS證書

Tyk Gateway支持在Gateway層面統一配置TLS證書[30],同時也起到在Gateway卸載TLS證書的作用:

圖片圖片

這次我們要在tyk.conf中進行配置,才能在Gateway層面生效。這里我們借用《通過實例理解Go Web身份認證的幾種方式[31]》一文中生成的幾個證書(大家可以在https://github.com/bigwhite/experiments/tree/master/authn-examples/tls-authn/make_certs下載),并將它們放到/opt/tyk-gateway/certs/下面:

$ls /opt/tyk-gateway/certs/
server-cert.pem  server-key.pem

然后,我們在/opt/tyk-gateway/tyk.conf文件中增加下面配置:

// /opt/tyk-gateway/tyk.conf 

  "http_server_options": {
    "use_ssl": true,
    "certificates": [
      {
        "domain_name": "server.com",
        "cert_file": "./certs/server-cert.pem",
        "key_file": "./certs/server-key.pem"
      }
    ]
  }

之后,重啟tyk gateway服務,使得tyk.conf的配置修改生效。

注:在/etc/hosts中設置server.com為127.0.0.1。

現在我們用之前的http方式訪問一下no-authn的API:

$curl server.com:8080/api/v1/no-authn
Client sent an HTTP request to an HTTPS server.

由于全局啟用了HTTPS,采用http方式的請求將被拒絕。我們換成https方式訪問:

// 不驗證服務端證書
$curl -k https://server.com:8080/api/v1/no-authn
Welcome api: localhost:18081/v1/no-authn

// 驗證服務端的自簽證書
$curl --cacert ./inter-cert.pem https://server.com:8080/api/v1/no-authn
Welcome api: localhost:18081/v1/no-authn

3.4.2 Mutual TLS雙向認證

在《通過實例理解Go Web身份認證的幾種方式[32]》一文中,我們介紹的第一種身份認證方式就是TLS雙向認證,那么Tyk Gateway對MTLS的支持如何呢?Tyk官方文檔[33]提到它既支持client mTLS[34],也支持upstream mTLS[35]。

我們更關心的是client mTLS,即客戶端在與Gateway建連后,Gateway會使用Client CA驗證客戶端的證書!我最初認為這個Client CA的配置是在tyk.conf中,但找了許久,也沒有發現配置Client CA的地方。

在no-authn API的定義文件(no-authn-v1.json)中,我們做如下配置改動:

"use_mutual_tls_auth": true,
  "client_certificates": [
      "/opt/tyk-gateway/certs/inter-cert.pem"
  ],

但使用下面命令訪問API時報錯:

$curl --key ./client-key.pem --cert ./client-cert.pem --cacert ./inter-cert.pem https://server.com:8080/api/v1/no-authn
{
    "error": "Certificate with SHA256 bc8717c0f2ea5a0b81813abb3ec42ef8f9bf60da251b87243627d65fb0e3887b not allowed"
}

如果將"client_certificates"的配置中的inter-cert.pem改為client-cert.pem,則是可以的,但個人感覺這很奇怪,不符合邏輯,將tyk gateway的文檔、issue甚至代碼翻了又翻,也沒找到合理的配置client CA的位置。

Tyk Gateway支持多種身份認證方式[36],下面我們來看一種使用較為廣泛的方式:JWT Auth。

主要JWT身份認證方式的原理和詳情,可以參考我之前的文章《通過實例理解Go Web身份認證的幾種方式[37]》。

3.4.3 JWT Token Auth

下面是我為這個示例做的一個示意圖:

圖片圖片

這是我們日常開發中經常遇到的場景,即通過portal用用戶名和密碼登錄后便可以拿到一個jwt token,然后后續的訪問功能API的請求僅攜帶該jwt token即可。API Gateway對于portal/login API不做任何身份認證;而對后續的功能API請求,通過共享的secret(也稱為static secret)對請求中攜帶的jwt token進行簽名驗證。

portal/login API由于不進行authn,這樣其配置與前面的no-authn API幾乎一致,只是API名稱、路徑和target_list有不同:

// apps/portal-login-v1.json

{
  "name": "portal-login-v1",
  "slug": "portal-login-v1",
  "listen_port": 0,
  "protocol": "",
  "enable_proxy_protocol": false,
  "api_id": "portal-login-v1",
  "org_id": "1",
  "use_keyless": true,
  ... ...
  "proxy": {
    "preserve_host_header": false,
    "listen_path": "/api/v1/portal/login",
    "target_url": "",
    "disable_strip_slash": false,
    "strip_listen_path": true,
    "enable_load_balancing": true,
    "target_list": [
      "http://localhost:28084"
    ],
    "check_host_against_uptime_tests": true,
  ... ... 
}

對應的portal login API也不復雜:

// api-gateway-examples/portal-login/main.go

package main

import (
 "log"
 "net/http"
 "time"

 "github.com/golang-jwt/jwt/v5"
)

func main() {
 // 創建一個基本的HTTP服務器
 mux := http.NewServeMux()

 username := "admin"
 password := "123456"
 key := "iamtonybai"

 // for uptime test
 mux.HandleFunc("/health", func(w http.ResponseWriter, req *http.Request) {
  w.WriteHeader(http.StatusOK)
 })

 // login handler
 mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
  // 從請求頭中獲取Basic Auth認證信息
  user, pass, ok := req.BasicAuth()
  if !ok {
   // 認證失敗
   w.WriteHeader(http.StatusUnauthorized)
   return
  }

  // 驗證用戶名密碼
  if user == username && pass == password {
   // 認證成功,生成token
   token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
    "username": username,
    "iat":      jwt.NewNumericDate(time.Now()),
   })
   signedToken, _ := token.SignedString([]byte(key))
   w.Write([]byte(signedToken))
  } else {
   // 認證失敗
   http.Error(w, "Invalid username or password", http.StatusUnauthorized)
  }
 })

 // 監聽28084端口
 err := http.ListenAndServe(":28084", mux)
 if err != nil {
  log.Fatal(err)
 }
}

運行該login API服務后,我們用curl命令獲取一下jwt token:

$curl -u 'admin:123456' -k https://server.com:8080/api/v1/portal/login
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MDA3NTEyODEsInVzZXJuYW1lIjoiYWRtaW4ifQ.-wC8uPsLHDxSXcEMxIxJ8O2l3aWtWtWKvhtmuHmgIMA

現在我們再來建立protected API:

// apps/protected-v1.json

{
  "name": "protected-v1",
  "slug": "protected-v1",
  "listen_port": 0,
  "protocol": "",
  "enable_proxy_protocol": false,
  "api_id": "protected-v1",
  "org_id": "1",
  "use_keyless": false,    // 設置為false, gateway才會進行jwt的驗證
  ... ...
  "enable_jwt": true,      // 開啟jwt
  "use_standard_auth": false,
  "use_go_plugin_auth": false,
  "enable_coprocess_auth": false,
  "custom_plugin_auth_enabled": false,
  "jwt_signing_method": "hmac",        // 設置alg為hs256
  "jwt_source": "aWFtdG9ueWJhaQ==",    // 設置共享secret: base64("iamtonybai")
  "jwt_identity_base_field": "username", // 設置代表請求中的用戶身份的字段,這里我們用username
  "jwt_client_base_field": "",
  "jwt_policy_field_name": "",
  "jwt_default_policies": [
     "5e189590801287e42a6cf5ce"        // 設置security policy,這個似乎是jwt auth必須的
  ],
  "jwt_issued_at_validation_skew": 0,
  "jwt_expires_at_validation_skew": 0,
  "jwt_not_before_validation_skew": 0,
  "jwt_skip_kid": false,
  ... ...
  "version_data": {
    "not_versioned": true,
    "default_version": "",
    "versions": {
      "Default": {
        "name": "Default",
        "expires": "",
        "paths": {
          "ignored": null,
          "white_list": null,
          "black_list": null
        },
        "use_extended_paths": true,
        "extended_paths": {
          "persist_graphql": null
        },
        "global_headers": {
          "username": "$tyk_context.jwt_claims_username" // 設置轉發到upstream的請求中的header字段username
        },
        "global_headers_remove": null,
        "global_response_headers": null,
        "global_response_headers_remove": null,
        "ignore_endpoint_case": false,
        "global_size_limit": 0,
        "override_target": ""
      }
    }
  },
  ... ...
  "enable_context_vars": true, // 開啟上下文變量
  "config_data": null,
  "config_data_disabled": false,
  "tag_headers": ["username"], // 設置header
  ... ...
}

這個配置就相對復雜許多,也是翻閱了很長時間資料才驗證通過的配置。JWT Auth必須有關聯的policy設置,我們在tyk gateway開源版中要想設置policy,需要現在tyk.conf中做如下設置:

// /opt/tyk-gateway/tyk.conf

  "policies": {
    "policy_source": "file",
    "policy_record_name": "./policies/policies.json"
  },

而policies/policies.json的內容如下:

// /opt/tyk-gateway/policies/policies.json
{
 "5e189590801287e42a6cf5ce": {
  "rate": 1000,
  "per": 1,
  "quota_max": 100,
  "quota_renewal_rate": 60,
  "access_rights": {
   "protected-v1": {
    "api_name": "protected-v1",
    "api_id": "protected-v1",
    "versions": [
     "Default"
    ]
   }
  },
  "org_id": "1",
  "hmac_enabled": false
 }
}

上述設置完畢并重啟tyk gateway生效后,且protected api服務也已經啟動時,我們訪問一下該API服務:

$curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MDA3NTEyODEsInVzZXJuYW1lIjoiYWRtaW4ifQ.-wC8uPsLHDxSXcEMxIxJ8O2l3aWtWtWKvhtmuHmgIMA" -k https://server.com:8080/api/v1/protected
invoke protected api ok

我們看到curl發出的請求成功通過了Gateway的驗證!并且通過protected API輸出的請求信息來看,Gateway成功解析出username,并將其作為Header中的字段傳遞給了protected API服務實例:

http.Request{Method:"GET", URL:(*url.URL)(0xc0002f6240), Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"Accept":[]string{"*/*"}, "Accept-Encoding":[]string{"gzip"}, "Authorization":[]string{"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MDA3NTEyODEsInVzZXJuYW1lIjoiYWRtaW4ifQ.-wC8uPsLHDxSXcEMxIxJ8O2l3aWtWtWKvhtmuHmgIMA"}, "User-Agent":[]string{"curl/7.29.0"}, "Username":[]string{"admin"}, "X-Forwarded-For":[]string{"127.0.0.1"}}, Body:http.noBody{}, GetBody:(func() (io.ReadCloser, error))(nil), ContentLength:0, TransferEncoding:[]string(nil), Close:false, Host:"localhost:28085", Form:url.Values(nil), PostForm:url.Values(nil), MultipartForm:(*multipart.Form)(nil), Trailer:http.Header(nil), RemoteAddr:"[::1]:55583", RequestURI:"/", TLS:(*tls.ConnectionState)(nil), Cancel:(<-chan struct {})(nil), Response:(*http.Response)(nil), ctx:(*context.cancelCtx)(0xc0002e34f0)}

如果不攜帶Authorization頭字段或jwt的token是錯誤的,那么結果將如下所示:

$ curl -k https://server.com:8080/api/v1/protected
{
    "error": "Authorization field missing"
}

$ curl -k -H "Authorization: Bearer xxx" https://server.com:8080/api/v1/protected
{
    "error": "Key not authorized"
}

一旦通過API Gateway的身份認證,上游的API服務就會拿到客戶端身份,有了唯一身份后,就可以進行授權操作[38]了,其實policy設置本身也是一種授權訪問控制。Tyk Gateway自身也支持RBAC等模型[39],也支持與OPA(open policy agent)等的集成,但更多是在商業版的tyk dashboard下完成的,這里也就不重點說明了。

下面的Gateway的幾個主要功能特性由于試驗環境受限以及文章篇幅考量,我不會像上述例子這么細致的說明了,只會簡單說明一下。

3.5 功能特性:流量控制與限速

Tyk Gateway內置提供了強大的流量控制功能,可以通過全局級別和API級別的限速[40]來管理請求流量。此外,Tyk Gateway 還支持請求配額(request quota)[41]來限制每個用戶或應用程序在一個時間周期內的請求次數。

流量不僅和請求速度和數量有關系,與請求的大小也有關系,Tyk Gateway還支持在全局層面和API層面設置Request的size limit[42],以避免超大包對網關運行造成不良影響。

3.6 功能特性:高可用與容錯處理

在許多情況下,我們要為客戶確保服務水平(service level),比如:最大往返時間、最大響應時延等。Tyk Gateway提供了一系列功能,可幫助我們確保網關的高可用運行和SLA服務水平。

Tyk支持健康檢查[43],這對于確定Tyk Gateway的狀態極為重要,沒有健康檢查,就很難知道網關的實際運行狀態如何。

Tyk Gateway還內置了斷路器(circuit breaker)[44],這個斷路器是基于比例的,因此如果y個請求中的x請求都失敗了,斷路器就會跳閘,例如,如果x = 10,y = 100,則閾值百分比為10%。當失敗比例到達10%時,斷路器就會切斷流量,同時跳閘還會觸發一個事件,我們可以記錄和處理該事件。

當upstream的服務響應遲遲不歸時,Tyk Gateway還可以設置強制超時[45],可以確保服務始終在給定時間內響應。這在高可用性系統中非常重要,因為在這種系統中,響應性能至關重要,這樣才能干凈利落地處理錯誤。

3.7 功能特性:監控與可觀測性

微服務時代,可觀測性對運維以及系統高可用的重要性不言而喻。Tyk Gateway在多年的演化過程中,也逐漸增加了對可觀測的支持,

可觀測主要分三大塊:

  • log

Tyk Gateway支持設置輸出日志的級別(log level),默認是info級別。Tyk輸出的是結構化日志,這使得它可以很好的與其他日志收集查詢系統集成,Tyk支持與主流的日志收集工具對接[46],包括:logstash、sentry、Graylog、Syslog等。

  • metrics

度量數據是反映網關系統健康狀況、錯誤計數和類型、IT基礎設施(服務器、虛擬機、容器、數據庫和其他后端組件)及其他流程的硬件資源數據的重要參考。運維團隊可以通過使用監控工具來利用實時度量的數據[47],識別運行趨勢、在系統故障時設置警報、確定問題的根本原因并緩解問題。

Tyk Gateway內置了對主流metrics采集方案Prometheus+Grafana的支持[48],可以在網關層面以及對API進行實時度量數據采集和展示。


  • tracing

Tyk Gateway從5.2版本開始支持了與服務Tracing界的標準:OpenTelemetry的集成[49],這樣你可以使用多種支持OpenTelemetry的Tracing后端,比如Jaeger、Datadog等。Tracing可在Gateway層面開啟,也可以延展到API層面。

4. 小結

本文對已經相對成熟的API網關技術做了回顧,對API網關的演進階段、主流特性以及當前市面上的主流API網關進行了簡要說明,并以Go實現的Tyk Gateway社區開源版為例,以示例方式對API網關的主要功能做了介紹。

總體而言,Tyk Gateway是一款功能強大,社區相對活躍并有商業公司支持的產品,文檔很豐富,但從實際使用層面,這些文檔對Tyk社區版本的使用者來說并不友好,指導性不足(更多用商業版的Dashboard說明,與配置文件難于對應),就像本文例子中那樣,為了搞定JWT認證,筆者著實花了不少時間查閱資料,甚至閱讀源碼。

Tyk Gateway的配置設計平坦,沒有層次和邏輯,感覺是隨著時間隨意“堆砌”上去的。并且配置文件更新時,如果出現格式問題,Tyk Gateway并不報錯,讓人難于確定配置是否真正生效了,只能用Tyk Gateway的控制API[50]去查詢結果來驗證,非常繁瑣低效。

本文涉及的源碼可以在這里[51]下載,文中涉及的一些tyk gateway api和security policy的配置也可以在其中查看。

5. 參考資料

  • Leaving the Cloud[52] - https://37signals.com/podcast/leaving-the-cloud/
  • The Past, Present, and Future of API Gateways[53] - https://www.infoq.com/articles/past-present-future-api-gateways/
  • How moving from AWS to Bare-Metal saved us 230,000/yr[54] - https://blog.oneuptime.com/moving-from-aws-to-bare-metal/
  • A Comprehensive Guide to API Gateways, Kubernetes Gateways, and Service Meshes[55] - https://navendu.me/posts/gateway-and-mesh/
  • Use API gateways in microservices[56] - https://learn.microsoft.com/en-us/azure/architecture/microservices/design/gateway
  • The Tyk API Gateway and Postman[57] - https://blog.postman.com/the-tyk-api-gateway-and-postman/
  • Getting Started with Tyk API Gateway with Keycloak[58] - https://javascript.plainenglish.io/getting-started-to-tyk-api-gateway-with-keycloak-16307435584a
  • Observing your API traffic with Tyk, Elasticsearch & Kibana[59] - https://medium.com/@asoorm/observing-your-api-metrics-with-tyk-elasticsearch-kibana-74e8fd946c39
  • Set up JWT token in tyk gateway[60] - https://community.tyk.io/t/set-up-jwt-token-in-tyk-gateway/6572/9


參考資料

[1] David Heinemeier Hansson: https://dhh.dk/

[2] 將公司所有的業務都從公有云搬遷到了自建的數據中心: https://37signals.com/podcast/leaving-the-cloud/

[3] 以單體應用的形式存在: https://tonybai.com/2023/10/09/service-weaver-coding-in-monolithic-deploy-in-microservices/

[4] CNCF Landscape: https://https://landscape.cncf.io

[5] Amazon的API Gateway: https://aws.amazon.com/cn/api-gateway/

[6] Google Cloud的API Gateway: https://cloud.google.com/api-gateway

[7] APISIX: https://apisix.apache.org/

[8] Kong: https://konghq.com/

[9] EMISSARY INGRESS: https://github.com/emissary-ingress/emissary

[10] Tyk API網關: https://tyk.io/blog/res-api-management-vendor-comparisons/

[11] 不代表Tyk API網關就要比其他Go實現的API Gateway優秀: https://tyk.io/blog/enter-the-leader-tyk-recognised-as-a-leader-in-gartners-2023-magic-quadrant-for-api-management/

[12] Tyk API網關: https://github.com/TykTechnologies/tyk

[13] Open Core模式開源: https://opensource.com/article/21/11/open-core-vs-open-source

[14] 開源兼商業API管理和網關解決方案: https://tyk.io/docs/tyk-oss-gateway/

[15] docker-compose: https://tonybai.com/2021/11/26/build-all-in-one-runtime-environment-with-docker-compose

[16] Kubernetes Operator: https://tonybai.com/2022/08/15/developing-kubernetes-operators-in-go-part1

[17] Tyk API網關開源版本的功能詳情: https://tyk.io/docs/tyk-oss-gateway/

[18] 使用CentOS的yum包管理工具安裝Tyk API網關: https://tyk.io/docs/tyk-oss/ce-redhat-rhel-centos/

[19] systemd daemon服務: https://tonybai.com/2016/12/27/when-docker-meets-systemd/

[20] 調用Tyk的控制類API: https://tyk.io/docs/getting-started/create-api/#tutorial-create-an-api-with-the-tyk-gateway-api

[21] 通過傳統的配置文件,放入特定目錄下: https://tyk.io/docs/getting-started/create-api/#tutorial-create-an-api-in-file-based-mode

[22] API的定義文件: https://tyk.io/docs/tyk-gateway-api/api-definition-objects/

[23] 請求流量負載均衡: https://tyk.io/docs/planning-for-production/ensure-high-availability/load-balancing/

[24] 支持配置帶權重的RR負載均衡算法: https://tyk.io/docs/planning-for-production/ensure-high-availability/load-balancing/

[25] 動態負載均衡: https://tyk.io/docs/planning-for-production/ensure-high-availability/service-discovery/

[26] 服務發現示例文檔頁面: https://tyk.io/docs/planning-for-production/ensure-high-availability/service-discovery/examples/

[27] IP白名單: https://tyk.io/docs/tyk-apis/tyk-gateway-api/api-definition-objects/ip-whitelisting/

[28] IP黑名單: https://tyk.io/docs/tyk-apis/tyk-gateway-api/api-definition-objects/ip-blacklisting/

[29] 通過實例理解Go Web身份認證的幾種方式: https://tonybai.com/2023/10/23/understand-go-web-authn-by-example

[30] 統一配置TLS證書: https://tyk.io/docs/basic-config-and-security/security/tls-and-ssl/

[31] 通過實例理解Go Web身份認證的幾種方式: https://tonybai.com/2023/10/23/understand-go-web-authn-by-example/

[32] 通過實例理解Go Web身份認證的幾種方式: https://tonybai.com/2023/10/23/understand-go-web-authn-by-example

[33] Tyk官方文檔: https://tyk.io/docs/basic-config-and-security/security/mutual-tls/

[34] client mTLS: https://tyk.io/docs/basic-config-and-security/security/mutual-tls/client-mtls

[35] upstream mTLS: https://tyk.io/docs/basic-config-and-security/security/mutual-tls/upstream-mtls

[36] Tyk Gateway支持多種身份認證方式: https://tyk.io/docs/apim-best-practice/api-security-best-practice/authentication/

[37] 通過實例理解Go Web身份認證的幾種方式: https://tonybai.com/2023/10/23/understand-go-web-authn-by-example/

[38] 授權操作: https://tonybai.com/2023/11/04/understand-go-web-authz-by-example/

[39] 支持RBAC等模型: https://tyk.io/docs/tyk-dashboard/rbac/#understanding-the-concept-of-users-and-permissions

[40] 全局級別和API級別的限速: https://tyk.io/docs/basic-config-and-security/control-limit-traffic/rate-limiting/

[41] 支持請求配額(request quota): https://tyk.io/docs/basic-config-and-security/control-limit-traffic/request-quotas/

[42] 設置Request的size limit: https://tyk.io/docs/basic-config-and-security/control-limit-traffic/request-size-limits/

[43] Tyk支持健康檢查: https://tyk.io/docs/planning-for-production/ensure-high-availability/health-check/

[44] 內置了斷路器(circuit breaker): https://tyk.io/docs/planning-for-production/ensure-high-availability/circuit-breakers/

[45] 設置強制超時: https://tyk.io/docs/planning-for-production/ensure-high-availability/enforced-timeouts/

[46] Tyk支持與主流的日志收集工具對接: https://tyk.io/docs/log-data/#logging

[47] 使用監控工具來利用實時度量的數據: https://tyk.io/docs/planning-for-production/monitoring/

[48] 對主流metrics采集方案Prometheus+Grafana的支持: https://tyk.io/blog/service-level-objectives-for-your-apis-with-tyk-prometheus-and-grafana/

[49] 支持了與服務Tracing界的標準:OpenTelemetry的集成: https://tyk.io/docs/product-stack/tyk-gateway/advanced-configurations/distributed-tracing/open-telemetry/open-telemetry-overview/

[50] Tyk Gateway的控制API: https://tyk.io/docs/tyk-gateway-api/

[51] 這里: https://github.com/bigwhite/experiments/tree/master/api-gateway-examples

[52] Leaving the Cloud: https://37signals.com/podcast/leaving-the-cloud/

[53] The Past, Present, and Future of API Gateways: https://www.infoq.com/articles/past-present-future-api-gateways/

[54] How moving from AWS to Bare-Metal saved us 230,000/yr: https://blog.oneuptime.com/moving-from-aws-to-bare-metal/

[55] A Comprehensive Guide to API Gateways, Kubernetes Gateways, and Service Meshes: https://navendu.me/posts/gateway-and-mesh/

[56] Use API gateways in microservices: https://learn.microsoft.com/en-us/azure/architecture/microservices/design/gateway

[57] The Tyk API Gateway and Postman: https://blog.postman.com/the-tyk-api-gateway-and-postman/

[58] Getting Started with Tyk API Gateway with Keycloak: https://javascript.plainenglish.io/getting-started-to-tyk-api-gateway-with-keycloak-16307435584a

[59] Observing your API traffic with Tyk, Elasticsearch & Kibana: https://medium.com/@asoorm/observing-your-api-metrics-with-tyk-elasticsearch-kibana-74e8fd946c39

[60] Set up JWT token in tyk gateway: https://community.tyk.io/t/set-up-jwt-token-in-tyk-gateway/6572/9

[61] “Gopher部落”知識星球: https://public.zsxq.com/groups/51284458844544

[62] 鏈接地址: https://m.do.co/c/bff6eed92687


責任編輯:武曉燕 來源: TonyBai
相關推薦

2011-11-16 09:59:50

私有云云存儲

2009-12-22 09:41:15

無線路由器

2010-06-30 11:04:41

SNMP協議網絡管理

2010-04-26 16:51:11

Oracle Deco

2010-03-05 13:53:38

Python Thre

2010-06-01 10:52:14

IPv6交換中心

2025-02-05 07:00:00

Next.jsWeb前端

2019-10-31 09:14:27

物聯網網關物聯網IOT

2016-02-19 10:03:30

蘋果支付Apple Pay

2010-06-24 13:57:57

Linux Cat命令

2009-12-03 13:55:10

路由器主要功能

2016-12-02 16:00:22

服務器托管機柜

2010-03-03 13:50:40

Python文件

2010-01-14 17:46:29

智能交換機

2009-03-08 09:15:09

Windows 7微軟功能禁用

2009-11-20 16:33:02

備份路由器

2014-12-22 10:39:44

虛擬化云平臺PaaS

2010-02-22 16:09:18

骨干交換機

2009-07-07 13:45:52

JDK日志框架

2009-11-09 10:51:46

點贊
收藏

51CTO技術棧公眾號

国产女人18毛片水真多| www.日本高清视频| 亚洲国产欧美日本视频| 国产亚洲综合在线| 亚洲一区中文字幕在线观看| 日本一区二区免费在线观看| 欧美三级三级| 欧美va在线播放| 女人另类性混交zo| 国产网站在线免费观看| av电影天堂一区二区在线观看| 国产精品国内视频| 日本亚洲欧美在线| 久久伦理在线| 日韩av在线免播放器| 亚洲欧美偷拍另类| 亚洲欧美韩国| 亚洲在线中文字幕| 亚洲一区二区三区加勒比 | 久久久久亚洲av片无码| 人人精品视频| 日韩欧美一区二区久久婷婷| 嫩草av久久伊人妇女超级a| 性欧美高清come| 中文一区一区三区高中清不卡| 国产免费一区| 国产肥老妇视频| 美女脱光内衣内裤视频久久网站| 91国语精品自产拍在线观看性色 | 国产麻豆乱码精品一区二区三区 | 精品伊人久久97| 午夜影院免费观看视频| 日韩免费小视频| 午夜电影网亚洲视频| 精品一区二区三区毛片| 午夜视频在线| 国产视频一区二区三区在线观看| 精品麻豆av| 亚洲成人久久精品| 国产成人av影院| 91亚洲精品久久久久久久久久久久| 亚洲欧美一二三区| 午夜在线观看免费一区| 国模精品一区二区三区色天香| 四虎永久免费在线| 久久香蕉国产| 最近2019中文字幕一页二页| 99久久久无码国产精品衣服| 中文字幕伦av一区二区邻居| 国产网站欧美日韩免费精品在线观看| 69xxx免费视频| 91夜夜蜜桃臀一区二区三区| 日韩欧美国产高清| 性猛交╳xxx乱大交| 2020国产精品极品色在线观看| 日韩美女视频一区二区在线观看| 国产精品999.| 亚洲一区二区三区中文字幕在线观看| 3atv在线一区二区三区| 亚洲一区二区中文字幕在线观看| 亚洲综合资源| 日韩女优制服丝袜电影| 无码国产精品一区二区高潮| 欧美另类中文字幕| 亚洲成avwww人| 69亚洲乱人伦| 中文精品一区二区| 一本一本久久a久久精品综合小说| 九色porny自拍视频| 欧美热在线视频精品999| 亚洲视频视频在线| 久久久久99精品成人| 欧美第一精品| 久久久精品国产| 国产探花在线免费观看| 韩国一区二区三区在线观看| 国内精品久久久久影院 日本资源| 日韩成人免费在线观看| 午夜一级久久| 成人xvideos免费视频| 国产黄色片免费| 成人av电影在线播放| 欧美xxxx黑人又粗又长精品| 草碰在线视频| 亚洲精品写真福利| 国产成人无码a区在线观看视频| 欧美裸体视频| 欧美日韩精品一区二区三区四区| 久久精品国产露脸对白| aaa国产精品视频| 亚洲开心激情网| 色撸撸在线视频| 在线观看不卡| 国产精品扒开腿做| 999久久久久久| www精品美女久久久tv| 一本久道久久综合| 波多野结衣在线播放| 在线观看视频一区二区欧美日韩| 一个人看的视频www| 欧美影院天天5g天天爽| 色综合伊人色综合网站| 久久免费黄色网址| 青娱乐精品视频| 国产高清自拍99| 成人一区二区不卡免费| 亚洲一区中文日韩| 亚洲综合日韩欧美| 久久悠悠精品综合网| 久久精品2019中文字幕| 日韩欧美大片在线观看| 久久www免费人成看片高清| 精品亚洲第一| 日韩另类在线| 欧美三级韩国三级日本三斤| 欧美肉大捧一进一出免费视频| 日韩理论片av| 欧美在线视频网站| 亚洲av无码专区在线| 欧美高清在线视频| 人妻有码中文字幕| 成人免费在线电影网| 日韩视频一区在线| 国产熟妇一区二区三区四区| 成人国产精品免费| 黄色网zhan| 国模私拍国内精品国内av| 亚洲精品美女在线| 国产一级av毛片| 国产真实乱对白精彩久久| 日本中文不卡| 一区二区三区电影大全| 亚洲国产成人久久综合一区| 欧美交换国产一区内射| 麻豆91在线播放| 日本一区二区精品| 在线免费看h| 日韩精品在线观看一区| 久久久久久久久久99| 韩国三级电影一区二区| 一本一生久久a久久精品综合蜜| 亚洲伊人av| 日韩高清有码在线| 日韩熟女精品一区二区三区| 懂色av噜噜一区二区三区av| 亚洲爆乳无码精品aaa片蜜桃| 亚洲一区二区av| 久久人人爽亚洲精品天堂| 一级日韩一级欧美| 国产精品久久久久精k8| 男人添女人下面免费视频| jiujiure精品视频播放| 国产精品av免费在线观看| 九色蝌蚪在线| 欧美在线小视频| wwwww黄色| 老司机免费视频一区二区三区| 色爱区成人综合网| www.26天天久久天堂| 日韩在线观看你懂的| 亚洲永久精品视频| 亚洲摸摸操操av| 永久免费看片在线观看| 一区视频在线| 久久综合一区二区三区| 暖暖成人免费视频| 中文字幕国产亚洲| 国产乱码久久久| 一区二区不卡在线视频 午夜欧美不卡在| 免费黄频在线观看| 欧美激情日韩| 久久精品magnetxturnbtih| 中文在线8资源库| 亚洲欧美三级在线| 97精品人妻一区二区三区在线| 亚洲男女毛片无遮挡| 久草视频福利在线| 日韩精品欧美精品| 好色先生视频污| 给我免费播放日韩视频| 热草久综合在线| 日本在线视频站| 亚洲爱爱爱爱爱| 亚洲视屏在线观看| 一区二区三区四区国产精品| av无码av天天av天天爽| 奇米一区二区三区av| 国产女教师bbwbbwbbw| 美女视频亚洲色图| 国产精品视频自在线| 欧美性爽视频| 中文亚洲视频在线| 高h放荡受浪受bl| 91激情在线视频| 欧美成人三级在线观看| 久久精品夜色噜噜亚洲aⅴ| 网站在线你懂的| 久久精品亚洲| 日本三级中文字幕在线观看| 国产在线拍揄自揄拍无码视频| 国模无码视频一区| 亚洲免费二区| 裸体丰满少妇做受久久99精品| 日本国产亚洲| 欧美中文字幕第一页| av网址在线免费观看| 国产丝袜一区二区| www.中文字幕| 欧美日韩一区不卡| av资源免费观看| 亚洲男人的天堂在线aⅴ视频| 黑人巨大精品欧美| 成人自拍视频在线观看| 少妇一级淫免费播放| av成人黄色| 四虎永久免费网站| 精品久久久久久久| 精品国产一区二区三区麻豆小说| 99久久这里有精品| 国产精品看片资源| 亚洲天堂电影| 久久免费国产视频| 成人三级网址| 中文字幕一区二区精品| 黄色av网站在线免费观看| 亚洲国产成人精品久久久国产成人一区 | 欧美一区二区三区精品电影| 99视频免费在线观看| 色午夜这里只有精品| 美州a亚洲一视本频v色道| 精品福利一二区| 性一交一乱一精一晶| 这里只有精品电影| 国产又黄又粗又长| 欧美午夜一区二区| 精品久久久久久久久久久久久久久久久久 | 精品国产伦一区二区三区免费| 91麻豆成人精品国产免费网站| 欧美亚洲综合久久| 免费黄色片视频| 欧美日韩一区二区免费视频| 日韩欧美高清在线观看| 亚洲一区二区三区四区的| 日本一级二级视频| 亚洲精品v日韩精品| 欧美日韩中文字幕在线观看| 亚洲人妖av一区二区| 美国黄色片视频| 日韩一区中文字幕| 老熟妻内射精品一区| 亚洲男同1069视频| 免费视频网站www| 一级日本不卡的影视| 国产在线观看99| 午夜不卡在线视频| 精品黑人一区二区三区| 欧美私模裸体表演在线观看| 中文字幕永久免费视频| 欧美日本不卡视频| 国产免费高清av| 日韩免费观看高清完整版| 国产黄色片网站| 亚洲国产私拍精品国模在线观看| 天天爱天天干天天操| 亚洲人成网7777777国产| av在线三区| 超碰精品一区二区三区乱码| 美女网站视频在线| 国语自产精品视频在免费| 亚洲一级少妇| 成人精品在线观看| 2020国产精品极品色在线观看| 精品欧美国产| 禁断一区二区三区在线| 在线不卡日本| 最新亚洲一区| 免费在线观看的毛片| 久久精品999| 佐佐木明希电影| wwwwww.欧美系列| 大吊一区二区三区| 一区二区三区久久| 69视频免费在线观看| 欧美色区777第一页| 成人免费观看在线视频| 亚洲精品视频网上网址在线观看| www.在线视频.com| 久久久久国色av免费观看性色 | 国产精品自产拍高潮在线观看| 欧美日本三级| 美女视频久久| 亚洲国产日韩欧美在线| 欧美亚洲国产成人| 激情文学综合插| 中国美女乱淫免费看视频| 亚洲欧美日韩人成在线播放| 国产精品视频免费播放| 正在播放亚洲一区| 免费在线国产| 欧美丰满少妇xxxx| jizz欧美| 久久av一区二区三区亚洲| 欧美疯狂party性派对| 亚洲熟妇av日韩熟妇在线| 精品一区二区免费在线观看| 国产偷人妻精品一区| 亚洲精品国产精品乱码不99 | 国产第一页在线视频| 国产日韩换脸av一区在线观看| 特黄特色欧美大片| 成人免费观看在线| 久久99久久99精品免视看婷婷| 久久久久久久久免费看无码| 一区二区视频在线| 在线观看视频二区| 亚洲精品在线视频| 爱福利在线视频| 91精品在线国产| 成人高清av| 激情综合网婷婷| 99re视频这里只有精品| 欧美成人三级视频| 欧美一区二区三区在线电影| 国产大片在线免费观看| 2019中文字幕在线观看| 成人h动漫免费观看网站| 国产精品99久久久久久大便| 免费国产亚洲视频| 免费看黄色的视频| 欧美日韩国产区| 人妻91麻豆一区二区三区| 欧美精品免费在线| 国内不卡的一区二区三区中文字幕| 日韩欧美在线一区二区| 性久久久久久| 魔女鞋交玉足榨精调教| 午夜电影一区二区三区| 日本免费网站在线观看| 久久久久久久久久久人体| 欧美一区在线观看视频| 国产精品无码乱伦| 精品一区二区三区免费视频| av片在线免费看| 欧美日韩激情一区二区三区| gogogo高清在线观看免费完整版| 国产成人综合精品在线| 亚洲毛片免费看| 国产aaa一级片| 久久婷婷久久一区二区三区| 男人天堂2024| 亚洲偷欧美偷国内偷| 性感美女一区二区在线观看| 欧美精品尤物在线| 日韩精品一卡二卡三卡四卡无卡| 亚洲AV无码成人精品区明星换面 | 99久久精品无免国产免费| 久久九九热免费视频| 久久视频免费| 久久久亚洲国产精品| 99精品欧美一区| 美女又爽又黄免费视频| 亚洲天堂av在线播放| 国产精品第一国产精品| 综合久久国产| 国产成人av影院| 中日韩黄色大片| 国产亚洲成av人片在线观看桃| 成人一区视频| 免费看污污视频| 成人av高清在线| 波多野结衣黄色网址| 日韩小视频在线| 欧美成年网站| 男人天堂999| 中文字幕欧美激情一区| 国产三级自拍视频| 国内精品小视频在线观看| 欧美日本成人| 黄色片免费网址| 精品国产户外野外| av在线中文| 成人18视频| 久久中文欧美| 国产免费美女视频| 亚洲黄一区二区| 欧美黑粗硬大| 久久国产精品网| 国产精品另类一区| 农村少妇久久久久久久| 国产精品久久久久久久久久久久久久 | 国产一级免费观看| 亚洲欧美精品在线| 激情综合婷婷| 国产a级片免费观看| 一区二区三区在线免费视频| 日本一卡二卡四卡精品| 亚洲精品日韩激情在线电影| 亚洲综合日韩| 欧洲第一无人区观看| 亚洲免费高清视频|