惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
月光博客
月光博客
AI
AI
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
CXSECURITY Database RSS Feed - CXSecurity.com
WordPress大学
WordPress大学
GbyAI
GbyAI
L
Lohrmann on Cybersecurity
O
OpenAI News
Schneier on Security
Schneier on Security
P
Palo Alto Networks Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Troy Hunt's Blog
V2EX - 技术
V2EX - 技术
W
WeLiveSecurity
L
LINUX DO - 最新话题
人人都是产品经理
人人都是产品经理
S
Security Affairs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
Arctic Wolf
Recorded Future
Recorded Future
Microsoft Security Blog
Microsoft Security Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
G
GRAHAM CLULEY
N
Netflix TechBlog - Medium
TaoSecurity Blog
TaoSecurity Blog
C
Check Point Blog
Scott Helme
Scott Helme
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
PCI Perspectives
PCI Perspectives
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Vercel News
Vercel News
The Hacker News
The Hacker News
Y
Y Combinator Blog
Latest news
Latest news
SecWiki News
SecWiki News
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
Cisco Blogs
博客园_首页
H
Hackread – Cybersecurity News, Data Breaches, AI and More
宝玉的分享
宝玉的分享
L
LINUX DO - 热门话题

祈雨的笔记

安全多方计算MPC spark原理解析 kueue执行源码分析 spark on k8s执行源码分析 spark-operator源码解析 系统压测遇到的缓存击穿问题 我的世界PC与安卓联机 蚂蚁金服流量投放平台的AIG改造 G1大对象致Old区占用率高 日志打印导致接口响应率下跌分析 Groovy加载类导致OOM分析 ERROR日志打印导致CPU满载 记OceanBase死锁超时 应用发版期间服务响应超时 Ark Serverless初探 系统优化复盘一二三 The user specified as a definer does not exist API网关选型调研 CPU火焰图常用工具 配置中心选型调研 root操作Nginx导致用户组错误 基于Proxifier使用代理 FastJSON字段智能匹配踩坑 Nacos初探 记一次Nginx服务器CPU满荷载故障 基于券系统分库分表的思考 limit不参与SQL成本计算致索引失效 Linux常用性能监控命令 golang低版本http2偶现400 hostname in certificate didn't match 常见对称加密原理以及应用 tcp_tw_recycle引起的TCP握手失败 记一次mysql执行DDL导致锁表 mysql磁盘占用查看 mysql对text字段update致磁盘增长 elasticsearch报错index read-only TIME_WAIT与Http的Keep-Alive 记一次TIME_WAIT导致连接数报警 记一次生产事故OOM问题排查 redis分布式锁RedissonLock的实现细节 webservice复杂加密签名(2)java调用 webservice复杂加密签名(1)SoapUI mysql延时关联 利用中间人拦截实现APP内H5窜改 MySQL表字符集不同导致关联查询索引失效 通过SSH隧道远程办公 数据落盘方案 BeanDefinitionRegistryPostProcessor扩展 mysql空间索引 HTTPS攻击 spring循环依赖过程解析 elasticsearch性能优化 mysql IS NULL 使用索引 mysql字符集utf8mb4失效踩坑 常用加密算法 xml与javaBean转换 初探InnoDB MVCC源码实现 mysql索引原理 redis之list源码分析 redis之key过期源码分析 redis之string源码分析 redis之hash源码分析 线程池之ThreadPoolExecutor mysql数据页结构 Using temporary与Using filesort mysql回表致索引失效 springboot(28)HTTP连接池 定时任务之ScheduledThreadPoolExecutor elasticsearch常用script聚合 elasticsearch实现like查询 elasticsearch实现乐观锁 elasticsearch准实时原理 springboot(27)自定义缓存读写机制CachingConfigurerSupport optimizer tracing arthas常用命令 HTTP和HTTPS详解 redis集群选举机制 kafka消息重试 一点压力测试的经验 kafka架构概念 explain分析sql语句字段的解释 JVM问题分析处理手册 logstash过滤器(2)date logstash过滤器(3)dissect logstash编码器(1)json logstash编码器(2)multiline logstash表达式 logstash输入(1)通用选项 logstash输入(3)file logstash过滤器(1)通用选项 logstash输入(2)stdin logstash安装 记一次前端vConsole导致JSON序列化错误排查 解决多个异步操作嵌套问题 fastjson反序列化失败autoType is not support RTMP串流服务 POI自动调整列宽错误 Nginx+Lua实现动态黑名单 使用curl命令模拟POST和GET请求 ResponseEntity下载文件
Kong网关初探
祈雨的笔记 · 2021-03-07 · via 祈雨的笔记

安装

Kong安装文档

Kong开源版不提供dashboard支持,只有Kong企业版才有该功能。但有第三方控制台Konga同样可以友好地管理Kong Admin API对象,快速安装如下:

1
2
3
4
5
6
7
8
9
10
docker run -d -p 1337:1337  \
--name konga \
--network=kong-net \
-e DB_ADAPTER=postgres \
-e DB_HOST=kong-database \
-e DB_PORT=5432 \
-e DB_USER=kong \
-e DB_PASSWORD=kong \
-e DB_DATABASE=konga \
pantsel/konga

使用

需求定位是通过网关不仅实现API网关功能,也要能够替代原先Nginx。因此需要的主要功能如下:

  • 服务负载均衡
  • 负载节点健康检查
  • 静态资源访问
  • 调用方认证、路由鉴权
  • 限流、IP黑白名单
  • 灰度发布
  • 监控

Kong网关的主要概念有route、service、upstream、target,其逻辑关系见下图:

image

负载均衡

当前的负载均衡逻辑为Nginx做负载均衡,服务发版时通过动态模板解析实现:Jenkins自动化脚本修改Nginx的upstream文件实现。例如对某服务的a、b两节点发版时具体逻辑如下:

  1. 先修改Nginx的upstream脚本摘除该服务的a节点
  2. 等待a节点无流量请求后发布重启a节点的新版本
  3. 最后再修改Nginx的upstream脚本重新添加a节点
  4. 接着同样的逻辑操作b节点

通过以上逻辑实现服务的无缝发版,但每次节点变动都需要reload一次Nginx。虽然现在的Nginx版本的reload已经支持配置平滑更新,但实际上reload操作依然会造成CPU竞争、Nginx性能降低以及提前关闭HTTP长连接导致部分客户端调用异常。

image

为了避免以上问题,常见的解决方案如下:

  1. DNS动态解析
  2. lua脚本解析

Kong网关对以上两种方案均支持,基于这两种方案,可以对当前上述服务发版流程优化成功以下几种方式:

集成Kubernetes

集成Kubernetes,通过Kubernetes的DNS服务发现实现负载均衡。Kong网关只负责路由匹配、调用者认证、路由鉴权等网关责任,而服务注册发现的逻辑全部交由Kubernetes处理,使Kong网关完全脱离upstream的逻辑处理。

集成注册中心

image

Kong网关提供了API接口,可以通过这些开放的API接口来管理Kong内部的各个对象,例如上线/下线节点target,详见官方文档admin-api/add-target

1
2
3
4
5
6
7
8
9
# 节点上线
curl -X POST http://127.0.0.1:8001/upstreams/test-upstream/targets \
--data "target=172.17.0.1:8080" \
--data "weight=100"

# 节点下线
curl -X POST http://127.0.0.1:8001/upstreams/test-upstream/targets \
--data "target=172.17.0.1:8080" \
--data "weight=0"

因此可以搭建如上图的架构方案,自行代码实现一个节点监听服务,通过对接注册中心的API来实时监听各个服务节点的状态。当某服务节点上下线后,注册中心将节点上下线事件推送给监听服务,然后监听服务通过Kong的开放API修改该节点对应的Kong中的target对象状态。

通过上述方案从而实现一个注册中心同时管理微服务之间的服务发现和网关到服务的服务发现。此时应用发布流程例如对某服务的a、b两节点发版时具体逻辑如下:

  1. 请求注册中心下线该服务的a节点
  2. 监听服务监听到a节点下线后自动将Kong中的a节点下线
  3. 等待a节点无流量请求后发布重启a节点的新版本
  4. a节点启动成功后自动将自己重新注册到注册中心
  5. 监听服务监听到a节点上线后自动将Kong中的a节点上线
  6. 接着同样的逻辑操作b节点

自动化脚本

该方案需要配合健康检查使用,具体逻辑与动态模板解析方案基本相同,仅仅是将模板修改操作替换成API请求操作。例如对某服务的a、b两节点发版时具体逻辑如下:

  1. 请求Kong网关API摘除该服务的a节点
  2. 等待a节点无流量请求后发布重启a节点的新版本
  3. 最后再请求Kong网关API重新添加a节点
  4. 接着同样的逻辑操作b节点

健康检查

Kong的upstream支持target健康检查,详细文档见health-checks-circuit-breakers

Kong支持两种健康检查方式,即可以单独使用,也可以组合使用。通过健康检查target的健康状态,被标记为不健康的target不再有请求路由到该节点。

  • 主动健康检查:定时请求target的指定path,并通过响应状态码标记该target为健康/不健康
  • 被动健康检查:target的指定响应码数量超过阈值后标记该target为不健康

==被动健康检查不会将不健康的target标记成功健康状态,需要人工手动标记该target为健康状态从而恢复流量路由到该目标。因此如果需要使用被动健康检查,务必与主动健康检查组合使用,通过主动健康检查自动将恢复响应的target标记为健康状态。==

静态资源

Kong目前仅支持API路由,不支持静态资源映射,为了最简单地方式使Kong实现静态资源访问,可以搭建下图所示的架构。单独搭建一个Nginx服务做静态资源服务器,然后在Kong中将该Nginx服务配置成service并设置路由规则,将静态资源访问请求通过路由规则请求到该Nginx上。

image

限流

Kong自带限流插件rate-limiting

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
local function get_identifier(conf)
local identifier

if conf.limit_by == "service" then
identifier = (kong.router.get_service() or
EMPTY).id
elseif conf.limit_by == "consumer" then
identifier = (kong.client.get_consumer() or
kong.client.get_credential() or
EMPTY).id

elseif conf.limit_by == "credential" then
identifier = (kong.client.get_credential() or
EMPTY).id

elseif conf.limit_by == "header" then
identifier = kong.request.get_header(conf.header_name)

elseif conf.limit_by == "path" then
local req_path = kong.request.get_path()
if req_path == conf.path then
identifier = req_path
end
end

return identifier or kong.client.get_forwarded_ip()
end

rate-limiting插件限流逻辑的对象选择关键代码如上,当基于path限流时,该插件的后续处理逻辑有点反常识。正常逻辑下对指定path限流意味着path规则匹配时则限流,path不匹配时不限流,但该插件的逻辑是path规则匹配时限流,path规则不匹配时按调用方ip限流。

且该插件的path匹配规则仅支持单个完全匹配,不支持范围匹配、正则匹配等常见规则。因此如果需要基于path做限流控制,可以对官方插件稍作修改后使用。

计数模式config.policy支持3种策略:

  • local: 节点本地内存中计数,应用场景为单节点模式,性能影响最小
  • redis: redis中计数,应用场景为集群模式,需要额外依赖redis服务,性能影响中
  • cluster: 集群计数,应用场景为集群模式,不需要额外依赖服务,但性能影响最大

灰度发布

灰度发布是指通过将更改缓慢推广到一小部分用户,降低在生产环境中引入新软件版本的风险。Kong开源版官方不提供该插件,但有第三方插件支持kong-plugins-canary

支持通过ip、header、cookie、args四种匹配方案来做灰度流量控制,并支持单个、多个、正则匹配规则。

数据监控

启用prometheus插件

首先在Kong控制台启用prometheus插件,如下图所示,直接在全局范围启用该插件,关于prometheus插件更多配置详见官方文档

image

插件启动后访问KongAdmin的/metrics地址,如下图所示,则说明prometheus插件启动成功。

image

安装prometheus

prometheus

修改配置文件,将KongAdmin的访问地址添加到targets值域中,如下图,然后启动prometheus服务。

image

1
2
3
4
5
6
docker run -d \
--name prometheus \
--network=kong-net \
-p 9090:9090 \
-v /etc/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus

访问prometheus的访问地址http://host:9090后,在搜索栏中输入关键字kong后如下图自动补全搜索关键字,则表示prometheus成功收集到了Kong的监控数据。

image

安装grafana

1
2
3
4
5
docker run -d \
--name=grafana \
--network=kong-net \
-p 3000:3000 \
grafana/grafana

访问grafana的控制台地址http://host:3000(默认账号密码admin:admin),需要先关联prometheus服务。如下图,在配置栏添加prometheus数据库,并输入prometheus的服务访问地址http://host:9090

image

image

image

prometheus数据库配置完成后,添加Kong的dashboards,直接输入模板ID7424或者访问
https://grafana.com/grafana/dashboards/7424下载模板JSON文件后导入均可,如下图。

image

image

最终效果展示:

image

image

image