为什么需要 API 网关
在微服务架构之下,服务被拆的非常零散,降低了耦合度的同时也给服务的统一管理增加了难度。如上图左所示,在旧的服务治理体系之下,鉴权,限流,日志,监控等通用功能需要在每个服务中单独实现,这使得系统维护者没有一个全局的视图来统一管理这些功能。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关键术语/名词解析
Upstream
Upstream 对象表示虚拟主机名,可用于通过多个服务(目标)对传入请求进行负载均衡。例如:service.v1.xyz 为 Service 对象命名的上游 Host 是 service.v1.xyz 对此服务的请求将代理到上游定义的目标。
Target
目标 IP地址/主机名,其端口表示后端服务的实例。每个上游都可以有多个 Target,并且可以动态添加 Target。
由于上游维护 Target 的更改历史记录,因此无法删除或者修改 Target。要禁用目标,请发布一个新的 Targer weight=0,或者使用 DELETE 来完成相同的操作。
Service
顾名思义,服务实体是每个上游服务的抽象。服务的示例是数据转换微服务,计费API等。
服务的主要属性是它的 URL(其中,Kong 应该代理流量),其可以被设置为单个串或通过指定其 protocol, host,port 和path。
服务与路由相关联(服务可以有许多与之关联的路由)。路由是 Kong 的入口点,并定义匹配客户端请求的规则。一旦匹配路由,Kong 就会将请求代理到其关联的服务。
Route
路由实体定义规则以匹配客户端的请求。每个 Route 与一个 Service 相关联,一个服务可能有多个与之关联的路由。与给定路由匹配的每个请求都将代理到其关联的 Service 上。可以配置的字段有:
hosts
paths
methods
Service 和 Route 的组合(以及它们之间的关注点分离)提供了一种强大的路由机制,通过它可以在 Kong 中定义细粒度的入口点,从而使基础架构路由到不同上游服务。
Consumer
Consumer 对象表示服务的使用者或者用户。你可以依靠 Kong 作为主数据库存储,也可以将使用者列表与数据库映射,以保持Kong 与现有的主数据存储之间的一致性。
Plugin
插件实体表示将在 HTTP请求/响应生命周期 期间执行的插件配置。它是为在 Kong 后面运行的服务添加功能的,例如身份验证或速率限制。
将插件配置添加到服务时,客户端向该服务发出的每个请求都将运行所述插件。如果某个特定消费者需要将插件调整为不同的值,你可以通过创建一个单独的插件实例,通过 service 和 consumer 字段指定服务和消费者。
对应关系
Upstream : target -> 1:n
Service : Upstream -> 1:1 or 1:0 (Service 可以直接指向具体的 Target,相当于不做负载均衡)
Service : Route -> 1:n
Client 请求的流量通过 Route 指向与之相关的 Service,如果配置插件的话就会作用插件,Service 接到流量后给到相应的 Upstream 的服务上面。
Kong的管理方式
通过文件夹结构的分析,以及数据库中的表结构,我们已经对 Kong 的整体架构有了一个基本的认识,但肯定还存在一个疑问:我会配置 Nginx 来控制路由,但这个 Kong 应当怎么配置才能达到相同的目的呢?莫急,下面来看看 Kong 如何管理配置。
Kong 简单易用的背后,便是因为其所有的操作都是基于 HTTP Restful API 来进行的。
kong端点
其中 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;
}
}
对应的 Kong restful-api 配置
# 配置 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"
curl -X POST http://localhost:8001/routes --data "hosts[]=a.com,b.com,*.abc.com" --data "service.id=8695cc65-16c1-43b1-95a1-5d30d0a50409"
这一切都是动态的,无需手动 reload nginx.conf。
KongA -> 第三方Kong管理界面
KongA 带来的一个最大的便利就是可以很好地通过UI观察到现在 Kong 的所有的配置,并且可以对于管理 Kong 节点情况进行查看、监控和预警,KongA 主要特性如下:
- 多用户管理
- 管理多个 Kong 节点
- 电子邮件异常信息通知
- 管理所有Kong Admin API
- 使用快照备份,还原和迁移Kong节点
- 使用运行状况检查监控节点和API状态
- 轻松的数据库集成(MySQL,postgresSQL,MongoDB)
评论区