[转载]选择Kong作为你的API网关

更新,现在有更强大的API网关,国产 Apache APISIX,可自行谷歌。

本文转载自选择Kong作为你的API网关

Kong(https://github.com/Kong/kong)是一个云原生,高效,可扩展的分布式 API 网关。 自 2015 年在 github 开源后,广泛受到关注,目前已收获 1.68w+ 的 star,其核心价值在于高性能和可扩展性。

为什么需要 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 的架构

从技术的角度讲,Kong 可以认为是一个 OpenResty 应用程序。 OpenResty 运行在 Nginx 之上,使用 Lua 扩展了 Nginx。 Lua 是一种非常容易使用的脚本语言,可以让你在 Nginx 中编写一些逻辑操作。之前我们提到过一个概念 Kong = OpenResty + Nginx + Lua,但想要从全局视角了解 Kong 的工作原理,还是直接看源码比较直接。我们定位到本地的 Kong 文件夹,按照上图中的目录层级来识识 Kong 的庐山真面目。

  1. Kong 文件下包含了全部源码和必要组件,分析他们,我们便得到了 Kong 的架构。0.13.x 是目前 Kong 的最新版本。
  2. 从 2 号块中可以看到 nginx.conf ,这其实便是一个标准的 Nginx 目录结构,这也揭示了 Kong 其实就是运行在 Nginx 的基础之上,而进行的二次封装。由 share 文件夹向下展开下一次分析。
  3. share 文件夹中包含了 OpenResty 的相关内容,其实背后就是一堆 Lua 脚本,例如 lapis 包含了数据库操作,Nginx 生命周期,缓存控制等必要的 Lua 脚本,logging 包含了日志相关的 Lua 脚本,resty 包含了 dns,健康检查等相关功能的 Lua 脚本…而其中的 kong 目录值得我们重点分析,他包含了 Kong 的核心对象。
  4. api 和 core 文件夹,封装了 Kong 对 service,route,upstream,target 等核心对象的操作代码(这四个核心对象将会在下面的小节重点介绍),而 plugins 文件夹则是 Kong 高可扩展性的根源,存放了 kong 的诸多扩展功能。
  5. plugins 文件夹包含了上一节提到的 Kong 的诸多插件功能,如权限控制插件,跨域插件,jwt 插件,oauth2 插件…如果需要自定义插件,则需要将代码置于此处。

从上述文件夹浏览下来,大概可以看到它和 Nginx 的相似之处,并在此基础之上借助于 Lua 对自身的功能进行了拓展,除了 nginx.conf 中的配置,和相对固定的文件层级,Kong 还需要连接一个数据库来管理路由配置,服务配置,upstream 配置等信息,是的,由于 Kong 支持动态路由的特性,所以几乎所有动态的配置都不是配置在文件中,而是借助于 Postgres 或者 Cassandra 进行管理。

Kong 对外暴露了 Restful API,最终的配置便是落地在了数据库之中。

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;
  }
}

如上这个简单的 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"
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。

我们为 Kong 新增路由信息时涉及到了 upstream,target,service,route 等概念,他们便是 Kong 最最核心的四个对象。(你可能在其他 Kong 的文章中见到了 api 这个对象,在最新版本 0.13 中已经被弃用,api 已经由 service 和 route 替代)

从上面的配置以及他们的字面含义大概能够推测出他们的职责,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/,部分插件需要收费的企业版才可使用。

总结

Kong 是目前市场上相对较为成熟的开源 API 网关产品,无论是性能,扩展性,还是功能特性,都决定了它是一款优秀的产品,对 OpenResty 和 Lua 感兴趣的同学,Kong 也是一个优秀的学习参考对象。基于 OpenResty,可以在现有 Kong 的基础上进行一些扩展,从而实现更复杂的特性,比如我司内部的 ABTest 插件和定制化的认证插件,开发成本都相对较低。Kong 系列的文章将会在以后持续连载。


阅读扩展

初识 Kong 之负载均衡 https://www.cnkirito.moe/kong-loadbalance/

Kong 集成 Jwt 插件 https://www.cnkirito.moe/kong-jwt/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容