Kong 是 Mashape 开源的一款云原生架构下的分布式 API 网关,其性能和可扩展性在同类组件中,表现都很优异。Kong 官方提供了很多直接可用的插件,此外,Kong 还可以通过插件扩展已有功能。
本文的主要内容:
- 什么是云原生网关?
- Kong 介绍
- Kong 的基本架构
- 使用 Kong 构建服务网关
- 几种常用插件应用
- 自定义插件的实践
什么是云原生网关
什么是云原生
在介绍云原生网关的概念之前,首先谈谈关于云原生的具体定义。关于云原生的定义,仁者见仁智者见智。
Pivotal 是云原生应用的提出者,并推出了 Pivotal Cloud Foundry 云原生应用平台和 Spring 开源 Java 开发框架,成为云原生应用架构中先驱者和探路者。Pivotal 公司的 Matt Stine 关于云原生应用架构的定义,提出来几个主要特征:
- 符合12因素应用
- 面向微服务架构
- 自服务敏捷架构
- 基于API的协作
- 抗脆弱性
随着技术的发展,云原生的概念也在不断的完善。云原生的定义未来还会变,本文参考 CNCF V1.0 的定义:
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。
因此,云原生网关很重要的特性之一,就是能够快速集成到持续发布的云原生环境中。
为什么需要 API 网关?
当使用单体应用程序架构时,客户端(Web 或移动端)通过向后端应用程序发起一次 REST 调用来获取数据。负载均衡器将请求路由给 N 个相同的应用程序实例中的一个。然后应用程序会查询各种数据库表,并将响应返回给客户端。微服务架构下,单体应用被切割成多个微服务,如果将所有的微服务直接对外暴露,势必会出现安全方面的各种问题。
客户端可以直接向每个微服务发送请求,其问题主要如下:
- 客户端需求和每个微服务暴露的细粒度 API 不匹配。
- 部分服务使用的协议不是Web友好协议。可能使用 Thrift 二进制 RPC,也可能使用 AMQP 消息传递协议。
- 微服务难以重构。如果合并两个服务,或者将一个服务拆分成两个或更多服务,这类重构就非常困难了。
服务端的各个服务直接暴露给客户端调用势必会引起各种问题。同时,服务端的各个服务可扩展和伸缩性很差。API 网关是微服务架构中的基础组件,位于接入层之下和业务服务层之上,如前所述的这些功能适合在 API 网关实现。
关于服务网关的开源组件,有 Netflix Zuul、Spring Cloud Gateway、Kong、Traefik、NGINX 和服务网关类型的 Envoy 等。在之前的文章已经介绍过可编程的新型网关:Spring Cloud Gateway,需要了解的读者可以查看 Spring Cloud Gateway。本文主要介绍现代微服务网关 Kong,在 Kong 的官网介绍中,第一条特性便是 Kong 的云原生属性:与平台无关,Kong 可以从裸机运行到 Kubernetes。本文基于 Kong 1.2.1,自定义插件部分会涉及部分 Lua 编码,适合服务端开发和运维人员。
Kong 介绍
Mashape 开源的高性能高可用 API 网关和 API 服务管理层——KONG(基于NGINX)特点尤为突出,它可以通过插件扩展已有功能,这些插件(使用 lua 编写)在 API 请求响应循环的生命周期中被执行。与此同时,KONG 本身提供包括HTTP基本认证、密钥认证、CORS、TCP、UDP、文件日志、API请求限流、请求转发及NGINX监控等基本功能。目前,Kong 在 Mashape 管理了超过 15,000 个 API,为200,000开发者提供了每月数十亿的请求支持。
- 什么是 Kong 当我们决定对应用进行微服务改造时,应用客户端如何与微服务交互的问题也随之而来,毕竟服务数量的增加会直接导致部署授权、负载均衡、通信管理、分析和改变的难度增加。 面对以上问题,API GATEWAY是一个不错的解决方案,其所提供的访问限制、安全、流量控制、分析监控、日志、请求转发、合成和协议转换功能,可以解放开发者去把精力集中在具体逻辑的代码,而不是把时间花费在考虑如何解决应用和其他微服务链接的问题上。
- 为什么使用Kong 在众多 API GATEWAY 框架中,Mashape 开源的高性能高可用API网关和API服务管理层——KONG(基于 NGINX)特点尤为突出,它可以通过插件扩展已有功能,这些插件(使用 lua 编写)在API请求响应循环的生命周期中被执行。于此同时,KONG本身提供包括 HTTP 基本认证、密钥认证、CORS、TCP、UDP、文件日志、API请求限流、请求转发及 NGINX 监控等基本功能。目前,Kong 在 Mashape 管理了超过 15,000 个 API,为 200,000 开发者提供了每月数十亿的请求支持。
Kong 的基本架构
Kong 是 Mashape 开源的高性能高可用 API 网关和 API 服务管理层,一款基于 Nginx_Lua 模块写的高可用服务网关,由于 Kong 是基于 Nginx 的,所以可以水平扩展多个 Kong 服务器。通过前置的负载均衡配置把请求均匀地分发到各个 Server,来应对大批量的网络请求。
图片来源 Kong 官网
Kong 主要有三个组件:
- Kong Server :基于nginx的服务器,用来接收 API 请求。
- Apache Cassandra/PostgreSQL:用来存储操作数据。
- Kong dashboard:官方推荐 UI 管理工具,当然,也可以使用 restfull 方式管理 admin api。
Kong 采用插件机制进行功能定制,插件集(可以是 0 或 N 个)在 API 请求响应循环的生命周期中被执行。插件使用 Lua 编写,基础功能包括:HTTP 基本认证、密钥认证、CORS(Cross-Origin Resource Sharing,跨域资源共享)、TCP、UDP、文件日志、API 请求限流、请求转发以及 Nginx 监控等。
Kong 网关具有以下的特性:
- 可扩展性: 通过简单地添加更多的服务器,可以轻松地进行横向扩展,这意味着您的平台可以在一个较低负载的情况下处理任何请求;
- 模块化: 可以通过添加新的插件进行扩展,这些插件可以通过RESTful Admin API轻松配置;
- 在任何基础架构上运行: Kong 网关可以在任何地方都能运行。可以在云或内部网络环境中部署 Kong,包括单个或多个数据中心设置,以及 public,private 或 invite-only APIs。
术语
Kong 中常用的术语介绍,这些术语会在下面的实践中经常用到。
- Route:请求的转发规则,按照 Hostname 和 PATH,将请求转发给 Service;
- Services:多个 Upstream 的集合,是 Route 的转发目标;
- Consumer:API 的用户,记录用户信息;
- Plugin:插件,可以是全局的,也可以绑定到 Service、Router 或者 Consumer;
- Certificate:https 配置的证书;
- Sni:域名与 Certificate 的绑定,指定了一个域名对应的 https 证书;
- Upstream:上游对象用来表示虚拟主机名,拥有多个服务(目标)时,会对请求进行负载均衡;
- Target:最终处理请求的 Backend 服务。
使用 Kong 构建服务网关
客户端的请求将会首先经由微服务网关处理,一些通用的功能切面将会在网关生效,即 Kong 中的插件,之后才会将请求进行转发到对应的 Backend 服务,如下图所示。
图片来源 https://konghq.com/blog/kong-1-0-ga/
在介绍了为什么需要微服务网关和 Kong 的相关概念之后,我们将会进行实战,使用 Kong 构建网关。
安装实践
目前 Kong 的最新版本 1.2,Kong 的安装支持多种方式。官方支持如下列出方式的安装:
图片来源 Kong 官网
除了官方提供的安装方式,还有社区提供的安装方式,详细了解参见:https://konghq.com/install/。
笔者为了方便,基于 docker 的方式安装。docker-compose.yml 中定义的镜像、依赖和参数如下所示:
代码语言:javascript复制version: "3.7"
services:
kong:
image: kong:1.1.2
environment:
- "KONG_DATABASE=postgres"
- "KONG_PG_HOST=kong-database"
- "KONG_CASSANDRA_CONTACT_POINTS=kong-database"
- "KONG_PROXY_ACCESS_LOG=/dev/stdout"
- "KONG_ADMIN_ACCESS_LOG=/dev/stdout"
- "KONG_PROXY_ERROR_LOG=/dev/stderr"
- "KONG_ADMIN_ERROR_LOG=/dev/stderr"
- "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl"
ports:
- 8000:8000
- 8443:8443
- 8001:8001
- 8444:8444
networks:
- kong-net
depends_on:
- kong-database
konga:
image: pantsel/konga
environment:
- "TOKEN_SECRET=blueskykong.com"
- "NODE_ENV=production"
ports:
- 8080:1337
networks:
- kong-net
depends_on:
- kong-database
kong-database:
image: postgres:9.6
ports:
- "5432:5432"
environment:
- POSTGRES_USER=kong
- POSTGRES_DB=kong
networks:
- kong-net
volumes:
- /etc/localtime:/etc/localtime:ro
- /data/data/postgresql:/var/lib/postgresql/data
networks:
kong-net:
external: true
如上的 docker-compose.yml 会启动三个容器服务:Kong、konga 和 kong-database。这三个容器之间的通信需要增加 network 段,把容器放在同一个网段内,相关链接修改为容器名称来访问:
代码语言:javascript复制docker network create kong-net
所启动的三个容器服务,除了 Kong 之外的两个服务:konga 是 Kong 的 Dashboard,基于 js 的客户端管理工具,对外暴露的端口为 8080;kong-database 是 Kong 的数据库服务,存储配置信息,这里使用的是 postgres。需要注意的是,在启动 Kong 容器之前,需要保持数据库的 Docker 容器在运行状态,并执行如下初始化数据库的操作:
代码语言:javascript复制docker run --rm
--network=kong-net
-e "KONG_DATABASE=postgres"
-e "KONG_PG_HOST=kong-database"
kong:latest kong migrations bootstrap
数据库初始化成功后,再次启动 docker-compose.yml 服务就可以了。我们看到 Kong 映射出多个端口,默认情况下,Kong 监听的端口为:
- 8000:此端口是 Kong 用来监听来自客户端传入的 HTTP 请求,并将此请求转发到上有服务器;(Kong 根据配置的规则转发到真实的后台服务地址)
- 8443:此端口是 Kong 用来监听来自客户端传入的HTTPS请求的。它跟8000端口的功能类似,转发 HTTPS 请求的。可以通过修改配置文件来禁止它;
- 8001:Admin API,通过此端口,管理者可以对 Kong 的监听服务进行配置,插件设置、API 的增删改查、以及负载均衡等一系列的配置都是通过 8001 端口进行管理;
- 8444:通过此端口,管理者可以对 HTTPS 请求进行监控。
容器都启动好之后,我们来验证一下:
代码语言:javascript复制curl -i http://localhost:8001/
HTTP/1.1 200 OK
Date: Sat, 20 Jul 2019 08:39:08 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/1.1.2
Content-Length: 5785
...
如上的结果,表示安装正确,可以正常使用 Kong。访问 http://localhost:8080 访问 Konga 的管理界面,第一次登录使用需要创建管理员帐号和密码。
更多内容参照官网的安装文档。至此,Kong 以及管理工具都已安装完成,下面将进入 API Gateway 的具体实践。
创建服务
如我们在术语部分的介绍,服务是上游服务的抽象,可以是一个应用,或者具体某个接口。Kong 提供了管理接口,我们可以通过请求 8001 管理接口直接创建,也可以通过安装的管理界面,实现的效果是一样的。
代码语言:javascript复制curl -i -X POST
--url http://localhost:8001/services/
--data 'name=aoho-blog'
--data 'url=http://blueskykong.com/'
我们创建一个服务名为 aoho-blog
,指定转发的地址为 http://blueskykong.com
。可以在管理界面中看到如下的记录:
其中的一些参数,如 Retries、Connect timeout、Write/Read timeout 等参数。
创建路由
创建好服务之后,我们需要创建具体的 API 路由。路由是请求的转发规则,根据 Hostname 和 PATH,将请求转发。
代码语言:javascript复制curl -i -X POST
--url http://localhost:8001/services/aoho-blog/routes
--data 'hosts[]=blueskykong.com'
--data 'paths[]=/api/blog'
如上在 aoho-blog 中创建了一个访问 /api/blog 的路由,在管理界面可以看到相应的记录:
创建好路由之后,我们就可以访问 /api/blog。
Kong 默认通过 8000 端口处理代理的请求。成功的响应意味着 Kong 将 http://localhost:8000
的请求转发到配置的 URL,并将响应转发给我们。需要注意的是,如果 API 暴露的地址与前面 Host 定义的地址(blueskykong.com)不一致,就需要在请求的 Headers 里面加入 Header,Kong 根据上面请求中定义的 Header:Host,执行此操作。
小结
本文主要介绍了云原生和云原生网关的相关概念,随后具体介绍了本文的主角 Kong 的特性和基本架构。重点介绍了如何使用 Kong 构建服务网关。Kong 官方和社区提供了很多插件,关于 Kong 中的常用插件使用,以及如何定制自己的 Kong 插件,将会在下文讲解。