整合一套高性能网关Kong
前言
相信大家对Api网关都比较的熟悉,我们之前的文章也介绍过ASP.NET Core的网关Ocelot,也介绍过Spring Cloud Gateway。说到网关的主要功能,其实总结起来就两个字"统一",无论是作为应用的入口、认证授权、熔断限流等等主要都是为了统一的地方做一些事情。今天我们介绍一款性能更高的网关Kong,相对于Ocelot或Gateway这些类型的网关来说,Kong的优势是具有更高的性能,主要因为Kong是基于Nginx+Lua为核心的,接下来我们就详细介绍一下。
概念介绍
在使用Kong之前我们先来大致的介绍一下Kong是什么,Kong是基于OpenResty的开源网关。而OpenResty是基于Nginx与Lua的高性能Web平台。经常使用Nginx的同学们都知道,如果修改了Nginx的配置是需要重启Nginx的。而OpenResty让Nginx具备了动态编程的能力,使得Nginx成为了一个应用服务器软件,Kong正是基于OpenResty的,Nginx的性能不必多说,所以Kong可以理解为运行在Nginx上的高性能网关,在学习的过程中我们可以类比着Nginx进行了解。
Kong
说了这么多接下来我们大致介绍一下Kong自学三件套
- 官方Github地址:https://github.com/Kong/kong
- 官方网站地址:https://konghq.com/
- 开源版官方文档地址:https://docs.konghq.com/gateway-oss/为什么这里要说开源版呢,相信大家已经猜到了,因为它还有企业版、SaaS版、Ingress、Mesh等等,即有常规部署方式也有基于K8S和Mesh的方式,这里我们就不过多介绍了。
Kong有一点做的还是比较好的,无论是GitHub还是官方文档介绍的都比较详细,而且比较通俗易懂,这里我们就不过多的介绍了,有兴趣的同学可以自行了解一下。介绍完了自学三件套之后,接下来我们了解一下搭建一套Kong的几个组成部分,总结起来就是三个Kong服务、Kong依赖的存储、Kong可视化界面,下面我们大致的介绍一下。
- 首先是Kong服务,一套可以正常工作的Kong会包含两个对外提供服务的端口,一个是网关常规使用的端口,即对外提供访问的入口。另一个则是管理Kong的Admin端口,比如对Kong管理服务的增删改查以及Kong常用的Plugin管理以及一些常规的配置等,Kong的插件非常的丰富,基本上可以到达常规的一些操作比如限流、认证授权、链路跟踪、监控等都有而且形式非常的丰富。
- 其次是Kong存储服务,因为在Kong上配置的转发服务、插件、环境变量、认证等相关的信息都是需要存储的,但是外部存储不是必须的,Kong可以将这些信息存储到进程内的缓存中,但是重启Kong之后这些配置将会丢失,因此在正常的使用过程中我们总会给他提供一个外部数据库来存储这些信息。可供Kong使用的存储数据库也有好几个选择分别是Mysql、MongoDB、Postgresql等。本次演示我们使用的是Postgresql,也是官方推荐的方式。
- 最后是Kong的可视化UI,当然这个不是必须的。Kong提供了Admin管理接口的形式对服务和Plugin查看、新增、修改、删除等操作,但是有一个可视化的管理界面,无疑让有些操作变得更加简单清晰,而且这些可视化系统正式基于Kong的Admin接口开发的。可供选择的可视化UI也比较多,比较出名的有Konga、kong-ui、kong-admin-ui。本次演示我们选择的是Konga,也是推荐使用的最多的一个。
Konga
Konga并非Kong官方出品的可视化UI,但是它是最流行的一个,也是使用最多的一个,目前最新版本是v0.6.3。Konga是基于Nodejs开发的,它的Github地址是https://github.com/pantsel/konga,同样的Konga的GitHub文档上介绍的也非常的详细。它的部署方式有两种,一个是直接克隆GitHub上的仓库上的代码通过npm的方式运行,另一种则是使用docker的方式部署。两种方式都非常的简单,本次我们选择docker的方式。
环境搭建
关于Kong的搭建,官方网站给出了好几种部署方式可以基于Docker或K8S,也可以在Liunx操作系统Centos、Ubuntu、RHEL等都支持,目前最稳定版本为2.3.x,这些在官方文档上讲解的非常详细非常易懂,具体可参阅官方文档https://konghq.com/install/。如果想能快速的搭建起一套Kong+Postgresql+Konga
的环境,docker-compose无疑是一个比较好的选择,接下来我们将演示用过这种方式快速搭建起一条完整的Kong环境。
Kong官方GitHub有专门的docker-kong仓库地址为https://github.com/Kong/docker-kong,也已将这个仓库Clone下来,找到compose文件运行。但是我们这里还要整合可视化界面Konga,Konga并非官方出品,所以我要要修改一下compose文件整合进去Konga,完整的呈现如下所示
version: '3.3'
#创建kong_data卷
volumes:
kong_data: {}
#创建kong-net网络
networks:
kong-net:
external: false
services:
#数据库运行完成之后需要执行kong进行初始化操作
kong-migrations:
image: "${KONG_DOCKER_TAG:-kong:latest}"
command: kong migrations bootstrap
depends_on:
- db
environment:
KONG_DATABASE: postgres
KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong}
KONG_PG_HOST: db
KONG_PG_USER: ${KONG_PG_USER:-kong}
KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password
secrets:
- kong_postgres_password
networks:
- kong-net
restart: on-failure
deploy:
restart_policy:
condition: on-failure
#迁移过程依赖db
kong-migrations-up:
image: "${KONG_DOCKER_TAG:-kong:latest}"
command: kong migrations up && kong migrations finish
depends_on:
- db
environment:
KONG_DATABASE: postgres
KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong}
KONG_PG_HOST: db
KONG_PG_USER: ${KONG_PG_USER:-kong}
KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password
secrets:
- kong_postgres_password
networks:
- kong-net
restart: on-failure
deploy:
restart_policy:
condition: on-failure
# kong服务
kong:
image: "${KONG_DOCKER_TAG:-kong:latest}"
user: "${KONG_USER:-kong}"
depends_on:
- db
environment:
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: '0.0.0.0:8001'
KONG_CASSANDRA_CONTACT_POINTS: db
KONG_DATABASE: postgres
KONG_PG_DATABASE: ${KONG_PG_DATABASE:-kong}
KONG_PG_HOST: db
KONG_PG_USER: ${KONG_PG_USER:-kong}
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_PG_PASSWORD_FILE: /run/secrets/kong_postgres_password
secrets:
- kong_postgres_password
networks:
- kong-net
#kong的端口,非https使用8000和8001
ports:
- "8000:8000/tcp"
- "8001:8001/tcp"
- "8443:8443/tcp"
- "8444:8444/tcp"
#健康检查
healthcheck:
test: ["CMD", "kong", "health"]
interval: 10s
timeout: 10s
retries: 10
restart: on-failure
deploy:
restart_policy:
condition: on-failure
#konga可视化界面
konga:
image: pantsel/konga
networks:
- kong-net
depends_on:
- db
ports:
- "1337:1337/tcp"
environment:
TOKEN_SECRET: konga
DB_ADAPTER: postgres
DB_HOST: db
DB_PORT: 5432
DB_USER: kong
DB_PASSWORD: kong
DB_DATABASE: kong
restart: on-failure
deploy:
restart_policy:
condition: on-failure
# postgres数据库
db:
image: postgres:9.6
environment:
POSTGRES_DB: ${KONG_PG_DATABASE:-kong}
POSTGRES_USER: ${KONG_PG_USER:-kong}
POSTGRES_PASSWORD_FILE: /run/secrets/kong_postgres_password
secrets:
- kong_postgres_password
healthcheck:
test: ["CMD", "pg_isready", "-U", "${KONG_PG_USER:-kong}"]
interval: 30s
timeout: 30s
retries: 3
restart: on-failure
deploy:
restart_policy:
condition: on-failure
stdin_open: true
tty: true
ports:
- 5432:5432
networks:
- kong-net
volumes:
- kong_data:/var/lib/postgresql/data
# 用文件统一管理数据库密码
secrets:
kong_postgres_password:
file: ./POSTGRES_PASSWORD
通过docker-compose直接运行上面的yaml文件,便可以直接运行一套完整的kong项目,这里在强调一下上面说过GitHub上有官方专门提供的docker-kong仓库,直接Clone便可以直接得到运行Kong的yaml,但是本示例我们加入了Konga,如果需要可直接下载我修改后的包[点击下载👈]下载完成之后进入docker-compose.yml
所在的文件夹,执行docker-compose up -d
指令,首次的话会下载依赖的镜像文件可能稍微慢一点,出现如下界面的时候说明正常运行完成
{
"message": "no Route matched with those values"
}
因为我们没有配置任何路由规则,所以会提升匹配不到路由。然后我们在浏览器打开konga的地址http://localhost:1337/出现如下界面,则表示kong和konga运行成功
操作使用
通过上面的操作我们已经成功运行起来了Kong+Konga+Postgresql
的运行环境,然后我们就可以使用这套网关完成服务的转发相关的操作,常用的方式有两种,一种是通过Konga直接配置,另一种则是直接通过Kong服务的8001
端口访问管理的restful接口进行操作,当然Konga也是基于这套接口来操作的,接下来我们就来大致演示一下使用这两种方式完成相关操作。
通过Konga界面配置
打开Konga之后首次会让注册登录信息,注册完成之后会让完成Konga的配置连接操作,主要就是配置Kong的管理接口
首先配置Upstreams,由于kong本质处理请求还是通过nginx进行的,所以概念可以直接和nginx类比过来,其实就是是类似配置一个转发操作,这个操作既可以是一个服务地址,也可以是一组服务集合
那么Host就是是Upstream的名称或真实的访问目标地址名称
ADD ROUTE
会弹出添加Route信息的弹窗,主要配置Name、Host Paths Strip Path具体含义可看截图OrderService
服务里获取订单详情的地址为http://localhost:5001/order/get/1
,我们在通过网关访问OrderService的时候地址是http://localhost:8000/orderservice/order/get/1
,这种情况Path里的orderservice对我来说只是为了能访问到OrderService的一个路径标识,真实服务OrderService的时候并不需要,这个时候我就可以设置Strip Path的值为true
,这样在转发地址的时候就不会在Url上带上orderservice这个标识了。到这里,关于通过Konga配置的常用操作介绍的就差不多了,截图上也标注了常用字段的含义,想更详细的了解还需要自己搭建一套Konga实操一下。
通过Kong的Admin接口配置
上面我们介绍了通过Konga的方式配置Kong的服务,我们开始的时候也说过,Konga也是通过Kong Admin API的接口完成对服务的增删改查的操作的,Kong Admin API是Kong自带的管理接口,通过这些接口我们可以通过更原生的方式去操作Kong。而且如果你通过Konga配置的时候不太了解哪些字段是必须的,或者需要理解每个字段详细代表的含义,这时候就可以通过原生的接口了解,这样有助于更深刻的了解。Admin API的官方文档地址位于https://docs.konghq.com/gateway-oss/2.3.x/admin-api/文档介绍的非常的详细,接下来我们就大致的介绍Admin API的一些常规操作。
- 默认情况Admin API的监听端口是8001,如果是https的话默认为8444
- API可接收的内容格式即ContentType为application/json、application/x-www-form-urlencoded、multipart/form-data
- Kong Admin API是标准的Restful风格的接口,这对于我们操作来说非常的便捷
由于Admin API官方文档介绍的非常详细了,这里咱们就不一一的介绍了,咱们这里简单的介绍一下有代表性的接口和一些注意相关的操作。强烈建议,学习Kong的话一定要看这个文档,这样的话能解决很多的困惑。首先介绍Service的List的接口,这个接口是返回注册在Kong上的所有Service
- 请求方式是
curl http://localhost:8001/services
- 成功的状态码为
HTTP 200 OK
- 返回的json格式代表的含义,文档中介绍的也非常详细
{
"data": [{
"id": "a5fb8d9b-a99d-40e9-9d35-72d42a62d83a",
"created_at": 1422386534,
"updated_at": 1422386534,
"name": "my-service",
"retries": 5,
"protocol": "http",
"host": "example.com",
"port": 80,
"path": "/some_api",
"connect_timeout": 60000,
"write_timeout": 60000,
"read_timeout": 60000,
"tags": ["user-level", "low-priority"],
"client_certificate": {"id":"51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"},
"tls_verify": true,
"tls_verify_depth": null,
"ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"]
}],
"next": "http://localhost:8001/services?offset=6378122c-a0a1-438d-a5c6-efabae9fb969"
}
data为数据结果,next是下一批数据查询的地址。这一点做得还是考虑的比较周全的,如果Service比较多的话,一次性返回不是一个明智的操作,通过判断next的方式可以知道是否存在分页的情况,根据判断状态码可以知道请求是否成功。
其次Service还有一个检索接口,它主要用于返回指定的Service信息,它的请求方式是curl http://localhost:8001/services/{service name or id}
,如果返回的状态码为404
则说明服务没有被注册过,如果服务存在则状态码为200
并返回服务详情的json。
还有一个比较实用的接口是Update Or Create Service
翻译过来就是修改或创建,即如果Service存在则执行更新操作,如果不存在则直接创建一个Service。试着想一下,如果不存在这个接口,我们每次注册Service之前还要调用一下检索接口判断一下Service是否被注册过。
请求方式是curl -X PUT -H "Content-Type: application/json" -d '{}' "http://localhost:8001/services/{service name or id}"
它的请求数据格式和Add的是一样的只是请求方式是PUT
它的数据格式是
{
"id": "9748f662-7711-4a90-8186-dc02f10eb0f5",
"created_at": 1422386534,
"updated_at": 1422386534,
"name": "my-service",
"retries": 5,
"protocol": "http",
"host": "example.com",
"port": 80,
"path": "/some_api",
"connect_timeout": 60000,
"write_timeout": 60000,
"read_timeout": 60000,
"tags": ["user-level", "low-priority"],
"client_certificate": {"id":"4e3ad2e4-0bc4-4638-8e34-c84a417ba39b"},
"tls_verify": true,
"tls_verify_depth": null,
"ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"]
}'
它返回的结果是HTTP 201 Created or HTTP 200 OK
这里需要特别注意的是Add相关的接口返回的Http是HTTP 201 Created
我们就通过关于Service的操作,大致介绍一下关于Admin API的大致操作方式,关于每一个Service、Route、Upstream、Target的操作都有完整的增删改查接口,咱们上面介绍的是除了这些之外实用操作的接口。这里还需要注意的是有些操作是有关联关系的,比如Service和Route的操作,Upstream和Target的操作,因此在实际通过接口开发的过程中要注意对Service的Id或Upstream的Id的保存。
因为Kong对注册中心这些比如Consul、Eureka、Nacos这种支持的并不是很完善,虽然Kong支持自己编写Lua脚本的方式完成这些操作,但是这些编写成本还是比较高的,所以这个时候Admin API就显得格外的实用。
总结
本次我们主要讲解了对Kong的大致入门操作,相信很多同学都听说过或者用过它,我个人觉得Kong这种级别的组件很多时候能了解它的大致场景和结构并能搭建出来一套可运行的环境,那么入门就已经完成一半了。我觉得Kong做的比较好的一点是,它的学习文档和GitHub仓库上的一些操作都非常的完整而且很详细。我每次写这种类型的文章其实初衷都非常的简单,就是能让对这些东西有兴趣的同学,能通过这篇文章入门,算是能有一个好的开始吧。