轻量级微服务流量管理实践

2020 年 3 月 22 日

轻量级微服务流量管理实践

流量管理的过程主要有三个步骤:采集和发送监控数据、监控数据结构化存储、使用监控数据进行报警和管理控制,这三个流程由客户端、数据存储和管理端交互完成。



  • 客户端:通过pom依赖集成在所有服务方应用,需配置过滤器和启动Bean。

  • 数据存储:目前使用了Redis集群,3分片每分片1GB内存,目前存储100+服务所有流量两天的监控信息,使用了40%空间。

  • 管理端:独立部署的应用,用于展示图表等监控信息、发送报警通知、配置降级限流和授权等功能的参数。


1 采集和发送监控数据


一、采集监控数据


监控系统为了采集监控数据,需要对每一次请求都进行记录,如果这一过程发生异常或占用较多资源将影响正常服务运行,因此采集客户端需要足够的轻量和高效,并隔离异常以确保不影响原流程。主流 RPC 框架(JSF、dubbo、rest 等)中都提供了 Filter 过滤器的扩展能力,我们通过在自定义的服务端过滤器中对请求进行记录和控制。


每一次请求必须的监控关键信息是服务信息(接口名、方法名)、来源应用(将来源 IP 自动转换为应用名,后面会解释如何转换)、时间戳,即监控每一个服务方法的每一个来源的每秒调用量。根据时间戳精度,如果记录每秒钟的调用量则每个服务每个调用来源一天需要 86400 个记录,显然这是一个比较庞大的记录量,一番权衡之后,目前记录每个服务每个调用来源 4 秒的请求量,除以 4 得到该时间范围的平均 TPS。


如何采集上述信息呢?我们在每个应用实例中创建一个静态的并发 Map,将每一个服务者和来源作为 key,对应值为该服务的一个原子计数器,每当调用时发生时进行计数器自增操作。同时在应用启动时会创建一个监控主线程,它通过定时器每 4 秒执行一次计划任务,这个任务需要一些技巧严格维持在每分钟的 0 秒、4 秒、8 秒……56 秒这样的时间戳执行,任务会将当前时间戳和 Map 中所有计时器统计结果发送到异步队列,同时清零所有原子计数器。由于这个过程没有耗时性任务,这样能保证精准完成统计信息并且不影响原服务流程。


二、发送监控数据


接下来如何发送采集的监控数据呢?为了尽量减少资源占用和减少复杂性,我们没有选择本地日志记录发送的方式,而是直接在消费队列的异步线程中将 4 秒一次的统计信息发送到 Redis 集群。针对每一个服务-调用来源-时间戳作为 key,调用量作为 value 在 redis 中进行存储,因此每次发送实际是一个个 INCRBY 操作,所有应用实例操作后就能得到整个集群准确的流量信息。


实际应用中这种方案会造成大量的 Redis 并发写入,从整个 Redis 集群监控中可以看到 4 秒一次的非常高的 TPS 波峰,一个简单的思路是将异步线程发送随机延后,这可以起到一定削峰效果,但是依然有很大优化空间,大量的 Redis 调用可以通过 pipeline 机制进行加速。使用 pipeline 进行批量操作不仅可以节约每次单独调用时的 RTT(网络来回延迟),还能减少 Redis 内部处理时的 IO 系统调用。经优化提高了 10 倍左右的性能。为了使用批量发送,需要将队列任务收集并积累为一批任务发送,我们通过队列的 poll 和超时检测,将未发生出队超时的(一批)任务批量一次发送。



2 监控数据结构化存储和读取


从轻量和效率等因素考虑,我们直接使用内部申请的 Redis 集群作为存储。


  • 第一种办法:前面我们提到的key-value存储结构比较简单,它通过系统名-接口名-方法名-调用方应用名-时间戳这样的key,设置value为计数量,这是最简单但是最浪费存储空间的设计方式,因为key会非常长,优点是逻辑简单直接。

  • 第二种办法:针对它的直接优化,将所有接口名、方法名等都转换为数字序列id,如0-0-0-0这样,这样key精简到非常简短,但同时增加复杂性,实际上空间占用还是很大。最好的办法是利用hash这类的数据结构进行存储,如key中包括系统名-接口名-方法名-调用方、filed中存储简短的时间戳、对应的value中存储计数量,这种方式能极大的减少存储空间。经测试按同样规则生产的100个1天范围的采集数据。

  • 第三种办法:hash结构存储比第一种简单方式(带超时信息)减少了一半以上的存储空间。


在读取和生成监控图表的过程,经常会面对非常大时间范围,如果此时还使用秒级数据将导致查询结果非常多,数据会超过图表的像素容量,此时最好在存储时进行汇总,即通过后台任务将前一分钟秒级监控数据汇总为分钟级,较大范围查询时直接查询分钟级数据,类似的如果查询较高级别的查询则通过查询所有下一级数据进行汇总展示,同时读取批量数据也可以同 pipeline 进行批量读取加速。



3 报警和管理控制


**


**


一、监控管理端提供多维度页面进行来源和 TPS 等信息展示,可以迅速了解当前服务的流量来源和分布,此外可以针对每一个接口方法来源进行 TPS 报警和控制,通过预先配置的调用来源预估调用量,当超过阈值时进行报警通知。并可采取以下三种管理措施:


  • 降级:根据配置开关,当触发熔断条件时进行自动或手动操作降级,降级后采集端的过滤器会直接对新请求新返回失败,在不影响其他调用方的情况下对服务端进行保护。

  • 限流:与降级类似的方案是限流,由于分布式系统中进行总量限流会依赖中心节点进行令牌桶这类计算,同步调用对原接口影响较大,非严格的情况下并不是一个很通用的选择,这里我们使用了一个简单方案,即在每个服务节点进行单位时间固定量限制,即4秒内超过限制量的请求会被阻挡,虽然不是平滑限流,而且设置量也需要根据机器数进行调整,但该方案对正常的流量影响最小。

  • 流量许可:除了对异常流量进行降级和限流外,还可以通过白名单机制对部分接口进行流量许可,没有预先加入白名单的视为非授权请求。


以上这些降级、限流以及白名单的配置存储在 Redis 中,客户端本地缓存在 map 中并每分钟刷新,在过滤器中通过简单规则匹配实现管理逻辑,不强依赖存储和管理端。


二、管理端还承担了各类定时任务,如定期每分钟汇总秒级数据到分钟级数据,将所有 IP 转换为应用名,各类系统控制开关和配置项等。


这里有个前文忽略的一点,在监控过滤器中的取到的调用方 IP,它是如何转换成应用名称呢?京东当前有多个应用部署平台,其中通过 J-ONE 发布的应用在调用时会携带应用名参数,但是其他部署平台就只能获得 IP 信息,我们通过访问统一的运维平台,主动查询 IP 地址到应用名的映射关系,进行存储并定期每天刷新,过滤器本地也保持有该映射的缓存并定期刷新,在减少影响和实时性之间作了权衡。由于生产环境不允许混合部署(一个实例多个应用),因此不会产生识别冲突,更多可能的延迟主要在应用缩容扩容时,可以通过缩容扩容主动刷新缓存的方案解决。



4 总结


受限于条件和目标,上述流量管理方案有不足可优化之处,如:


  • 范围限制在了服务端(provider);

  • 调用方客户端(consumer)也有更多扩展思路,例如限流或降级的开关应该设置在客户端,当降级时甚至不需要再发起远程调用请求;

  • 超过几千台规模的应用实例的情况下可能会产生较高的Redis写入压力,可以通过增加Redis集群分片数量解决;

  • 也可考虑其他同步和存储方案,如Kafka异步传输和HBase集群存储等。


但作为一个快速实现的监控管理系统,可以看出很多通用监控的思路和要点,同时加强了对微服务流量方面的治理,希望能对大家有所帮助,欢迎后续和作者一起探讨沟通。


2020 年 3 月 22 日 20:49181

评论

发布
暂无评论
发现更多内容

《图解数据结构》.pdf

田维常

数据结构

一次产品影响地图的探索之旅

Bruce Talk

敏捷 Agile Product Owner 影响地图

研发管理:敏捷研发下周报的价值

云原生实验室

云原生 敏捷 研发管理 周报

福利 | 这些网站有免费代理IP!

前嗅大数据

大数据 代理IP 网站反爬 免费代理ip 封ip

架构探索:事务处理一

carol

架构师训练营第 1 期 第 11 周作业

李循律(祥龙)

极客大学架构师训练营

三分钟看懂快速开发,常用软件快速开发平台速览

Marilyn

敏捷开发 快速开发 企业开发 企业应用

蕃茄田宋姝梦:科技赋能时代,儿童在线艺术教育的思考

ZEGO即构

想拿到10k-40k的offer,这些技能必不可少!作为程序员的你了解吗?

Crud的程序员

Java 程序员 技能

基于RTMP数据传输协议的实时流媒体技术研究(论文全文)

程序员小灰

音视频 ffmpeg 流媒体 RTMP webrtc、

CloudIDE插件开发实战:教你如何调试代码

华为云开发者社区

ide 开发 Cloud

全球熵ETV系统APP开发|全球熵ETV软件开发

开發I852946OIIO

系统开发

拆解增长黑客之实战(一):获客与激活

丁一

增长 产品运营

多活/多机房的几种实现方式与重点

Justfly

高可用 跨机房 数据同步 异地多活容灾

redis系统深度学习四:主节点自动化故障恢复——哨兵

linux亦有归途

数据库 redis 大数据 故障

K8s 将弃用 Docker;TypeScript 超越 C++ 成第四大语言

京东智联云开发者

程序人生

话题讨论 | 用好VSCode这13款插件和8个快捷键,工作效率提升10倍

柠檬橙

话题讨论

深入灵魂的考验,每行注释都是灵魂的单例模式,源码+实例降临

小Q

Java 学习 架构 面试 设计模式

anyRTC 联合 vInClass 打造在线教育上课模式

anyRTC开发者

音视频 WebRTC 在线教育 RTC

干货分享!用心满满:面试前必知必会的二分查找及其变种

比伯

Java 编程 架构 面试 计算机

鹅厂大佬亲身经历证明,一周上线百万级并发系统

Java架构师迁哥

WebRTC SDP 详解和剖析

阿里云视频云

软件开发中的防呆方法总结

张明云

DevOps 软件开发 技术架构 防呆 模式

GitHub上标星75k+的《Java面试突击版》,美团架构师呕心沥血整理,已助多人拿到满意的大厂offer。

Java成神之路

Java 程序员 架构 面试 编程语言

5G多输入多输出技术,到底是个啥东东?

华为云开发者社区

5G 输入 输出

为什么阿里人能够快速成长?看完他们Java架构进化笔记,我秒懂!

Java架构追梦

Java 学习 架构 面试 成长笔记

大型团队实践敏捷开发管理的挑战与应对

万事ONES

敏捷开发 研发管理 敏捷开发管理 开发管理

InfoQ 内容推荐位资源限时开放

丁晓昀

InfoQ 资源

理解Python协程的本质

Justfly

Python 协程 异步 Async 异步编程

深度学习在物理层信号处理中的应用研究

华为云开发者社区

学习 模型 物理层

美女面试官问我:说说你对序列化的理解

田维常

序列化

轻量级微服务流量管理实践-InfoQ