无需编写一行代码,实现任何方法的流量防护能力

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 微服务的稳定性一直是开发者非常关注的话题。随着业务从单体架构向分布式架构演进以及部署方式的变化,服务之间的依赖关系变得越来越复杂,业务系统也面临着巨大的高可用挑战。疫情期间,大家可能都经历过以下的场景:1、线上预约购买口罩时瞬间洪峰流量导致系统超出最大负载,load 飙高,用户无法下单;2、在线选课时同一时刻提交选课的请求过多,系统无法响应;3、在线办公/教学时同时在线会议的用户过多,会议比较卡;这些可用性下降的场景会严重影响用户体验,所以我们需要预先通过一些手段来提前对不稳定的因素进行防护,同时在突发流量的情况下我们也要具备快速止损的能力。

背景

微服务的稳定性一直是开发者非常关注的话题。随着业务从单体架构向分布式架构演进以及部署方式的变化,服务之间的依赖关系变得越来越复杂,业务系统也面临着巨大的高可用挑战。疫情期间,大家可能都经历过以下的场景:

  • 线上预约购买口罩时瞬间洪峰流量导致系统超出最大负载,load 飙高,用户无法下单;
  • 在线选课时同一时刻提交选课的请求过多,系统无法响应;
  • 在线办公/教学时同时在线会议的用户过多,会议比较卡;

这些可用性下降的场景会严重影响用户体验,所以我们需要预先通过一些手段来提前对不稳定的因素进行防护,同时在突发流量的情况下我们也要具备快速止损的能力。

流控降级 - 保障微服务稳定性重要的一环

影响微服务可用性的因素有非常多,而这些不稳定的场景可能会导致严重后果。我们从微服务流量的视角来看,可以粗略分为两类常见的场景:


  • 服务自身流量超过承载能力导致不可用。比如激增流量、批量任务投递导致服务负载飙高,无法正常处理请求。


流量是非常随机性的、不可预测的。前一秒可能还风平浪静,后一秒可能就出现流量洪峰了(例如双十一零点的场景)。然而我们系统的容量总是有限的,如果突然而来的流量超过了系统的承受能力,就可能会导致请求处理不过来,堆积的请求处理缓慢,CPU/Load 飙高,最后导致系统崩溃。因此,我们需要针对这种突发的流量来进行限制,在尽可能处理请求的同时来保障服务不被打垮。


  • 服务因依赖其他不可用服务,导致自身连环不可用。比如我们的服务可能依赖好几个第三方服务,假设某个支付服务出现异常,调用非常慢,而调用端又没有有效地进行预防与处理,则调用端的线程池会被占满,影响服务自身正常运转。在分布式系统中,调用关系是网状的、错综复杂的,某个服务出现故障可能会导致级联反应,导致整个链路不可用。


一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的服务进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。

MSE 服务治理基于阿里限流降级组件 Sentinel 的稳定性防护能力,以流量为切入点,从流量控制、并发控制、熔断降级、热点防护、系统自适应保护等多个维度来帮助保障服务的稳定性,覆盖微服务、云原生网关、Service Mesh 等几大场景。

介绍完流控降级的场景与能力之后,下面讲请出我们今天要重点介绍的主人公:运行时动态 Enhance 能力。我们将介绍如何通过MSE服务治理一键实现任意点位的流控降级,任意点位包含但不限于Web、Rpc、SQL、Redis等访问接口、任意编写的业务方法、框架的接口等等。

运行时 Enhance 能力 - 一键实现任意点位的流控降级

如何在运行时,给任意指定的方法增加一个流控降级能力呢?下面我将以一个Demo为例简单介绍。

我们编写了如下一个业务代码,我们编写了一个简单的Spring Boot应用,其中a方法是一个随意编写的内部方法。

@SpringBootApplicationpublicclassAApplication {
publicstaticvoidmain(String[] args) {
SpringApplication.run(AApplication.class, args);
    }
@Api(value="/", tags= {"入口应用"})
@RestControllerclassAController {
        ...
@ApiOperation(value="HTTP 全链路灰度入口", tags= {"入口应用"})
@GetMapping("/a")
publicStringrestA(HttpServletRequestrequest) {
returna(request);
        }
privateStringa(HttpServletRequestrequest) {
StringBuilderheaderSb=newStringBuilder();
Enumeration<String>enumeration=request.getHeaderNames();
while (enumeration.hasMoreElements()) {
StringheaderName=enumeration.nextElement();
Enumeration<String>val=request.getHeaders(headerName);
while (val.hasMoreElements()) {
StringheaderVal=val.nextElement();
headerSb.append(headerName+":"+headerVal+",");
                }
            }
return"A"+SERVICE_TAG+"["+inetUtils.findFirstNonLoopbackAddress().getHostAddress() +"]"+" -> "+restTemplate.getForObject("http://sc-B/b", String.class);
        }
        ...
    }
}

到目前为止监控是看不到a方法的,我们只能看到 restA 的接口或者说是 GET:/a 的监控数据,并且可以对其配置限流降级规则。

开源的方式我们需要在代码中增加Sentinel的依赖,并且对 com.alibabacloud.mse.demo.AApplication.AController#a 方法配置注解或者编码方式增加Sentinel能力

// 注解方式进行埋点,注解方式受 AOP 代理的诸多限制@SentinelResource("com.alibabacloud.mse.demo.AApplication.AController:a")
privateStringa(HttpServletRequestrequest) {
StringBuilderheaderSb=newStringBuilder();
Enumeration<String>enumeration=request.getHeaderNames();
while (enumeration.hasMoreElements()) {
StringheaderName=enumeration.nextElement();
Enumeration<String>val=request.getHeaders(headerName);
while (val.hasMoreElements()) {
StringheaderVal=val.nextElement();
headerSb.append(headerName+":"+headerVal+",");
        }
    }
return"A"+SERVICE_TAG+"["+inetUtils.findFirstNonLoopbackAddress().getHostAddress() +"]"+" -> "+restTemplate.getForObject("http://sc-B/b", String.class);
}
// SDK 方式增加流控降级能力,需要侵入业务代码privateStringa(HttpServletRequestrequest) {
Entryentry=null;
try {
entry=SphU.entry("HelloWorld");
StringBuilderheaderSb=newStringBuilder();
Enumeration<String>enumeration=request.getHeaderNames();
while (enumeration.hasMoreElements()) {
StringheaderName=enumeration.nextElement();
Enumeration<String>val=request.getHeaders(headerName);
while (val.hasMoreElements()) {
StringheaderVal=val.nextElement();
headerSb.append(headerName+":"+headerVal+",");
            }
        }
return"A"+SERVICE_TAG+"["+inetUtils.findFirstNonLoopbackAddress().getHostAddress() +"]"+" -> "+restTemplate.getForObject("http://sc-B/b", String.class);
    } catch (BlockExceptionex) {
System.err.println("blocked!");
    } finally {
if (entry!=null) {
entry.exit();
        }
    }
}

需要编码那就自然会有许多的弊端,要增加依赖要改代码,要重新发布,难以做到即上即下...到处都是成本。

那么我们如何可以不编写一行代码,就可以做到对 com.alibabacloud.mse.demo.AApplication.AController#a 的限流降级能力呢?

配置运行时白屏化规则

配置运行时白屏化规则,并选择当前应用的自定义埋点类型的接口,并填入类与方法。

当然可以看到,我们白屏化规则能力不仅仅支持动态限流降级,还支持任意点位的访问日志以及请求上下文的收集

观察到指定方法的监控数据

我们在应用治理找到目标应用,在接口监控 > 自定义埋点中看到指定方法com.alibabacloud.mse.demo.AApplication.AController#a 的监控数据

配置流控规则

我们可以点击接口概览右上角的“新增防护规则”按钮,添加一条流控规则:

我们可以配置最简单的 QPS 模式的流控规则,比如上面的例子即限制该接口每秒单机调用量不超过 1次。

配置规则后,稍等片刻即可在监控页面看到限流效果:


被拒绝的流量也会返回错误信息。MSE 自带的框架埋点都有默认的流控处理逻辑,如 Web 接口被限流后返回 429 Too Many Requests,DAO 层、java 方法被限流后抛出异常等。

总结

我们将运行时白屏化能力抽象为如下规则:WhiteScreenRule = Taget + Action

Target:

  • ResourceTarget: 目标接口,支持Web、Rpc、SQL 以及任意的自定义方法
  • WorkloadTarget: 目标实例,可以选择所有机器或指定机器 IP
  • TrafficCondition: 是否仅针对异常、慢调用、全链路灰度标签

Action:

  • 相关上下文诊断信息的收集,参数、返回值、线程上下文、Target对象、类加载器信息等
  • 后续链路是否日志打印
  • 进行限流降级
  • 指定流量进行打标染色(规划中)

近期 MSE 将推出基于上述规则的模型结合动态 Enhance 能力的日志治理,我们不仅仅有基于动态 Enhance 能力的任意点位的限流降级,还可以帮助我们洞察全链路流量运行的行为,并做出实时的治理与保护。


MSE Sentinel 不仅在阿里内部淘宝、天猫等电商领域有着广泛的应用,在互联网金融、在线教育、游戏、直播行业和其他大型政央企行业也有着大量的实践。有了针对任何方法都可以做到限流降级的能力后,我们可以快速赋予任意一个微服务系统具备流量防护的能力,让我们有更多的时间专注于业务的快速发展,关于系统的稳定性就放心地交给 MSE ,让专业的团队做专业的事情。

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
1月前
|
运维 监控 数据库
构建高效后端:从代码优化到系统监控的全方位策略
【6月更文挑战第12天】本文深入探讨了如何打造一个高效、稳定的后端系统。我们将从代码层面的最佳实践出发,逐步扩展到系统架构设计,再到性能监控和故障排查,提供一系列实用的技巧和工具,帮助开发者提升后端服务的性能和可靠性。
|
24天前
|
消息中间件 物联网 数据处理
TDengine 数据接入功能支持 Wonderware 了,不需一行代码完成迁移工作
TDengine 3.2.3.0 引入了 Wonderware Historian (AVEVA Historian) 连接器,简化了数据迁移至 TDengine 的过程,增强时序数据管理与分析。此连接器解决了传统实时数据库扩展性问题,提供成本效益高、国产化的替代方案。TDengine 已支持多种数据源集成,如 OPC、Kafka、MQTT等,打造统一数据平台,助力企业数字化转型。作为高性能时序数据库,TDengine 提供云原生解决方案,减少系统复杂度,加速业务创新。
26 6
|
1月前
|
JSON 测试技术 API
API接口测试指南:确保接口稳定性与可靠性的实践
API接口测试是确保软件产品质量的重要组成部分。通过遵循本指南中的测试步骤和最佳实践,开发者可以有效地验证API的功能、性能和安全性,从而提升软件的整体质量和用户满意度。
|
9月前
|
Kubernetes 网络虚拟化 Perl
k8s常用的网络插件优化方案|干货
k8s常用的网络插件优化方案|干货
|
数据采集 缓存 运维
jpOwl一款高性能的后端业务监控,动态配置策略规则的工具包
jpOwl一款高性能的后端业务监控,动态配置策略规则的工具包
jpOwl一款高性能的后端业务监控,动态配置策略规则的工具包
|
数据采集 调度 数据库
如何实现通用爬虫并检测可用性?
我们的目标:根据配置文件信息, 加载爬虫,抓取HTTP代理,进行校验,如果可用,写入到数据库中
|
2月前
|
SQL 监控 Java
无需编写一行代码,实现任何方法的流量防护能力
本文介绍了如何通过MSE服务治理一键实现任意点位的流控降级,任意点位包含但不限于Web、Rpc、SQL、Redis等访问接口、任意编写的业务方法、框架的接口等等。
无需编写一行代码,实现任何方法的流量防护能力
|
存储 SQL 数据可视化
模板化的封装,降低业务代码开发
做这些业务设计时,核心思想是:把常用的逻辑进行封装,流程设计为可配置,这样即可在一定时间内应对业务的需求和变化,降低开发成本的支出,从而使研发更侧重核心业务的管理和抽象封装等内容。
139 0
模板化的封装,降低业务代码开发
|
负载均衡 API 调度
语聊源码,任务分发系统需要具备的功能
语聊源码,任务分发系统需要具备的功能
|
安全 程序员 数据库
可控参数带来的网站漏洞修复建议方案
网站中存在的越权漏洞,首先我们来讲一下什么是关键可控参数,也就是说像我们的一些关键参数,例如use ID order by ID就是一些关键的参数,必须是你的这么一个测试者,是能够去对其控制的。如果这个参数已经挟持了,或者说他有固定的这个值。那此时的话就不称为可控参数了。而关键就是你的改动必须能造成这个越权效果的一种称为关键参数。我们一定要快速定位到这种关键可控的这个参数之后,我们才能够更快速的去找到对应的这么一个越权漏洞。
160 0
可控参数带来的网站漏洞修复建议方案