微服務Kong(八)——代理參考


Kong偵聽四個端口的請求,默認情況是:

  8000:此端口是Kong用來監聽來自客戶端的HTTP請求的,並將此請求轉發到您的上游服務。這也是本教程中最主要用到的端口。

  8443:此端口是Kong監聽HTTP的請求的端口。該端口具有與8000端口類似的行為,但是它只監聽HTTPS的請求,並不會產生轉發行為。可以通過配置文件來禁用此端口。

  8001:用於管理員對KONG進行配置的端口。

  8444:用於管理員監聽HTTPS請求的端口。

  在本文中,我們將介紹Kong的路由功能,並詳細說明8000端口上的客戶端請求如何根據請求頭、URI或HTTP被代理到配置中的上游服務。

 

基礎術語

  API:指Kong的API實例。您可以通過管理員身份配置您的API。

  Plugin:他指的是Kong的“插件”,它們是在代理生命周期中運行的業務邏輯。可以通過管理員身份進行全局配置,也可針對每個API進行分別配置。

  Client:指向Kong的代理端口發出請求的下游客戶,即第三方客戶端。

  Upstream service:指的是位於Kong后面的您自己的API服務,客戶端請求被轉發的最終目的地。nginx中的上游服務器。

 

概述

  從整體上來看,Kong偵聽其配置的代理端口上的HTTP請求(默認為8000),並識別正在請求的是哪個上游服務,然后運行在該API上的配置插件(如果沒有則不執行),並將上游的HTTP請求轉發到您自己的API服務。

  當客戶端向代理端口發出請求時,Kong將根據API在KONG里的配置情況,來決定將請求傳入到哪個上游服務中。 您可以在KONG里對每個API添加許多屬性,但是有三個是必須要配置的,他們是hosts、uris和methods。如果KONG無法確定API請求的上游服務地址,則會返回一下內容:

HTTP/1.1 404 Not Found
Content-Type: application/json
Server: kong/<x.x.x>

{
    "message": "no API found with those values"
}

回憶下:如何向KONG添加一個API

    在之前的添加一個API的指南中,有學習過如何使用8001端口,在KONG服務中添加一個API的操作:

$ curl -i -X POST http://localhost:8001/apis/ \
    -d 'name=my-api' \
    -d 'upstream_url=http://my-api.com' \
    -d 'hosts=example.com' \
    -d 'uris=/my-api' \
    -d 'methods=GET,HEAD'
HTTP/1.1 201 Created
...

    該代碼表示用戶成功在Kong里注冊一個名為“my-api”的API,可通過訪問“http://example.com”發送請求。它還指定了一些HTTP請求的屬性,但請注意,這里有且只有一個HOST,URIS和METHODS屬性。當完成此配置后,以后所有的符合此host、uris和methods的請求,都將由KONG來代理過濾轉發。Kong是一個透明的代理,它會將請求轉發給您的上游服務,除了添加諸如Connection之類的各種標題。

 

轉發功能

    現在我們來討論一下,一個HTTP請求是如何與API配置屬性(如host、uris、methods)相匹配的。需要注意的是,這三個字段(h、u、m)都是可選的,但至少要有一個被指定。對於客戶端請求與API的匹配:

    · 請求必須包含所有已配置的字段

    · 請求中的字段值必須與至少一個已配置的值相匹配(盡管字段配置接受一個或多個值,請求只需要考慮匹配其中之一)

    讓我們來看幾個例子。請看如下一個API配置:

{
    "name": "my-api",
    "upstream_url": "http://my-api.com",
    "hosts": ["example.com", "service.com"],
    "uris": ["/foo", "/bar"],
    "methods": ["GET"]
}

    與該API相匹配的一些請求可能是:

GET /foo HTTP/1.1
Host: example.com

GET /bar HTTP/1.1
Host: service.com

GET /foo/hello/world HTTP/1.1
Host: example.com

    以上的三個請求都滿足API定義中設置的條件。但是,以下的幾個請求則與配置的條件不匹配:

GET / HTTP/1.1
Host: example.com

POST /foo HTTP/1.1
Host: example.com

GET /foo HTTP/1.1
Host: foo.com

    以上的三個請求只滿足兩個配置條件。第一個請求的URI不匹配,第二個請求的HTTP方法不匹配,第三個請求的Host頭不匹配。

    現在我們了解了hosts、uris、methods是如何一起工作的。下面我們來逐個了解他們是如何單獨工作的。

    1. 請求的HOST頭:

      基於HOST頭發送請求,是通過KONG發送請求的最直接的一種方式,這也是HOST頭的基本用法之一。KONG使通過HOST訪問API實體的流程更加簡便快捷。HOSTS 接受多種參數,當使用管理員API進行請求時,需要將每個參數間用逗號分隔開來配置:

$ curl -i -X POST http://localhost:8001/apis/ \
    -d 'name=my-api' \
    -d 'upstream_url=http://test-api.com' \
    -d 'hosts=test-api.com,demo.com,service.com'
HTTP/1.1 201 Created
...

此時,客戶端可使用 hosts=test-api.com, demo.com, service.com 中的任意一個HOST頭對 my-api 進行訪問,但不能缺省HOST的值。

    1.1 使用通配符查找主機名

  為了使代理更靈活,KONG允許使用通配符來配置HOSTS。通配符允許任何滿足條件的HOST頭對API實體進行訪問。在配置通配符時,只允許在HOST的最左或最右配置一個星號(*),例如:

*.example.com :允許類似於 a.example.com 或 a.b.example.com 等形式的HOST頭訪問。
example.*   :允許類似於 example.a 或 example.b.cn 等形式的HOST頭訪問。

  一個完整的例子:

{
    "name": "test-api",
    "upstream_url": "http://test-api.com",
    "hosts": ["*.example.com", "service.com"]
}

  匹配的HOST頭請求類似於一下幾種,但不限於一下的例子中的形式:

GET / HTTP/1.1
Host: an.example.com

GET / HTTP/1.1
Host: service.com

    1.2. preserve_host屬性

      當啟用代理時,KONG默認將API的 upstream_url 的值配置為上游服務主機的 host 。preserve_host提供一個boolean值,對KONG的這個行為進行限制。例如,當使用preserve_host的默認值進行配置時,API的配置信息大致為:

{
    "name": "my-api",
    "upstream_url": "http://my-api.com",
    "hosts": ["service.com"],
}

此時,客戶端發送的請求信息格式大致為:

GET / HTTP/1.1
Host: service.com

KONG會從API的upstream_url中提取HOST值,在做代理時,會向上游服務發送類似的請求:

GET / HTTP/1.1
Host: my-api.com

然而,當管理員在配置API時,明確指定了preserver_host=true時:

{
    "name": "my-api",
    "upstream_url": "http://my-api.com",
    "hosts": ["service.com"],
    "preserve_host": true
}

並假設客戶端發送了相同的請求:

GET / HTTP/1.1
Host: service.com

KONG將會保留客戶端發送來的HOST值,在做代理時,會向上游服務發送以下的請求:

GET / HTTP/1.1
Host: service.com

     2 請求URI

       KONG將請求轉發給上游服務的另一種方式,是通過配置uris屬性來指定請求的URI值。uris可以配置多個值,此時客戶端在進行請求時,必須選擇uris中的一個值作為請求的前綴。

  例如,如果API的配置為:

{
    "name": "my-api",
    "upstream_url": "http://my-api.com",
    "uris": ["/service", "/hello/world"]
}

  以下的幾種請求方式都可以對此API進行訪問:

GET /service HTTP/1.1
Host: my-api.com

GET /service/resource?param=value HTTP/1.1
Host: my-api.com

GET /hello/world/resource HTTP/1.1
Host: anything.com

  以上幾種方式在進行請求時,KONG偵測到他們的前綴與API的uris屬性值是匹配的,所以這些請求是可用的。

  當uris屬性配置好后,在進行請求時,KONG首先會取最長的uris值對URI進行匹配篩選,如果未匹配,然后才會取次長度的uris值進行匹配,依次類推,直到匹配成功為止或拒絕訪問。譬如上面的例子里,在發送請求時,KONG首先會取 `/hello/world` 與請求uri進行匹配,如果未成功,才會繼續取 `/service` 繼續匹配工作。

    2.1 strip_uri屬性

      在配置API的uris時,如果你希望隱藏上游服務的真實uri,並以另外的一種URI提供給客戶端時,通過簡單的配置API的strip_uri屬性就可以實現。例如:

{
    "name": "my-api",
    "upstream_url": "http://my-api.com",
    "uris": ["/service"],
    "strip_uri": true
}

  啟用strip_uri屬性來指示Kong在代理此API時,在上游請求的URI中不應包含匹配的URI前綴。針對上面的API配置,當客戶端發送請求時

GET /service/path/to/resource HTTP/1.1
Host:

  KONG代理到上游服務的真實uri為(此時的uri不包含uris中配置的內容)

GET /path/to/resource HTTP/1.1
Host: my-api.com

    3. HTTP請求方法

      從KONG 0.10版本開始,可以通過配置API的methods屬性來指定客戶端的請求。默認情況下,無論HTTP請求方式如何,Kong都會將請求將其代理到API的。但是,當配置methods屬性后,只有HTTP請求方式匹配時才會被KONG代理。methods屬性可以配置多個值:

{
    "name": "api-1",
    "upstream_url": "http://my-api.com",
    "methods": ["GET", "HEAD"]
}

  以下的兩種HTTP請求方式都可以被代理

GET / HTTP/1.1
Host:

HEAD /resource HTTP/1.1
Host:

  但是不會匹配POST或DELETE等其他的請求方式。配置此屬性,可以更細粒度的管理你的API。

 

代理的優先級

      一個API可以通過配置hosts、uris和methods屬性定義匹配規則。對於Kong來說,只有當所有的字段都匹配時,才會進行轉發。然而,KONG允許兩個或更多的API擁有相同的配置。此時,就涉及到請求的優先級問題了。

    匹配優先級原則是:在評估請求時,Kong會首先與匹配規則最多的API進行匹配(when evaluating a request, Kong will first try to match the APIs with the most rules.)。例如有兩個API的配置如下

{
    "name": "api-1",
    "upstream_url": "http://my-api.com",
    "hosts": ["example.com"]
},

{
    "name": "api-2",
    "upstream_url": "http://my-api-2.com",
    "hosts": ["example.com"],
    "methods": ["POST"]
}

  api-2比api-1多了一個methods配置,所以KONG會最先將請求與api-2進行匹配。通過此配置,我們就能避免在請求api-2時,錯誤的轉發到api-1。

此時,這個請求會被轉發到api-1:

GET / HTTP/1.1
Host: example.com

而這個請求,會被轉發到api-2:

POST / HTTP/1.1
Host: example.com

  以此類推,如果一個api同時配置了hosts、methods、uris,則這個API會最先與請求進行匹配,他的優先級會是三個中最高的。

 

代理行為

  上述內容詳細講述了KONG將請求代理到上游服務的代理規則。下面我們將詳細說明,在KONG將請求轉發到上游服務的這段時間內實際發生的一些事。

  1. 負載平衡

    從KONG 1.10 版本開始,Kong繼承實現了負載平衡的功能,可以將轉發的請求分發到多個上游服務實例。在 Kong 0.10之前,一般情況下,Kong會將代理的請求轉發到指定的upstream_url上,如果想實現服務的負載平衡,需要額外的工具來完成。您可以通過查閱負載平衡相關資料,找到更多有關向API添加負載平衡的信息。

  2. 插件擴展

    使用者可以通過plugins來自定義擴展插件,並將插件應用到request/response的生命周期中。插件可以在您的生產環境中對代理行為進行多種操作。通過對插件進行配置,可以將插件應進行全局應用或針對個別API應用。如果對給定的某個或某些API應用了一個插件或多個插件,則在代理請求到上游服務前,會首先執行API的匹配,匹配成功后再執行定義的插件,當插件執行完后,如果滿足天劍,才會將請求最終代理到上游服務中去。這里包含了插件的訪問時段的概念,具體參考插件開發配置相關資料。

  3. 代理或請求超時

    當KONG將所有的代理邏輯,包括API驗證和插件等,都處理完后,才會將請求代理到上游服務。這些是通過Nginx的代理模塊來實現的。從KONG 0.10開始,可以通過配置以下三個API屬性來定義連接超時時間:

  upstream_connect_timeout: 定義同上游服務建立連接的超時時間,單位是毫秒,默認值為60000.

  upstream_send_timeout: 定義兩個連續向上游服務發送的寫入操作的超時時間,單位是毫秒,默認值為60000.

  upstream_read_timeout: 定義兩個連續向上游服務發送讀取操作的超時時間,單位是毫秒,默認值為60000.

    在使用HTTP/1.1時,KONG會默認添加以下請求頭信息:

  HOST:<上游服務的host> 

  Connection:keep-alive : 允許重復使用上游連接

  X-REAL-IP:<$proxy_add_x_forwarded_for>: 參見 nginx_http_proxy_module.

  X-Forwarded-Proto:<protocol>: protocol是客戶端使用的協議名

    其他的請求頭都按默認配置添加。

    當使用WebSocket時,會有例外發生。如果發生,KONG允許通過以下請求頭對協議進行升級:

  Connection:Upgrade

  Upgrade:WebSocket

  4. Response

    Kong接收上游服務的響應,並以流式方式將其發回下游客戶端。此時,Kong將執行添加到該特定API的后續插件,並且這些插件繼承了header_filter子句。當所有繼承了header_filter的插件執行完后,以下的幾種頭信息將返回給客戶端:

  Via:kong/x.x.x KONG的版本信息,x.x.x是他的版本號。

  Kong-Proxy-Latency:<latency>,其中 latency 表示Kong接收來自客戶端的請求並將請求發送到上游服務所消耗的時間值(毫秒)。

  Kong-Upstream-Latency:<latency>,其中 latency 表示Kong等待上游服務響應的第一個字節所消耗的時間數(毫秒)。

    當headers發送到客戶端后,Kong將執行此API上已注冊的、繼承了body_filter的插件。body_filter將上游返回的數據成功處理后,然后再發送給客戶端。

 

配置一個fallback API

  默認情況下,當向KONG發送請求時,如果請求失敗,KONG會返回 HTTP 404,“API not found” 等信息。為了避免這種情況的發生,我們可以通過配置 fallback API 實現自定義 “異常\錯誤” 信息。 

  下面是一個例子:

{
    "name": "root-fallback",
    "upstream_url": "http://www.error.page",
    "uris": ["/"]
}

  觀察此配置中的“uris”,會發現,此處配置“/”可以適配所有的請求,根據uris的匹配規則,每個請求都會首先匹配最長的uri,依次遞減。所以當所有的uri都不匹配時,請求會自動轉發到這里配置的上有服務中去,因此而實現了自定義 “異常\錯誤” 信息。

 

配置API的SSL

  Kong提供了一種在每個連接的基礎上動態提供SSL證書的方法。從0.10版本開始,SSL插件已被刪除,SSL證書由內核直接處理,並可通過Admin API進行配置。你的客戶端HTTP庫必須支持SNI(Server Name Indication)擴展以確保SSL可用。

  SSL證書由Kong Admin API的兩個資源處理:

    · /certificates  存儲您的密鑰和證書。

    · /snis  將注冊的證書與服務器名稱指示相關聯。

  以下是為給定的API配置SSL證書的方法:

    首先,通過Admin API上傳SSL證書和密鑰:

$ curl -i -X POST http://localhost:8001/certificates \
    -F "cert=@/path/to/cert.pem" \
    -F "key=@/path/to/cert.key" \
    -F "snis=ssl-example.com,other-ssl-example.com"
HTTP/1.1 201 Created
...

 

  snis是加密參數,直接插入SNI並將上傳的證書與之相關聯。

  您現在必須在Kong內注冊以下API。為方便起見,我們將使用Host頭將請求轉發到此API:

$ curl -i -X POST http://localhost:8001/apis \
    -d "name=ssl-api" \
    -d "upstream_url=http://my-api.com" \
    -d "hosts=ssl-example.com,other-ssl-example.com"
HTTP/1.1 201 Created
...

  好了,現在你可以向KONG發送HTTPs請求了:

$ curl -i https://localhost:8443/ \
  -H "Host: ssl-example.com"
HTTP/1.1 200 OK
...

  1. https_only參數:

    如果你希望僅通過HTTPS提供API,可以通過啟用其https_only屬性來實現:

$ curl -i -X POST http://localhost:8001/apis \
    -d "name=ssl-only-api" \
    -d "upstream_url=http://example.com" \
    -d "hosts=my-api.com" \
    -d "https_only=true"
HTTP/1.1 201 Created
...

    這樣配置后,KONG將拒絕代理非HTTPS的請求。如果此時使用HTTP請求來訪問這個API,KONG會提示用戶需要將客戶端升級到HTTPS:

$ curl -i http://localhost:8000 \
    -H "Host: my-api.com"
HTTP/1.1 426
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: Upgrade
Upgrade: TLS/1.2, HTTP/1.1
Server: kong/x.x.x

{"message":"Please use HTTPS protocol"}

  2. http_if_terminated參數:

    當API被鎖定在HTTPS請求時,如果你想在請求頭信息中添加X-Forwarded-Proto,只要為API配置http_if_terminated屬性即可:

$ curl -i -X PATCH http://localhost:8001/apis/ssl-only-api \
    -d "http_if_terminated=true"
HTTP/1.1 200 OK
...

    並且我們使用X-Forwarded-Proto(假設它來自可信任的客戶端)發出請求:

$ curl -i http://localhost:8000 \
    -H "Host: my-api.com" \
    -H "X-Forwarded-Proto: https"
HTTP/1.1 200 OK
...

    Kong現在代理了這個請求,因為它假定你的體系結構的先前組件已經實現了SSL。

 

代理WebSocket

  由於KONG的底層實現了Nginx,所以他也支持WebSocket。如果你希望在客戶端和KONG之間建議一個WebSocket連接,那么你必須首先建立一個WebSocket握手。這個通過HTTP Upgrade機制完成。這個可以通過客戶端對KONG進行操作,例如:

GET / HTTP/1.1
Connection: Upgrade
Host: my-websocket-api.com
Upgrade: WebSocket

  此時,KONG會將Connection和Upgrade兩個請求頭轉發到上游服務中去。

 

小結

  通過本指南,希望你了解了Kong的底層代理相關的知識,從API的uris匹配,到如何使用WebSocket協議、為API配置SSL。如果想了解更多的相關知識,請參考Nginx的負載平衡相關內容。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM