花椒直播Kong应用实践
摘要:kong/templates/nginx_kong.lua 模板文件统一。local body_filter = require "kong.plugins.my-custom-plugin.body_filter"。
什么是Kong
Kong 是面向现代架构(混合云,混合组织)的下一代 API 网关平台,具有云原生、高性能,易用、可扩展等特性。
适用于 Api Gateway, Kubernetes Ingress, Service Mesh Sidecar 等场景。
主要特性有:
-
云原生: 与平台无关,Kong 可以从裸机运行到 Kubernetes
-
高性能: 背靠非阻塞通信的 nginx,性能自不用说
-
插件机制: 提供众多开箱即用的插件,且有易于扩展的自定义插件接口,用户可以使用 Lua 自行开发插件
-
熔断:可以通过插件实现熔断,避免系统雪崩
-
日志: 可以记录通过 Kong 的 HTTP,TCP,UDP 请求和响应。
-
鉴权: 权限控制,IP 黑白名单,同样是 OpenResty 的特性
-
SSL: Setup a Specific SSL Certificate for an underlying service or API.
-
监控: Kong 提供了实时监控插件
-
认证: 如数支持 HMAC, JWT, Basic, OAuth 2.0 等常用协议
-
限流:可以通过插件实现单个服务某些接口的限流,避免服务过载导致不可用
-
REST API: 通过 Rest API 进行配置管理,从繁琐的配置文件中解放
-
健康检查:自动检查,被动检查;节点不可用同步到所有的kong节点需要 1 - 2 秒
-
动态路由:Kong 的背后是 OpenResty+Lua,所以从 OpenResty 继承了动态路由的特性
为什么使用Kong
目前我们需要解决的问题
-
统一入口: 服务端微服务框架中,接口权限验证,ip限制,限流等在各个服务中都单独实现。没有统一入口,不方便统一管理。
-
易用性,扩展性: 服务端技术栈主要是LNMP开发,目前在逐步转型到基于Spring Boot、Spring Clound 微服务技术栈上开发。这是一个灰度迁移的过程,我们需要Proxy能操作简单,管理方便。
-
持续集成发布: 互联网 2C 产品,用户无时不刻不在使用服务,同时产品还在不断的迭代,服务每时每刻都可以发布,所以必须要热部署能力,并且是自动化的。但是基于Spring Boot的服务启动 15 -30 秒,我们需要 Kong 的蓝绿发布功能。
Kong 可以完美的解决以上问题,解决方案如下:
-
统一入口: 可以作为微服务统一入口,将限流,权限验证,日志,ip 限制等统一实现
-
易用性,扩展性:提供了Restful操作方式,并且有dashboard管理工具
# 创建一个名称 hello 的 upstream
curl -X POST http://localhost:8001/upstreams --data "name=hello"
# 为 hello 添加两个负载均衡节点
curl -X POST http://localhost:8001/upstreams/hello/targets --data "target=localhost:8080" --data "weight=100"
curl -X POST http://localhost:8001/upstreams/hello/targets --data "target=localhost:8081" --data "weight=100"
# 配置一个service
curl -X POST http://localhost:8001/services --data "name=hello" --data "host=hello"
# 为service 配置路由
curl -X POST http://localhost:8001/routes --data "paths[]=/hello" --data "service.id={$service.id 配置上面service返回的}"
dashboard工具截图
-
持续集成发布:与 GitLab CI/CD 配合,代码提交代码库后,自动打包,运行测试用例,蓝绿部署。
我们如何使用Kong
1
Kong集群
-
所有节点连接到数据中心
-
使用 Postgresql 主从机制,保证数据库高可用,注意使用9.6以上版本
所有节点将周期性执行任务,同步数据最终一致
-
配置选项: db_update_frequency (默认: 5 秒)
-
每 db_update_frequency 秒,所有节点将从数据库中拉取所有更新,如果有同步到更新变化,将清理本地相关缓存。
-
如果 Postgresql 数据库异常,节点使用原有数据还可以提供服务
节点有本地缓存,可以设置缓存过期时间
-
配置选项: db_cache_ttl (default: 0s)
-
当数据中心异常,依赖本地缓存依旧可以提供服务
支持动态扩容,参考上方架构图,Kong集群在Lvs后面
-
新增节点,同步其他节点配置后,验证正常,加到到Lvs的RS里即可,就提供服务了
-
删除节点,直接将 Lvs 的 RS 删除即可,他就不提供服务了
-
修改节点配置,先从 Lvs 后摘除kong RS, 修改完成后重启,验证正常,放回到 Lvs 的 RS 里面
支持 gRPC
# /etc/kong/kong.conf
proxy_listen = 0.0.0.0:8000, 0.0.0.0:8443 ssl, 0.0.0.0:9080 http2
服务监控
-
使用prometheus,grafana和Kong天然配合
注意事项
-
kong/templates/nginx_kong.lua 模板文件统一
-
对于kong日志要做好切割,我们使用 logrotate
2
Kong插件
-
kong的插件功能很多其内置了很多包括认证,限流,日志等相关插件,当然也可以自定义插件,加载成功后就可以在这个界面进行添加使用
-
不同的插件有不同的参数,需要进行设定,设定完成后就会启用
例如:这是内置的 key-auth 插件,作用是进行api认证,设定 key 之后只有认证通过的才能访问
-
自定义开发和部署,根据业务需要开发插件
基本流程
1.下载模板
base简单版
simple-plugin
├── handler.lua
└── schema.lua
advanced高级版
complete-plugin
├── api.lua
├── daos.lua
├── handler.lua
├── migrations
│ ├── cassandra.lua
│ └── postgres.lua
└── schema.lua
必要文件就是 handler.lua 和 schema.lua
2. 修改 handler.lua 文件,有很多函数,自定义逻辑就是在这些函数中写kong会在一些特定阶段调用对应的函数
local BasePlugin = require "kong.plugins.base_plugin"
-- The actual logic is implemented in those modules
local access = require "kong.plugins.my-custom-plugin.access"
local body_filter = require "kong.plugins.my-custom-plugin.body_filter"
local CustomHandler = BasePlugin:extend()
function CustomHandler:new()
CustomHandler.super.new(self, "my-custom-plugin")
end
function CustomHandler:access(config)
CustomHandler.super.access(self)
-- Execute any function from the module loaded in `access`,
-- for example, `execute()` and passing it the plugin's configuration.
access.execute(config)
end
function CustomHandler:body_filter(config)
CustomHandler.super.body_filter(self)
-- Execute any function from the module loaded in `body_filter`,
-- for example, `execute()` and passing it the plugin's configuration.
body_filter.execute(config)
end
return CustomHandler
3. 修改 schema.lua 文件,主要是配置一些参数,以及参数检查
return {
no_consumer = true, -- this plugin will only be applied to Services or Routes,
fields = {
-- Describe your plugin's configuration's schema here.
},
self_check = function(schema, plugin_t, dao, is_updating)
-- perform any custom verification
return true
end
}
4. 配置部署
插件文件在
/data/kong/plugins/simple-plugin/
则配置kong.conf
lua_package_path = /data/?.lua;($default);
plugins = bundled,simple-plugin
然后重新reload kong 如果lua插件没有错误,就可以在后台看到加载出来了
线上碰到问题
-
返回的内容太大,需要加大 buffer(upstream response cache error) 修改配置
nginx_proxy_proxy_buffer_size=128k
nginx_proxy_proxy_buffers=4 256k
nginx_proxy_proxy_busy_buffers_size=256k
-
需要注意配置属性
-
strip_path 属性
如果设置为 true, paths 设置有值,那么请求将会被替换掉
{ "paths": ["/service"], "strip_path": true, "service": { "id": "..." }}
请求:GET /service/path/to/resource HTTP/1.1Host: …
Proxy: GET /path/to/resource HTTP/1.1
{ "paths": ["/version/\d+/service"], "strip_path": true, "service": { "id": "..." }}
请求:GET /version/1/service/path/to/resource HTTP/1.1
Proxy: GET /path/to/resource HTTP/1.1
-
preserve_host属性
如果设置为 true,代理后仍然保留 header 请求 host
请求:GET / HTTP/1.1Host: service.com
Proxy: GET / HTTP/1.1Host: service.com
设置为false,将不保留header host
GET / HTTP/1.1Host: service.com
GET / HTTP/1.1Host: <my-service-host.com>
总结
Kong 是行业内较为成熟的网关开源产品,无论是性能,易用,扩展方面都表现不错。
Kong 就是服务治理的翅膀,可以更优雅,更便捷,更智能的实现服务降级,熔断,流量调度等工作。
让我们在自建 Kunernetes 私有云,Hulk云,阿里云等复杂的架构中任意翱翔。
本文转载自花椒技术
360技术公众号
技术干货|一手资讯|精彩活动
扫码关注我们