高效能API閘道器Kong介紹

天翼雲開發者社群發表於2022-06-02


本文關鍵詞:高效能、API閘道器、Kong、微服務

1.Introduction

        

API 閘道器 是隨著微服務( Microservice )概念興起的一種架構模式。原本一個龐大的單體應用( All in one )業務系統被拆分成許多微服務( Microservice )系統進行獨立的維護和部署,服務拆分帶來的變化是 API 的規模成倍增長, API 的管理難度也在日益增加,使用 API 閘道器釋出和管理 API 逐漸成為一種趨勢。一般來說, API 閘道器是執行於外部請求與內部服務之間的一個流量入口,實現對外部請求的協議轉換、鑑權、流控、引數校驗、監控等通用功能。

          本文即將介紹的 是一個開源的API gateway 和微服務管理的工具,基於 Nginx (特殊的 ),Kong 具有可插拔的架構,使其功能強大且靈活。

2.Key Concepts

·  Service: Kong 的一個實體物件,表示了外部的上游 API 或者微服務

·  Route: Kong 的一個實體物件,表示了一種將下游請求對映到上游服務的路由

·  Consumer: Kong 的一個實體物件,表示使用 API 的開發者或者機器,在使用 Kong 時,一個 Consumer 僅與 Kong 互動。

·  Plugin :外掛用於是 Kong 內部將請求轉發給上游 API 前後執行的一系列動作, Kong 在其 中提供了非常強大的外掛

·  Credential: A certificate object represents a public certificate/private key pair for an SSL certificate.

·  SNI: An SNI object represents a many-to-one mapping of hostnames to a certificate. That is, a certificate object can have many hostnames associated with it

·  Upstream: 上游服務 指代 Kong 背後的 API 或者服務 也是客戶端請求轉發的目的端 The upstream object represents a virtual hostname and can be used to loadbalance incoming requests over multiple services (targets).

·  Target: A target is an ip address/hostname with a port that identifies an instance of a backend service. Every upstream can have many targets, and the targets can be dynamically added. Changes are effectuated on the fly.

·  Admin API - 用於管理 Kong 配置,端點,使用者,外掛等的 RESTful API 端點

下圖展示了Kong 和其他 傳統 架構的區別,可以幫助我們理解為什麼有Kong


大概有鑑權、監控、日誌、安全審計、ACL 、快取、限流、 serverless 等等。

3.Setup

官方文件提供了多種環境下詳細的 。我們這裡使用docker 進行安裝( docker 安裝過程略):

# 1 .create docker network

$ docker network create kong-net

 

# 2 .run PostgreSQL database

$ docker run -d --name kong-database \

            --network=kong-net \

            - p   5432 : 5432  \

            - e   "POSTGRES_USER=kong"  \

            - e   "POSTGRES_DB=kong"  \

            postgre s:9 . 6

 

# 3 .prepare database

$ docker run --rm \

    --network=kong-net \

    - e   "KONG_DATABASE=postgres"  \

    - e   "KONG_PG_HOST=kong-database"  \

    - e   "KONG_CASSANDRA_CONTACT_POINTS=kong-database"  \

    kon g:latest  kong migrations bootstrap

 

Unable to   find  image 'kong:latest'  locally

lates t:  Pulling from library/kong

59265 c40e257: Pull complete

6389 eff8e6ff: Pull complete

f58488256be6: Pull complete

Diges t:   sha256 :f7ed033bb9955da0fcefa034d07fee324cad6d01c12ebf54268dfe825ba2e92c

Statu s:  Downloaded newer image for  kon g:latest

bootstrapping database...

migrating core on  database 'kong' ...

core migrated up   to : 000 _base (executed)

core migrated up   to : 001 _14_to_15 (executed)

core migrated up   to : 002 _15_to_1 (executed)

migrating oauth2 on  database 'kong' ...

oauth2 migrated up   to : 000 _base_oauth2 (executed)

oauth2 migrated up   to : 001 _14_to_15 (executed)

oauth2 migrated up   to : 002 _15_to_10 (executed)

migrating acl on  database 'kong' ...

acl migrated up   to : 000 _base_acl (executed)

acl migrated up   to : 001 _14_to_15 (executed)

migrating jwt on  database 'kong' ...

jwt migrated up   to : 000 _base_jwt (executed)

jwt migrated up   to : 001 _14_to_15 (executed)

migrating basic-auth on  database 'kong' ...

basic-auth migrated up   to : 000 _base_basic_auth (executed)

basic-auth migrated up   to : 001 _14_to_15 (executed)

migrating key-auth on  database 'kong' ...

key-auth migrated up   to : 000 _base_key_auth (executed)

key-auth migrated up   to : 001 _14_to_15 (executed)

migrating rate-limiting on  database 'kong' ...

rate-limiting migrated up   to : 000 _base_rate_limiting (executed)

rate-limiting migrated up   to : 001 _14_to_15 (executed)

rate-limiting migrated up   to : 002 _15_to_10 (executed)

migrating hmac-auth on  database 'kong' ...

hmac-auth migrated up   to : 000 _base_hmac_auth (executed)

hmac-auth migrated up   to : 001 _14_to_15 (executed)

migrating response-ratelimiting on  database 'kong' ...

response-ratelimiting migrated up   to : 000 _base_response_rate_limiting (executed)

response-ratelimiting migrated up   to : 001 _14_to_15 (executed)

response-ratelimiting migrated up   to : 002 _15_to_10 (executed)

22  migrations processed

22  executed

database is   up - to -date

 

# 4 .start Kong

$ docker run -d --name kong \

    --network=kong-net \

    - e   "KONG_DATABASE=postgres"  \

    - e   "KONG_PG_HOST=kong-database"  \

    - e   "KONG_CASSANDRA_CONTACT_POINTS=kong-database"  \

    - e   "KONG_PROXY_ACCESS_LOG=/dev/stdout"  \

    - e   "KONG_ADMIN_ACCESS_LOG=/dev/stdout"  \

    - e   "KONG_PROXY_ERROR_LOG=/dev/stderr"  \

    - e   "KONG_ADMIN_ERROR_LOG=/dev/stderr"  \

    - e   "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl"  \

    - p   8000 : 8000  \

    - p   8443 : 8443  \

    - p   8001 : 8001  \

    - p   8444 : 8444  \

    kon g:latest

999 a5cf1db1a8c23ca870933b73407d7ae5f0fd2d9a895a78627a9c27e08045c

 

$ docker container ls

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                NAMES

999 a5cf1db1a        kon g:latest           "/docker-entrypoint. "     8  seconds ago       Up 7  seconds         0.0 . 0.0 : 8000 - 8001 -> 8000 - 8001 /tcp, 0.0 . 0.0 : 8443 - 8444 -> 8443 - 8444 /tcp   kong

ecb50c2f7307        postgre s:9 . 6          "docker-entrypoint.s "    About an  hour ago   Up About an  hour     0.0 . 0.0 : 5432 -> 5432 /tcp

容器啟動完畢後 嘗試 curl -i 得到如下

{

     "plugins" : {

         "enabled_in_cluster" : [ ],

         "available_on_server" : {

             "response-transformer" : true ,

             "oauth2" : true ,

             "acl" : true ,

             "correlation-id" : true ,

             "pre-function" : true ,

             "jwt" : true ,

             "cors" : true ,

             "ip-restriction" : true ,

             "basic-auth" : true ,

             "key-auth" : true ,

             "rate-limiting" : true ,

             "request-transformer" : true ,

             "http-log" : true ,

             "file-log" : true ,

             "hmac-auth" : true ,

             "ldap-auth" : true ,

             "datadog" : true ,

             "tcp-log" : true ,

             "zipkin" : true ,

             "post-function" : true ,

             "request-size-limiting" : true ,

             "bot-detection" : true ,

             "syslog" : true ,

             "loggly" : true ,

             "azure-functions" : true ,

             "udp-log" : true ,

             "response-ratelimiting" : true ,

             "aws-lambda" : true ,

             "statsd" : true ,

             "prometheus" : true ,

             "request-termination" : true

        }

    },

     "tagline" : "Welcome to kong" ,

     "configuration" : {

         "plugins" : [

             "bundled"

        ],

         "admin_ssl_enabled" : true ,

         "lua_ssl_verify_depth" : 1 ,

         "trusted_ips" : { },

         "prefix" : "/usr/local/kong" ,

         "loaded_plugins" : {

             "response-transformer" : true ,

             "request-termination" : true ,

             "prometheus" : true ,

             "ip-restriction" : true ,

             "pre-function" : true ,

             "jwt" : true ,

             "cors" : true ,

             "statsd" : true ,

             "basic-auth" : true ,

             "key-auth" : true ,

             "ldap-auth" : true ,

             "aws-lambda" : true ,

             "http-log" : true ,

             "response-ratelimiting" : true ,

             "hmac-auth" : true ,

             "request-size-limiting" : true ,

             "datadog" : true ,

             "tcp-log" : true ,

             "zipkin" : true ,

             "post-function" : true ,

             "bot-detection" : true ,

             "acl" : true ,

             "loggly" : true ,

             "syslog" : true ,

             "azure-functions" : true ,

             "udp-log" : true ,

             "file-log" : true ,

             "request-transformer" : true ,

             "correlation-id" : true ,

             "rate-limiting" : true ,

             "oauth2" : true

        },

         "cassandra_username" : "kong" ,

         "ssl_cert_key" : "/usr/local/kong/ssl/kong-default.key" ,

         "admin_ssl_cert_key" : "/usr/local/kong/ssl/admin-kong-default.key" ,

         "dns_resolver" : { },

         "pg_user" : "kong" ,

         "mem_cache_size" : "128m" ,

         "ssl_ciphers" : "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256" ,

         "nginx_admin_directives" : { },

         "nginx_http_directives" : [

            {

                 "value" : "prometheus_metrics 5m" ,

                 "name" : "lua_shared_dict"

            }

        ],

         "pg_host" : "kong-database" ,

         "nginx_acc_logs" : "/usr/local/kong/logs/access.log" ,

         "proxy_listen" : [

             "0.0.0.0:8000" ,

             "0.0.0.0:8443 ssl"

        ],

         "client_ssl_cert_default" : "/usr/local/kong/ssl/kong-default.crt" ,

         "ssl_cert_key_default" : "/usr/local/kong/ssl/kong-default.key" ,

         "db_update_frequency" : 5 ,

         "db_update_propagation" : 0 ,

         "stream_listen" : [

             "off"

        ],

         "nginx_err_logs" : "/usr/local/kong/logs/error.log" ,

         "cassandra_port" : 9042 ,

         "dns_order" : [

             "LAST" ,

             "SRV" ,

             "A" ,

             "CNAME"

        ],

         "dns_error_ttl" : 1 ,

         "headers" : [

             "server_tokens" ,

             "latency_tokens"

        ],

         "cassandra_lb_policy" : "RequestRoundRobin" ,

         "nginx_optimizations" : true ,

         "pg_timeout" : 5000 ,

         "database" : "postgres" ,

         "pg_database" : "kong" ,

         "nginx_worker_processes" : "auto" ,

         "lua_package_cpath" : "" ,

         "admin_acc_logs" : "/usr/local/kong/logs/admin_access.log" ,

         "lua_package_path" : "./?.lua;./?/init.lua;" ,

         "nginx_pid" : "/usr/local/kong/pids/nginx.pid" ,

         "upstream_keepalive" : 60 ,

         "client_ssl" : false ,

         "admin_access_log" : "/dev/stdout" ,

         "cassandra_data_centers" : [

             "dc1:2" ,

             "dc2:3"

        ],

         "cassandra_ssl" : false ,

         "proxy_listeners" : [

            {

                 "transparent" : false ,

                 "ssl" : false ,

                 "ip" : "0.0.0.0" ,

                 "proxy_protocol" : false ,

                 "port" : 8000 ,

                 "http2" : false ,

                 "listener" : "0.0.0.0:8000"

            },

            {

                 "transparent" : false ,

                 "ssl" : true ,

                 "ip" : "0.0.0.0" ,

                 "proxy_protocol" : false ,

                 "port" : 8443 ,

                 "http2" : false ,

                 "listener" : "0.0.0.0:8443 ssl"

            }

        ],

         "proxy_ssl_enabled" : true ,

         "client_max_body_size" : "0" ,

         "proxy_error_log" : "/dev/stderr" ,

         "enabled_headers" : {

             "latency_tokens" : true ,

             "X-Kong-Proxy-Latency" : true ,

             "Via" : true ,

             "server_tokens" : true ,

             "Server" : true ,

             "X-Kong-Upstream-Latency" : true ,

             "X-Kong-Upstream-Status" : false

        },

         "dns_stale_ttl" : 4 ,

         "lua_socket_pool_size" : 30 ,

         "db_resurrect_ttl" : 30 ,

         "origins" : { },

         "cassandra_consistency" : "ONE" ,

         "db_cache_ttl" : 0 ,

         "admin_error_log" : "/dev/stderr" ,

         "pg_ssl_verify" : false ,

         "dns_not_found_ttl" : 30 ,

         "pg_ssl" : false ,

         "nginx_daemon" : "off" ,

         "nginx_kong_stream_conf" : "/usr/local/kong/nginx-kong-stream.conf" ,

         "cassandra_repl_strategy" : "SimpleStrategy" ,

         "error_default_type" : "text/plain" ,

         "dns_no_sync" : false ,

         "nginx_proxy_directives" : { },

         "proxy_access_log" : "/dev/stdout" ,

         "nginx_kong_conf" : "/usr/local/kong/nginx-kong.conf" ,

         "cassandra_schema_consensus_timeout" : 10000 ,

         "dns_hostsfile" : "/etc/hosts" ,

         "admin_listeners" : [

            {

                 "transparent" : false ,

                 "ssl" : false ,

                 "ip" : "0.0.0.0" ,

                 "proxy_protocol" : false ,

                 "port" : 8001 ,

                 "http2" : false ,

                 "listener" : "0.0.0.0:8001"

            },

            {

                 "transparent" : false ,

                 "ssl" : true ,

                 "ip" : "0.0.0.0" ,

                 "proxy_protocol" : false ,

                 "port" : 8444 ,

                 "http2" : false ,

                 "listener" : "0.0.0.0:8444 ssl"

            }

        ],

         "ssl_cipher_suite" : "modern" ,

         "ssl_cert" : "/usr/local/kong/ssl/kong-default.crt" ,

         "cassandra_timeout" : 5000 ,

         "admin_ssl_cert_key_default" : "/usr/local/kong/ssl/admin-kong-default.key" ,

         "cassandra_ssl_verify" : false ,

         "cassandra_contact_points" : [

             "kong-database"

        ],

         "real_ip_header" : "X-Real-IP" ,

         "real_ip_recursive" : "off" ,

         "cassandra_repl_factor" : 1 ,

         "client_ssl_cert_key_default" : "/usr/local/kong/ssl/kong-default.key" ,

         "admin_ssl_cert" : "/usr/local/kong/ssl/admin-kong-default.crt" ,

         "anonymous_reports" : true ,

         "log_level" : "notice" ,

         "kong_env" : "/usr/local/kong/.kong_env" ,

         "pg_port" : 5432 ,

         "admin_ssl_cert_default" : "/usr/local/kong/ssl/admin-kong-default.crt" ,

         "client_body_buffer_size" : "8k" ,

         "ssl_preread_enabled" : true ,

         "ssl_cert_csr_default" : "/usr/local/kong/ssl/kong-default.csr" ,

         "stream_listeners" : { },

         "cassandra_keyspace" : "kong" ,

         "ssl_cert_default" : "/usr/local/kong/ssl/kong-default.crt" ,

         "nginx_conf" : "/usr/local/kong/nginx.conf" ,

         "admin_listen" : [

             "0.0.0.0:8001" ,

             "0.0.0.0:8444 ssl"

        ]

    },

     "version" : "1.0.3" ,

     "node_id" : "3ccef799-3037-4a8f-8ccd-2e60326b4444" ,

     "lua_version" : "LuaJIT 2.1.0-beta3" ,

     "prng_seeds" : {

         "pid: 36" : 229762112224 ,

         "pid: 37" : 131951181922 ,

         "pid: 1" : 136391662351

    },

     "timers" : {

         "pending" : 5 ,

         "running" : 0

    },

     "hostname" : "999a5cf1db1a"

}

上面幾個埠,分別是:

·  :8000 on which Kong listens for incoming HTTP traffic from your clients, and forwards it to your upstream services.

·  :8443 on which Kong listens for incoming HTTPS traffic. This port has a similar behavior as the :8000 port, except that it expects HTTPS traffic only. This port can be disabled via the configuration file.

·  :8001 on which the Admin API used to configure Kong listens.

·  :8444 on which the Admin API listens for HTTPS traffic.

4.API Management

在本地配置 Kong 完畢後 我們來感受一下 Kong 強大的特性。首先我們有一個簡單的 API 服務 之前已經寫好的一個 flavors 的增刪改查 flavors 的查詢為例 我們將 GET /flavors/detail 新增到 Kong 中。

我們的API server 地址是 ,於是我們有:

·  route path:  /flavors/detail

·  service host: 

4.1 Add a service

curl -i -X POST \

  - -url http: / /localhost:8001/services/ \   - -data 'name=example-flavors'\   - -data 'url=

得到的響應

HTTP/1.1 201  Created

Date : Wed, 27 Feb 2019 06:08:25 GMT

Content-Type : application/json; charset=utf-8

Connection : keep-alive

Access-Control-Allow-Origin : *

Server : kong/1.0.3

Content-Length : 273

 

{ "host" : "127.0.0.1" , "created_at" : 1551247705 , "connect_timeout" : 60000 , "id" : "abba6d52-b239-4b8f-ad11-1e7389d4cf71" , "protocol" : "http" , "name" : "example-flavors" , "read_timeout" : 60000 , "port" : 8080 , "path" : "/flavors/detail" , "updated_at" : 1551247705 , "retries" : 5 , "write_timeout" : 60000  }

4.2 List current services

curl -i -X GET \

   - -url http: / /localhost:8001/services/

得到的響應:

HTTP/1.1 200  OK

Date : Wed, 27 Feb 2019 06:11:07 GMT

Content-Type : application/json; charset=utf-8

Connection : keep-alive

Access-Control-Allow-Origin : *

Server : kong/1.0.3

Content-Length : 296

 

{ "next" : null , "data" : [ { "host" : "127.0.0.1" , "created_at" : 1551247705 , "connect_timeout" : 60000 , "id" : "abba6d52-b239-4b8f-ad11-1e7389d4cf71" , "protocol" : "http" , "name" : "example-flavors" , "read_timeout" : 60000 , "port" : 8080 , "path" : "/flavors/detail" , "updated_at" : 1551247705 , "retries" : 5 , "write_timeout" : 60000  } ] }

可以看到目前就我們前面新增的一個。

4.3 Add a route to service

有了服務之後,我們為服務填一個轉發路由:

curl -i -X POST \

   - -url http: / /localhost:8001/services/example-flavors/routes  \   - -data 'hosts[]=hb.ctyun.com'  \   - -data 'paths[]=/flavors/detail'  \   - -data 'name=flavor-detail'  

得到的響應是

HTTP/1.1 201  Created

Date : Wed, 27 Feb 2019 06:24:00 GMT

Content-Type : application/json; charset=utf-8

Connection : keep-alive

Access-Control-Allow-Origin : *

Server : kong/1.0.3

Content-Length : 377

 

{ "created_at" : 1551248640 , "methods" : null , "id" : "11dbb4a1-7452-4d40-a45a-de3f3cad5275" , "service" : { "id" : "abba6d52-b239-4b8f-ad11-1e7389d4cf71"  }, "name" : "flavor-detail" , "hosts" : [ "hb.ctyun.com"  ], "updated_at" : 1551248640 , "preserve_host" : false , "regex_priority" : 0 , "paths" : [ "/flavors/detail"  ], "sources" : null , "destinations" : null , "snis" : null , "protocols" : [ "http" , "https"  ], "strip_path" : true  }

原先獲取flavors 列表,我們是透過:

curl -X GET http: // localhost: 8080 /flavors/ detail

而我們現在可以直接透過Kong 進行訪問,注意,我們必須修改 Header ,新增指定的 Host 資訊:

curl -X GET http: // localhost: 8000 /flavors/ detail -H 'Host:hb.ctyun.com'

結果遇到了報錯,提示:

172.18.0.1  - - [27/Feb/2019:06:43:17 +0000]   " GET  /flavors/detail HTTP/1.1"   502   69   "-"   "curl/7.54.0"

2019 / 02 / 27   06 : 43 : 17   [error]   36 # 0 : * 35879  connect() failed ( 111 : Connection refused) while connecting to upstream, client: 172.18.0.1 , server: kong, request: " GET  /flavors/detail HTTP/1.1" , upstream: " , host: "hb.ctyun.com"

可以看到能夠按照路由規則進行轉發,但是由於網路問題(kong 部署在了 docker 容器中),所以沒有辦法進行訪問。

我們重新建立service route ,並使用 來驗證:

# 執行一個容器,將本地的 8080 的請求轉發到容器的 80

docker run -d --name simple-web-server \

    --network kong-net \

    -p 8080 : 80  kennethreitz/httpbin

 

# 建立名為 demo service

curl -i -X POST \

  --url http: //localhost:8001/services/ \

  --data 'name=demo' \

  --data 'url=

 

HTTP/ 1.1   201  Created

Date: Wed, 27  Feb 2019   07 : 51 : 45  GMT

Content-Type: application/json; charset=utf -8

Connection: keep-alive

Access-Control-Allow-Origin: *

Server: kong/ 1.0.3

Content-Length: 256

 

{

     "host" : "simple-web-server" ,

     "created_at" : 1551253905 ,

     "connect_timeout" : 60000 ,

     "id" : "978de8a6-6767-4741-baca-a25c9a131f9d" ,

     "protocol" : "http" ,

     "name" : "demo" ,

     "read_timeout" : 60000 ,

     "port" : 80 ,

     "path" : "/get" ,

     "updated_at" : 1551253905 ,

     "retries" : 5 ,

     "write_timeout" : 60000

}

 

# service demo 配置 route 規則

curl -i -X POST \

  --url http: //localhost:8001/services/demo/routes \

  --data 'hosts[]=api.ctyun.com'  \

  --data 'paths[]=/get'  \

  --data 'name=demo-get'

 

HTTP/ 1.1   201  Created

Date: Wed, 27  Feb 2019   07 : 52 : 40  GMT

Content-Type: application/json; charset=utf -8

Connection: keep-alive

Access-Control-Allow-Origin: *

Server: kong/ 1.0.3

Content-Length: 361

 

{

     "created_at" : 1551253960 ,

     "methods" : null ,

     "id" : "06d6754e-a4ae-4be6-9b87-b64ccfe6c920" ,

     "service" : {

         "id" : "978de8a6-6767-4741-baca-a25c9a131f9d"

    },

     "name" : "demo-get" ,

     "hosts" : [

         "api.ctyun.com"

    ],

     "updated_at" : 1551253960 ,

     "preserve_host" : false ,

     "regex_priority" : 0 ,

     "paths" : [

         "/get"

    ],

     "sources" : null ,

     "destinations" : null ,

     "snis" : null ,

     "protocols" : [

         "http" ,

         "https"

    ],

     "strip_path" : true

}

然後我們嘗試透過訪問 kong 轉發到 httpbin

curl -i -X GET http: //localhost:8000/get -H 'Host:api.ctyun.com'

 

HTTP/ 1.1   200  OK

Content- Type:  application/json

Content- Length:   266

Connection:  keep-alive

Server:  gunicorn/ 19.9.0

Date:  Wed, 27  Feb 2019   07 : 56 : 50  GMT

Access-Control-Allow- Origin:  *

Access-Control-Allow- Credentials:   true

X-Kong-Upstream- Latency:   9

X-Kong-Proxy- Latency:   84

Via:  kong/ 1.0.3

 

{

   "args" : {},

   "headers" : {

     "Accept" : "*/*" ,

     "Connection" : "keep-alive" ,

     "Host" : "simple-web-server" ,

     "User-Agent" : "curl/7.54.0" ,

     "X-Forwarded-Host" : "api.ctyun.com"

  },

   "origin" : "172.18.0.1" ,

   "url" : "

}

至此,我們已經可以透過來源host route 將請求換髮到指定的目標 host ,並且得到了返回值,這就算完成了基本 API 轉發流程。

4.4 Plugins

Kong 提供了非常豐富的外掛,都可以在 找得到。這裡我們簡單為我們的服務配置一個 plugin

在服務demo 上啟用 key-auth 的外掛:

curl -X POST http: //localhost:8001/services/demo/plugins \

    --data "name=key-auth"  

{

     "created_at" : 1551256029 ,

     "config" : {

         "key_names" : [

             "apikey"

        ],

         "run_on_preflight" : true ,

         "anonymous" : null ,

         "hide_credentials" : false ,

         "key_in_body" : false

    },

     "id" : "4eaa000f-0fa2-4b3e-8c13-2db4c6b7ce49" ,

     "service" : {

         "id" : "978de8a6-6767-4741-baca-a25c9a131f9d"

    },

     "enabled" : true ,

     "run_on" : "first" ,

     "consumer" : null ,

     "route" : null ,

     "name" : "key-auth"

}

也可以在具體的 route 上啟用外掛 比如

curl -X POST http: // <host> :8001 /routes/{route_id} /plugins  \

    --data   "name=key-auth"  

我們這裡就不再贅述了。

開啟外掛後 再次訪問前面的 simple-web-server 則有

curl -i -X GET http: //localhost:8000/get -H 'Host:api.ctyun.com'

HTTP/ 1.1   401  Unauthorized

Date:  Wed, 27  Feb 2019   08 : 27 : 13  GMT

Content- Type:  application/json; charset=utf -8

Connection:  keep-alive

WWW- Authenticate:  Key realm= "kong"

Content- Length:   41

Server:  kong/ 1.0.3

 

{ "message" : "No API key found in request" }

此時外掛 key-auth 已經開啟了 開啟之後怎麼用呢 要想使用鑑權外掛 離不開 Consumer 。如何建立 Consumer 並使用指定的外掛 我們放到 中盡心更詳細的介紹。

4.5 Add Consumers

新增一個 consumer username custom_id 指定任一即可

curl -i -X POST \

  - -url http: / /localhost:8001/consumers/ \   - -data "username=<USERNAME>" \   - -data "custom_id=<CUSTOM_ID>"

curl -i -X POST \

  --url http: //localhost:8001/consumers/ \

  --data "username=elbarco"

 

HTTP/ 1.1   201  Created

Date:  Wed, 27  Feb 2019   08 : 47 : 50  GMT

Content- Type:  application/json; charset=utf -8

Connection:  keep-alive

Access-Control-Allow- Origin:  *

Server:  kong/ 1.0.3

Content- Length:   107

 

{

     "custom_id" : null ,

     "created_at" : 1551257270 ,

     "username" : "elbarco" ,

     "id" : "738627ae-57e9-4b20-9d1d-fb12998d5296"

}

為使用者提供一個key

curl -i -X POST \

  --url http: //localhost:8001/consumers/elbarco/key-auth/ \

  --data 'key=hola-elbarco'

 

HTTP/ 1.1   201  Created

Date:  Wed, 27  Feb 2019   09 : 12 : 12  GMT

Content- Type:  application/json; charset=utf -8

Connection:  keep-alive

Access-Control-Allow- Origin:  *

Server:  kong/ 1.0.3

Content- Length:   147

 

{

     "key" : "hola-elbarco" ,

     "created_at" : 1551258732 ,

     "consumer" : {

         "id" : "738627ae-57e9-4b20-9d1d-fb12998d5296"

    },

     "id" : "b9cb021d-cb37-4841-b172-40ff2dcacb5e"

}

此時 我們就可以帶著鑑權訪問前面的 simple-web-server 有兩種方式

curl  { proxy  path}?apikey=<some_key>

 

curl { proxy  path} \

    -H 'apikey: <some_key>'

我們這裡任選一種即可

curl -i -X GET http: //localhost:8000/get -H 'Host:api.ctyun.com' -H 'apikey:hola-elbarco'

 

HTTP/ 1.1   200  OK

Content- Type:  application/json

Content- Length:   398

Connection:  keep-alive

Server:  gunicorn/ 19.9.0

Date:  Wed, 27  Feb 2019   09 : 19 : 31  GMT

Access-Control-Allow- Origin:  *

Access-Control-Allow- Credentials:   true

X-Kong-Upstream- Latency:   68

X-Kong-Proxy- Latency:   26

Via:  kong/ 1.0.3

 

{

   "args" : {},

   "headers" : {

     "Accept" : "*/*" ,

     "Apikey" : "hola-elbarco" ,

     "Connection" : "keep-alive" ,

     "Host" : "simple-web-server" ,

     "User-Agent" : "curl/7.54.0" ,

     "X-Consumer-Id" : "738627ae-57e9-4b20-9d1d-fb12998d5296" ,

     "X-Consumer-Username" : "elbarco" ,

     "X-Forwarded-Host" : "api.ctyun.com"

  },

   "origin" : "172.18.0.1" ,

   "url" : "

}

4.6 Rate limiting

額外的 我們再看一下限流外掛

5.Advanced Features

5.1 Load balancing

6.Kong Dashboard (From community)

Kong 的商業版中 提供了一個視覺化介面工具 叫做 功能很是強大 比如

試用需要申請,我們轉而在社群中尋求替代工具,於是在Github 上搜到了 ,提供了使用npm docker 安裝兩種方式,這裡採用 docker 的方式安裝一下,看看效果:

# Start Kong Dashboard

docker run  --rm -p 9090:8080 pgbi/kong-dashboard start --kong-url  

# Start Kong Dashboard on a custom port

docker run  --rm -p [port]:8080 pgbi/kong-dashboard start --kong-url  

# Start Kong Dashboard with basic auth

docker run  --rm -p 8080:8080 pgbi/kong-dashboard start \ --kong-url     --basic-auth user1=password1 user2=password2

 

# See full list of start options

docker run  --rm -p 8080:8080 pgbi/kong-dashboard start -- help  

docker run --rm   --name  kong-dashboard -p 9090 :808i0  pgbi/kong-dashboard start --kong-url  http: //locahost :8001

docker run --rm    --network  kong-net --name  kong-dashboard -p 9090 :8080  pgbi/kong-dashboard start --kong-url  http: //kong :8001

Connecting to Kong on http: //kong :8001   ...

This version  of Kong dashboard doesn't support Kong v0.15 and higher.

受限於 Kong 的版本

docker container exec 999 a5cf1db1a kong version

1.0.3

我們沒辦法接入 kong-dashboard 後面 進行調研吧。

7.Summary

kong 的模型比較清晰 service route plugin upstream consumer 通用性比較強 因為外掛的存在 功能擴充套件性也很高。從我們的實際業務觸發,也可以參考借鑑這種模型方式,先從核心功能出發。

8.Reference

·  [1].

·  [2].

 

API 閘道器 :  


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70014251/viewspace-2898701/,如需轉載,請註明出處,否則將追究法律責任。

相關文章