免规则采集器列表算法( 架构师生产级应用面临的问题,你知道吗?(上))

优采云 发布时间: 2021-11-18 05:18

  免规则采集器列表算法(

架构师生产级应用面临的问题,你知道吗?(上))

  

  作者:丁浪,目前在一家创业公司担任高级技术架构师。曾就职于阿里巴巴大娱和蚂蚁金服。拥有丰富的稳定性保障和全链路性能优化经验。建筑师社区的特邀嘉宾!

  前言

  网上关于限流算法、Sentinel功能介绍、基本结构、原理分析可以说是汗流浃背,不打算重复内容了。我将在实际工作和生产环境中与大家分享使用和踩坑的经验。

  如果您在做限流熔断的技术选型,那么本文将为您提供客观而有价值的参考;

  如果你以后想在生产环境中使用Sentinel,这篇文章将帮助你以后少走弯路;

  如果您正在准备求职面试,您或许可以为您的技能树和经验添加亮点,并避免在您的面试评估表上“写在纸上”;

  Sentinel的开源版本和阿里内部的一样吗?

  我们可以在量产层面应用它吗?

  这里我直接告诉你答案:开源和内部版本是一样的,核心代码和能力都是开源的。它可以用于生产,但它不是“开箱即用”,需要你做一些二次开发和调整。接下来,我将仔细展开这些问题。当然,我推荐你直接使用阿里云上的AHASSentinel控制台和ASM配置中心,这些都是最佳实践的输出,可以节省大量的时间、人力、运维成本等。

  整体运营架构

  

  *敏*感*词*生产应用面临的问题

  看了Sentinel开源版原来的运行架构,很明显存在一些问题:

  1. 限流降级等规则存储在应用节点的内存中,应用释放重启后会失效,这在生产环境中显然是不能接受的;

  2. 默认情况下,规则的分配是基于机器节点维度而不是应用维度,正常公司的应用系统都是集群部署的,不支持集群限流;

  3. 指标信息被Dashboard拉取并保存在内存中仅5分钟。错过了,可能就无法还原“危机场景”,看不到流量趋势;

  4. 如果访问限流的应用有500+个,每个应用平均部署4个节点,那么一共2000个节点,那么Dashboard肯定会成为瓶颈,单机线程池不会完全能够处理它;

  如何优化和解决这些问题

  接下来,我们先来一一介绍如何解决上述明显的问题。

  首先,限流规则、降级规则等都应该按照应用维度来发布,而不是按照APP单节点的维度来发布。由于Sentinel支持集群限流,SentinelDashbord开源版做了限流规则的扩展,但没有扩展到熔断器、系统保护等,支持按应用维度下发。有兴趣的读者可以参考 FlowControllerV2 的实现来实现。

  其次,规则不应该存储在内存中,应该持久化到动态配置中心,应用可以直接从配置中心订阅规则。这样,Dashboard 和应用就通过配置中心解耦了。这是典型的生产者-消费者模型。基本的运行架构如下:

  

  以nacos配置中心为例。Sentinel 官方和社区提供了保存和订阅限流规则的演示。然后可以扩展熔断器降级、系统保护、网关限流...等规则。基本模型是:Dashboard将xxRuleEntityVO模型序列化保存到nacos中,应用从nacos订阅后反序列化成xxRule域模型。

  这里要提醒大家的是,前方有巨大的坑。请不要直接复制“热参数限流规则”和“黑名单限制规则”,因为Dashboard中定义了ParamFlowRuleEntity和AuthorityRuleEntity

  两个VO模型中的字段定义与域模型ParamFlowRule和AuthorityRule不匹配,会导致序列化/反序列化失败,进而导致应用无法订阅和使用热参数限流规则和黑名单限制规则。我要提交PR!!!

  第三点是Dashboard中有一个调度线程池,它会轮询请求(默认每1秒发起一次)。每个应用的机器节点查询metrics日志信息,汇总显示在界面上(改造后需要完成持久化动作)。这是典型的pull模式,是监控测量领域比较常见的架构。因为是存储在内存中,所以默认只保留5分钟,这也是有问题的。推荐以下解决方案:

  1. Dashboard拉取metrics信息后,直接保存在时序数据库中,Dashboard本身也从时序数据库中抓取数据进行展示。存储指标数据的时间取决于您的业务。以开源的Influxdb为例,它有自己的持久化策略功能(自动清理过期数据)。此外,还可以使用Grafana等开源Dashboards进行查询聚合,展示各种漂亮的行情、图表、排名等;

  2. 可以把pull模式改成push模式,记录metrics日志的时候直接写时序数据库。当你的时候,基于性能的考虑,你也可以改写MQ来做缓冲。除了耗时,最重要的是不要因为记录指标的动作而影响主要业务流程的进度;

  3. 继续打印metrics日志,启用SentinelDashboard拉出metrics数据,使用采集器直接在应用机器节点上采集,处理上报metrics日志。可以使用ELK等工具;

  4. 可以尝试自己开发PrometheusExporter,将metrics信息以Target的形式公开,Prometheus服务器会定时拉取。同时,您还可以使用 Prometheus 提供的各种丰富的查询和聚合语法和功能。, 通过 Grafana 等方式显示;

  下图是一个典型的时间序列数据示例,它是为指标索引数据设计的。该领域知名的开源软件包括OpenTSDB、Influxdb等。

  

  Grafana 限流市场展示效果图

  以上方法各有优缺点。如果你想做最小的改动,并且你的应用访问和部署规模不是特别大(500个节点以内),那么请选择第一种方式。

  

  第四点是Dashboard由于接入的应用程序和节点较多,在pulling和aggregation方面的性能瓶颈。解决问题3时,如果选择方法2、3、4,那么Sentinel自带的Dashboard只会作为规则分发的工具(甚至规则分发可以直接通过nacos配置中控台完成),自然不会有瓶颈问题。如果你还想使用 Sentinel 自带的 Dashboard 来完成拉取和持久化指标数据等任务,那么我为你提供两种解决方案:

  1. 按域隔离,将不同业务域的应用连接到各自的SentinelDashboard,让压力自然分散,减少出现瓶颈的可能性。优点是几乎不需要修改,缺点是不统一;

  2. 可以尝试改造 Sentinel 自带的 Dashboard,使其无状态。前面我们提到过,应用启动后会定时上报心跳信息。Dashboard 默认会在内存中维护一个“节点信息列表”数据。这是一个典型的状态数据,应该考虑集中存储。例如:redis。那么就需要修改“拉取指标信息”的线程池,改为分片任务执行,从而达到分担负载的效果,例如:改用elasticjob调度。当然,时序数据库的写入也可能成为瓶颈;

  3. 可以牺牲一点监控指标的时效性,增加Sentinel Dashboard中fetchScheduleService调度线程池的间隔时间参数,可以缓解下游worker线程池的处理压力;

  就我而言,我实际上推荐第一种和第三种方法。这些都是权宜之计,变化相对较小。

  当然,按字段划分还有其他好处。如果连接到500+个系统,以当前的Dashboard开源版本为例,左边的应用列表会延长多长时间?估计不能用了。UI和交互设计很业余,显然不能满足量产应用。但按领域隔离后,体验可能会有所改善。还有一点。Dashboard 目前的开源版本只提供了最基本的登录验证功能。如果需要权限控制、审计、审批确认等功能,则需要二次开发。如果Dashboard按字段独立,访问控制的风险会更小。

  当然,如果要重构Dashboard权限控制和UI交互,建议按照应用维度进行设计,添加基础搜索等。

  其他问题

  应用程序连接到Sentinel后,启动时需要指定应用程序名称、Dashboard地址、客户端端口号、日志配置、心跳设置等,可以通过JVM -D启动参数,也可以将配置文件保存在指定的配置路径。这是一种不合理的设计,对CI/CD和部署环境有干扰。我解决了这个问题,在1.6.3版本提交了PR。好在社区在1.7.0时解决了这个问题。

  一些规则配置和使用经验

  请不要误会我的意思。我不是教你怎么配置和使用,而是教你怎么用好。还记得我在之前的稳定保障体系文章中抛出关于限流的灵魂拷问吗?首先我们简单回顾一下Sentinel中可能用到的关键功能。接下来我会以自问自答的方式回答用户最常见的疑问,输出最有价值的经验和建议。

  1. 单机限流

  2. 集群限流

  3. 网关限流

  4. 热点参数限流

  5. 系统自适应保护

  6. 黑白名单限制

  7. 保险丝自动降级

  单机限流阈值是多少?

  这可不能“一巴掌”。匹配太高可能会导致故障。如果匹配度太低,您会担心过早的“过失杀人”请求。还是要根据容量规划和水位设置进行配置,前提是监控报警灵敏。给出了两个比较实用的方法:

  1. 参考单机容量规划的思路,在软负载中调整一个节点的流量权重和比例,直到接近极限。记录极限状态下的QPS,根据单机房70%水位设置标准,可以计算出资源的单机限流阈值;

  2. 可以定期观察监控系统的流程图,在线获取真实峰值QPS。如果应用系统和业务在周期的高峰期处于健康状态,那么可以假设峰值QPS就是理论水位。这种方式可能会造成资源浪费,因为高峰期可能达不到系统承载限制,适合流量周期有规律的业务;

  你真的需要集群限流吗?

  其实在大多数场景下,不需要使用集群限流,单机限流就足够了。仔细想想。实际上,只有几种情况可能需要使用集群限流:

  1. 想配置单机QPS限制时

  2. 上图中单机限流阈值为10 QPS,部署了3个节点。理论上集群的总QPS可以达到30,但实际上由于流量不均,集群的总QPS还没达到30就触发了。电流有限。很多人会说这不合理,但我觉得还是要根据实际情况来分析。如果这个“10QPS”是根据容量计划的系统承载能力计算的阈值(或者如果接口请求超过10QPS,系统可能会崩溃),那么这个限流的结果是令人满意的。如果这个“10QPS”只是业务级别的限制,那么即使一个节点的QPS超过10,也不会有什么问题。其实我们本质上是想限制整个集群的总QPS,所以这个限流的结果是不合理的。,并没有达到最好的效果;

  所以,这实际上取决于你的限流是实现“过载保护”还是实现业务级别的限制。

  还有一点需要注意的是,集群限流不能解决流量不均的问题,限流组件也不能帮你重新分配或调度流量。集群限流只会在流量不均的场景下,让整体限流效果更好。

  实际使用建议是:集群限流(实现业务层限流)+单机限流(系统去底层防止被炸掉)

  现在网关层限流了,应用层还需要限流吗?

  如果需要,双重保护是必要的。同理,上游聚合业务配置限流,下游基础业务也需要配置限流。试想一下,如果只配置了上游限流,如果上游发起大量重试,会不会压垮下游的基础服务?而在这种情况下,我们在配置限流阈值时也需要特别注意。例如,上游A和B服务依赖于下游Y服务。A和B分别配置100QPS,那么Y服务必须至少配置200QPS。否则,一些请求被额外透传处理,最终被拒绝,不仅浪费资源,

  因此,最好按照整个链路的整体容量规划(桶短板原则)来配置。越早拦截越好,而且每一层都要配置限流。

  热参数限流功能实用吗?

  该功能非常实用,可以防止热点数据(如:热门店铺、黑马产品)占用和消耗过多系统资源,严重影响其他数据请求的处理。

  还有一个要求。如果你在做C端产品,想限制用户访问某个接口的最大QPS,或者你在做B端SAAS产品,想限制租户访问某个接口的最大QPS某个接口... hotspot参数默认不是为满足这样的需求而设计的,需要自己扩展SLOT来实现类似的限制需求。当然,热点参数流量限制中的paramFlowItemList(参数异常项)可以实现某个客户ID=1的大客户访问某个资源的最大QPS为100),可以实现在某种程度上。有一个特殊要求。这个需求还有一个解决方案:当我们在代码中定义sourceName时,

  为什么要有自适应保护系统?

  其实这也是一种自下而上的做法。当实际流量超过部分限流阈值时,开销基本可以忽略。当真实流量远超限流阈值N倍时,尤其是双十一大促、春晚红包、12306购票等大流量场景,那么限流拒绝请求的开销就无法忽略。这种情况在阿里巴巴内部被称为“系统被触死”。在这种情况下,自适应限流可以很好地发挥作用。

  是否需要配置黑白名单限制?

  如果您想根据请求的来源进行限制(仅从指定的上游系统释放请求),此功能非常有用。Sentinel 内置了“簇点链接监控”功能,有点类似于调用链监控,但目的不同。

  熔断器自动降级使用有哪些建议?

  在配置熔断器自动降级之前,我们首先需要识别可能不稳定的服务,然后判断是否可以降级。降级处理通常很快就会失败。当然,我们可以自定义降级处理的结果(Fallback),例如:尝试包裹返回默认结果(降级),返回上次请求的缓存结果(时效性下降),包裹返回结果失败。即时结果等

  弱依赖和次要功能的退化通常是通过推动开关手动完成,而 Sentinel 的保险丝退化主要是在“调用端”自动判断和执行。Sentinel基于平均响应时间,可以利用错误率、错误数等统计指标进行自动融合和降级。

  例如:我们的系统同时支持“余额支付”和“银行卡支付”。这两个函数对应的接口默认在同一个应用的同一个线程池中。任何一方的 RT 抖动和大量超时都可能导致请求积压。线程池耗尽。假设从业务角度来看,“余额支付”的比例越高,保障的优先级也越高。然后我们可以在“银行卡支付”界面(依赖第三方,不稳定)当RT持续上升或者出现大量异常(前提是数据不一致等影响业务的问题)进行“熔断器自动降级”进程不能引起),以便优先确保“

  总结

  本文主要介绍了Sentinel开源版在*敏*感*词*生产级应用中面临的一些问题和解决方案,以及实际配置和使用中的一些经验。这些经验来自一线生产实践,希望读者朋友少走弯路。如果您有任何问题,请留言讨论。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线