安装测试

使用 docker 搭建 kong 测试环境.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
## 创建 postgre 数据库, 没有密码
docker run -d \
--name kong-database \
-p 5432:5432 \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_DB=kong" \
-e "POSTGRES_HOST_AUTH_METHOD=trust" \
postgres:9.6

## db init
docker run --rm \
--link kong-database:kong-database \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
kong kong migrations bootstrap

## 创建容器并运行
docker run -d --name kong \
--link kong-database:kong-database \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=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 \
kong

## konga kong 管理端
## konga 数据库准备
docker run --rm \
--link kong-database:kong-database \
pantsel/konga -c prepare -a postgres -u postgresql://kong@kong-database:5432/konga_db

--network=kong-net \

## konga 启动
docker run -d -p 1337:1337 \
--link kong-database:kong-database \
-e "DB_ADAPTER=postgres" \
-e "DB_HOST=kong-database" \
-e "DB_USER=kong" \
-e "DB_DATABASE=konga_db" \
-e "KONGA_HOOK_TIMEOUT=120000" \
-e "NODE_ENV=production" \
--name konga \
pantsel/konga

# 访问 konga
http://127.0.0.1:1337

# kong 运行
docker start kong
docker stop kong
# 杀掉容器
docker kill kong
# 删除容器
docker rm kong
docker rm kong-database
docker attach --sig-proxy=false kong

# 进入容器内
docker exec -it kong /bin/bash

# kong-docker 日志输出在终端, 使用 docker log 查看日志
docker log -f kong

docker ps -a

# 通过 konga 添加 service, route, upstream.
# 添加服务
curl -i -X POST \
--url http://localhost:8001/services/ \
--data 'name=example-service' \
--data 'url=http://mockbin.org'

# 添加路由
curl -i -X POST \
--url http://localhost:8001/services/example-service/routes \
--data 'hosts[]=example.com'

# 测试命令
curl -i -X GET \
--url http://localhost:8000/ \
--header 'Host: example.com'

curl -i \
-H "Host: echo_server" \
http://10.161.112.28:8000/a

curl -i \
-H "Host: echo-ip" \
http://10.161.112.28:8000/a

概述

kong 有三个核心概念: route, service, upstream. upstream 管理后端服务负载, route 用来匹配客户端请求, service 用来将两者进行耦合, 所有的 route 必须归属于 service, 由 service 确定 upstream.

Kong 在 access 阶段进行路由匹配, 关键函数是 router.lua::exec. 在 access.after 阶段进行 balancer 处理, 确定使用的 upstream, target. upstream 定义负载选择方法和健康检查信息, target 定义负载主机信息.

路由匹配

路由匹配核心是根据请求特征查找 service.

在请求处理 access 阶段会进行路由匹配(kong/runloop/handler.lua::access.before), 路由匹配核心是 kong/router.lua 库. kong 将所有路由放在表中进行处理.

access.before 阶段还会根据 service 数据进行负载均衡预处理.

负载均衡

kong 支持三种负载管理: DNS, Upstream, IP. 在 service 中配置的 host 如果在 Upstream 能找到, 则使用 Upstream 中的负载作为转发后端; 如果未找到, 则使用 DNS 进行解析, 使用得到的机器作为转发后端. 如果在 service 中配置的是 IP 地址, 则直接使用 IP 地址作为转发后端.

kong/runloop/balancer.lua::attach_healthchecker_to_balancer 函数中注册了健康检查回调, 在负载健康检查状态发生变化时通过回调调用 balancer:setAddressStatus 将负载置为可用或不可用.

函数 setAddressStatus 定义在 resty/dns/balancer 库中.

插件处理

除了插件自身的功能外需要考虑两点: 插件如何与路由绑定, 每个路由的插件配置是否相同.
init worker 阶段会执行 update_plugins_iterator 创建全局插件迭代器 plugins_iterator.
在请求处理过程中, kong 会在 rewrite 阶段会调用 execute_plugins_iterator 遍历插件调用 rewrite 阶段处理函数. rewrite 阶段是首次调用插件迭代器, 请求与插件匹配逻辑是在插件迭代器中实现(kong/runloop/plugins_iterator.lua::get_next 函数).