kong
简介
Kong
是一个开源的API
网关,集成了服务注册和发现、负载均衡、健康检查等功能,还可以通过插件来提供限流、熔断、监控、日志等能力,
在kong
的微服务架构中,kong
担当了注册中心的角色,服务提供者(Provider)
首先将服务信息注册到 kong
,服务消费者(Consumer)
调用服务的过程是调用端先将请求发到 kong
,再通过 kong
把请求转发到服务提供者而实现间接调用。
本文通过梳理kong
数据库中的字段关联关系,从而了解请求的转发流程。
kong
服务定义
一个完整的kong
服务由四部分实体构成:route
,service
,upstream
和target
。各自作用介绍如下:
route
:记录了请求规则和服务service
的对应关系;services
:服务实体,是上游服务upstream
的抽象;upstream
:一个或多个target
的集合,负责流量的转发;target
:提供服务的最小单位,也是负载均衡的终端。
kong
转发请求的整体流程可以概述为:当客户端发起一个请求时,routes
通过提前注册的信息匹配出对应的service
服务,根据service
对应的upstream
信息就可以找到最终处理请求的目标tartget
,从而完成请求的处理。调用流程图示如下:
以下就客户端请求/api/tembin/atsani
为例,结合kong
数据库中的关联关系来具体说明请求的转发流程。
转发流程梳理
从 Route 到 Service
routes
routes
路由匹配客户端的请求规则,匹配成功后分配到service
层,以请求的方法、host、路径等作为转发依据。route
与service
是多对一的关系,所以可根据请求的路径可匹配出对应的service
。
表结构
以下字段需要特殊注意:
字段 | 值 |
---|---|
protocols | 允许访问该路由的协议(默认https\http都允许) |
paths | 匹配路由访问的路径 |
service_id | 指向服务的id |
kong=# \d routes;
Table "public.routes"
Column | Type | Modifiers
----------------------------+--------------------------+--------------------
id | uuid | not null
created_at | timestamp with time zone |
updated_at | timestamp with time zone |
name | text |
service_id | uuid |
protocols | text[] |
methods | text[] |
hosts | text[] |
paths | text[] |
snis | text[] |
sources | jsonb[] |
destinations | jsonb[] |
regex_priority | bigint |
strip_path | boolean |
preserve_host | boolean |
tags | text[] |
https_redirect_status_code | integer |
headers | jsonb |
path_handling | text | default 'v0'::text
Indexes:
"routes_pkey" PRIMARY KEY, btree (id)
"routes_name_key" UNIQUE CONSTRAINT, btree (name)
"routes_service_id_idx" btree (service_id)
"routes_tags_idx" gin (tags)
Foreign-key constraints:
"routes_service_id_fkey" FOREIGN KEY (service_id) REFERENCES services(id)
Referenced by:
TABLE "plugins" CONSTRAINT "plugins_route_id_fkey" FOREIGN KEY (route_id) REFERENCES routes(id) ON DELETE CASCADE
Triggers:
routes_sync_tags_trigger AFTER INSERT OR DELETE OR UPDATE OF tags ON routes FOR EACH ROW EXECUTE PROCEDURE sync_tags()
可看出routes
和service
表通过service_id
进行关联
示例
在routes
表中可根据指定路径筛选出对应的service_id
为27f7d1f2-67f3-430f-b5a1-417c6dcb1198
kong=# select * from routes where paths='{/api/tembin/atsani}';
-[ RECORD 1 ]--------------+-------------------------------------
id | 00dd061d-438c-4e76-92a2-92984c6c55dc
created_at | 2022-10-30 11:53:15+00
updated_at | 2022-10-30 11:53:15+00
name | nscloud.kong-tembin.029
service_id | 27f7d1f2-67f3-430f-b5a1-417c6dcb1198
protocols | {http,https}
methods |
hosts |
paths | {/api/tembin/atsani}
snis |
sources |
destinations |
regex_priority | 0
strip_path | f
preserve_host | t
tags | {managed-by-ingress-controller}
https_redirect_status_code | 426
headers |
path_handling | v0
```
services
service
服务是一个抽象服务层,可以用于指向具体物理服务(target)
,也可以指向upstream
用于实现物理服务的负载效果,其中service
和upstream
是一对一的关系。
注:service
中的host
可以是upstream
的name
,也可以配置为外部的域名,这样请求会直接转发给外部
表结构
以下字段需要特殊注意:
字段 | 值 |
---|---|
protocol | 请求upstream的协议(http、https)默认http |
host | upstream name(一定要和upstream名称保持一致) |
port | 请求upstream的端口(虚拟端口,可自定义)默认80 |
path | 请求upstream的路径 |
kong=# \d services;
Table "public.services"
Column | Type | Modifiers
-----------------------+--------------------------+-----------
id | uuid | not null
created_at | timestamp with time zone |
updated_at | timestamp with time zone |
name | text |
retries | bigint |
protocol | text |
host | text |
port | bigint |
path | text |
connect_timeout | bigint |
write_timeout | bigint |
read_timeout | bigint |
tags | text[] |
client_certificate_id | uuid |
Indexes:
"services_pkey" PRIMARY KEY, btree (id)
"services_name_key" UNIQUE CONSTRAINT, btree (name)
"services_fkey_client_certificate" btree (client_certificate_id)
"services_tags_idx" gin (tags)
Foreign-key constraints:
"services_client_certificate_id_fkey" FOREIGN KEY (client_certificate_id) REFERENCES certificates(id)
Referenced by:
TABLE "oauth2_authorization_codes" CONSTRAINT "oauth2_authorization_codes_service_id_fkey" FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE
TABLE "oauth2_tokens" CONSTRAINT "oauth2_tokens_service_id_fkey" FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE
TABLE "plugins" CONSTRAINT "plugins_service_id_fkey" FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE
TABLE "routes" CONSTRAINT "routes_service_id_fkey" FOREIGN KEY (service_id) REFERENCES services(id)
Triggers:
services_sync_tags_trigger AFTER INSERT OR DELETE OR UPDATE OF tags ON services FOR EACH ROW EXECUTE PROCEDURE sync_tags()
示例
通过上一步查找的service_id
,可在service
表中匹配出对应记录
kong=# select * from services where id='27f7d1f2-67f3-430f-b5a1-417c6dcb1198';
-[ RECORD 1 ]---------+-------------------------------------
id | 27f7d1f2-67f3-430f-b5a1-417c6dcb1198
created_at | 2022-10-30 11:53:15+00
updated_at | 2022-10-30 11:53:15+00
name | nscloud.atsani.80
retries | 5
protocol | http
host | atsani.nscloud.80.svc
port | 80
path | /
connect_timeout | 60000
write_timeout | 60000
read_timeout | 60000
tags | {managed-by-ingress-controller}
client_certificate_id |
从 Service
到Upstream
upstreams
upstream
主要用于实现kong
的负载功能,一个service
匹配到一个upstream
后,upstream
可以指向多个target
服务以此来实现负载的效果。
表结构
以下字段需要特殊注意:
字段 | 值 |
---|---|
name | service指向时使用 |
algorithm | 默认round-robin。目前支持round-robin, consistent-hashing , least-connections |
healthchecks.active.type | 检查目标服务器target的健康方式。一共三类tcp、http、https |
healthchecks.active.http_path | 使用http协议检查target服务是否健康时绑定的路径 |
kong=# \d upstreams
Table "public.upstreams"
Column | Type | Modifiers
----------------------+--------------------------+---------------------------------------------------------------------------
id | uuid | not null
created_at | timestamp with time zone | default timezone('UTC'::text, ('now'::text)::timestamp(3) with time zone)
name | text |
hash_on | text |
hash_fallback | text |
hash_on_header | text |
hash_fallback_header | text |
hash_on_cookie | text |
hash_on_cookie_path | text |
slots | integer | not null
healthchecks | jsonb |
tags | text[] |
algorithm | text |
host_header | text |
Indexes:
"upstreams_pkey" PRIMARY KEY, btree (id)
"upstreams_name_key" UNIQUE CONSTRAINT, btree (name)
"upstreams_tags_idx" gin (tags)
Referenced by:
TABLE "targets" CONSTRAINT "targets_upstream_id_fkey" FOREIGN KEY (upstream_id) REFERENCES upstreams(id) ON DELETE CASCADE
Triggers:
upstreams_sync_tags_trigger AFTER INSERT OR DELETE OR UPDATE OF tags ON upstreams FOR EACH ROW EXECUTE PROCEDURE sync_tags()
从表索引中可看出对于target
表和upstreams
表针对upstreams.id
和targets.upstream_id
做了外键约束
示例
通过上一步查找出的host
字段匹配出对应的upstream
kong=# select * from upstreams where name='atsani.nscloud.80.svc';
-[ RECORD 1 ]---------------------------------------------------
id | b85dd291-d561-4605-8771-2895c1decaa3
created_at | 2022-10-31 02:52:43+00
name | atsani.nscloud.80.svc
hash_on | none
hash_fallback | none
hash_on_header |
hash_fallback_header |
hash_on_cookie |
hash_on_cookie_path | /
slots | 10000
healthchecks | {"active": {"type": "http", "healthy": {"interval": 0, "successes": 0, "http_statuses": [200, 302]}, "timeout": 1, "http_path": "/", "https_sni": null, "unhealthy": {"interval": 0, "timeouts": 0, "tcp_failures": 0, "http_failures": 0, "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505]}, "concurrency": 10, "https_verify_certificate": true}, "passive": {"type": "http", "healthy": {"successes": 0, "http_statuses": [200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308]}, "unhealthy": {"timeouts": 0, "tcp_failures": 0, "http_failures": 0, "http_statuses": [429, 500, 503]}}, "threshold": 0}
tags | {managed-by-ingress-controller}
algorithm | round-robin
host_header |
从Upstream
到Target
对请求进行处理的时候,主要有两项处理,一是进行负载均衡,二是调用插件进行处理。
一个Upstream
可以包含多个Target
,负载均衡的过程,就是为当前的请求选择一个Target
的过程
target
target
是IP
或者host
加port
,是提供服务的最小单位。每个tartget
还可设置不同的权重。
表结构
以下字段需要特殊注意:
字段 | 值 |
---|---|
upstream_id | tag对应的upstream表的主键 |
target | 转发目的的ip和port |
weight | 该target在整个upstream中所占的权重 |
kong=# \d targets
Table "public.targets"
Column | Type | Modifiers
-------------+--------------------------+---------------------------------------------------------------------------
id | uuid | not null
created_at | timestamp with time zone | default timezone('UTC'::text, ('now'::text)::timestamp(3) with time zone)
upstream_id | uuid |
target | text | not null
weight | integer | not null
tags | text[] |
Indexes:
"targets_pkey" PRIMARY KEY, btree (id)
"targets_tags_idx" gin (tags)
"targets_target_idx" btree (target)
"targets_upstream_id_idx" btree (upstream_id)
Foreign-key constraints:
"targets_upstream_id_fkey" FOREIGN KEY (upstream_id) REFERENCES upstreams(id) ON DELETE CASCADE
Triggers:
targets_sync_tags_trigger AFTER INSERT OR DELETE OR UPDATE OF tags ON targets FOR EACH ROW EXECUTE PROCEDURE sync_tags()
从表结构中可看出通过upstream_id
和upstreams
表进行关联。
示例
kong=# select * from targets where upstream_id='b85dd291-d561-4605-8771-2895c1decaa3';
-[ RECORD 1 ]-------------------------------------
id | f88f7a83-e973-4414-ae64-fd1b34e96a2a
created_at | 2022-10-30 11:53:16.174+00
upstream_id | b85dd291-d561-4605-8771-2895c1decaa3
target | 10.244.0.215:80
weight | 100
tags | {managed-by-ingress-controller}
由于本地环境中将kong
与k8s
进行结合,所以最终在环境上可通过target
获取出对应提供服务的Pod
[root@master-1 ~]# kubectl get pods -A -o wide | grep 10.244.0.215
nscloud /api/tembin/atsani 1/1 Running 1 23h 10.244.0.215 master-1 <none> <none>
至此就可以将对于/api/tembin/atsani
路径的请求转发至本机10.244.0.215
所对应的pod,完成请求的处理了。