[前言]:
Kong是一个云原生,高效,可扩展的分布式 API 网关。 自 2015 年在 github 开源后,广泛受到关注,目前已收获 1.68w+ 的 star,其核心价值在于高性能和可扩展性。
为什么需要 API 网关(more)
在微服务架构之下,服务被拆的非常零散,降低了耦合度的同时也给服务的统一管理增加了难度。如上图左所示,在旧的服务治理体系之下,鉴权,限流,日志,监控等通用功能需要在每个服务中单独实现,这使得系统维护者没有一个全局的视图来统一管理这些功能。API 网关致力于解决的问题便是为微服务纳管这些通用的功能,在此基础上提高系统的可扩展性。如右图所示,微服务搭配上 API 网关,可以使得服务本身更专注于自己的领域,很好地对服务调用者和服务提供者做了隔离。
为什么使用Kong
SpringCloud 玩家肯定都听说过 Zuul 这个路由组件,包括 Zuul2 和 Springcloud Gateway 等框架,在国内的知名度都不低。没错,我称呼这些为组件 Or 框架,而 Kong 则更衬的上产品这个词。在此我们可以简单对比下 Zuul 和 Kong。
举例而言,如果选择使用 Zuul,当需要为应用添加限流功能,由于 Zuul 只提供了基本的路由功能,开发者需要自己研发 Zuul Filter,可能你觉得一个功能还并不麻烦,但如果在此基础上对 Zuul 提出更多的要求,很遗憾,Zuul 使用者需要自行承担这些复杂性。而对于 Kong 来说,限流功能就是一个插件,只需要简单的配置,即可开箱即用。
Kong 的插件机制是其高可扩展性的根源,Kong 可以很方便地为路由和服务提供各种插件,网关所需要的基本特性,Kong 都如数支持:
- 云原生: 与平台无关,Kong可以从裸机运行到Kubernetes
- 动态路由:Kong 的背后是 OpenResty+Lua,所以从 OpenResty 继承了动态路由的特性
- 熔断
- 健康检查
- 日志: 可以记录通过 Kong 的 HTTP,TCP,UDP 请求和响应。
- 鉴权: 权限控制,IP 黑白名单,同样是 OpenResty 的特性
- SSL: Setup a Specific SSL Certificate for an underlying service or API.
- 监控: Kong 提供了实时监控插件
- 认证: 如数支持 HMAC, JWT, Basic, OAuth2.0 等常用协议
- 限流
- REST API: 通过 Rest API 进行配置管理,从繁琐的配置文件中解放
- 可用性: 天然支持分布式
- 高性能: 背靠非阻塞通信的 nginx,性能自不用说
- 插件机制: 提供众多开箱即用的插件,且有易于扩展的自定义插件接口,用户可以使用 Lua 自行开发插件
上面这些特性中,反复提及了 Kong 背后的 OpenResty,实际上,使用 Kong 之后,Nginx 可以完全摒弃,Kong 的功能是 Nginx 的父集。
而 Zuul 除了基础的路由特性以及其本身和 SpringCloud 结合较为紧密之外,并无任何优势。
Kong 的管理方式
Kong 简单易用的背后,便是其所有的操作都是基于 HTTP Restful API 来进行的。
其中 8000/8443 分别是 Http 和 Https 的转发端口,等价于 Nginx 默认的 80 端口,而 8001 端口便是默认的管理端口,我们可以通过 HTTP Restful API 来动态管理 Kong 的配置。
例:一个典型的 Nginx 配置
upstream helloUpstream { server localhost:3000 weight=100; } server { listen 80; location /hello { proxy_pass http://helloUpstream; } }
如上这个简单的 Nginx 配置,便可以转换为如下的 Http 请求。
对应的 Kong 配置:
# 配置 upstream curl -X POST http://localhost:8001/upstreams --data "name=helloUpstream" # 配置 target curl -X POST http://localhost:8001/upstreams/hello/targets --data "target=localhost:3000" --data "weight=100" # 配置 service curl -X POST http://localhost:8001/services --data "name=hello" --data "host=helloUpstream" # 配置 route curl -X POST http://localhost:8001/routes --data "paths[]=/hello" --data "service.id=8695cc65-16c1-43b1-95a1-5d30d0a50409"
这一切都是动态的,无需手动 reload nginx.conf。
从上面的配置及字面解释大概能够推测出他们的职责:upstream,target,service,route
,他们便是 Kong 最最核心的四个对象
upstream 是对上游服务器的抽象; target 代表了一个物理服务,是 ip + port 的抽象; service 是抽象层面的服务,他可以直接映射到一个物理服务(host 指向 ip + port),也可以指向一个upstream来做到负载均衡; route 是路由的抽象,他负责将实际的 request 映射到 service。
他们的关系如下:
- upstream 和 target :1 对 n
- service 和 upstream :1 对 1 或 1 对 0 (service 也可以直接指向具体的 target,相当于不做负载均衡)
- service 和 route:1 对 n
高可扩展性的背后—插件机制
Kong 的另一大特色便是其插件机制,这也是我认为的 Kong 最优雅的一个设计。
文章开始时我们便提到一点,微服务架构中,网关应当承担所有服务共同需要的那部分功能,这一节我们便来介绍下,Kong 如何添加 jwt 插件,限流插件。
插件(Plugins)装在哪儿?对于部分插件,可能是全局的,影响范围是整个 Kong 服务;大多数插件都是装在 service 或者 route 之上。这使得插件的影响范围非常灵活,我们可能只需要对核心接口进行限流控制,只需要对部分接口进行权限控制,这时候,对特定的 service 和 route 进行定向的配置即可
为 hello 服务添加50次/秒的限流
curl -X POST http://localhost:8001/services/hello/plugins \ --data "name=rate-limiting" \ --data "config.second=50"
为 hello 服务添加 jwt 插件
curl -X POST http://localhost:8001/services/login/plugins \ --data "name=jwt"
同理,插件也可以安装在 route 之上
curl -X POST http://localhost:8001/routes/{routeId}/plugins \ --data "name=rate-limiting" \ --data "config.second=50" curl -X POST http://localhost:8001/routes/{routeId}/plugins \ --data "name=jwt"
在官方文档中,我们可以获取全部的插件 https://konghq.com/plugins/,部分插件需要收费的企业版才可使用。
本文参考:
https://mp.weixin.qq.com/s/CWGy6cwy6QGLvwByurEGbw
https://www.jianshu.com/nb/27758849
[sleepy↓]