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

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
注册配置 MSE Nacos/ZooKeeper,182元/月
简介: 有了针对任何方法都可以做到限流降级的能力后,我们可以快速赋予任意一个微服务系统具备流量防护的能力,让我们有更多的时间专注于业务的快速发展,关于系统的稳定性就放心地交给 MSE ,让专业的团队做专业的事情。

作者:十眠


背景


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


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


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


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


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


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


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


1.png


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


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


2.png


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


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


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

如何在运行时,给任意指定的方法增加一个流控降级能力呢?下面我将以一个 Demo 为例简单介绍。我们编写了如下一个业务代码,我们编写了一个简单的 Spring Boot 应用,其中 a 方法是一个随意编写的内部方法。


@SpringBootApplication
public class AApplication {
    public static void main(String[] args) {
        SpringApplication.run(AApplication.class, args);
    }
    @Api(value = "/", tags = {"入口应用"})
    @RestController
    class AController {
        ...
    @ApiOperation(value = "HTTP 全链路灰度入口", tags = {"入口应用"})
        @GetMapping("/a")
        public String restA(HttpServletRequest request) {
            return a(request);
        }
        private String a(HttpServletRequest request) {
            StringBuilder headerSb = new StringBuilder();
            Enumeration<String> enumeration = request.getHeaderNames();
            while (enumeration.hasMoreElements()) {
                String headerName = enumeration.nextElement();
                Enumeration<String> val = request.getHeaders(headerName);
                while (val.hasMoreElements()) {
                    String headerVal = 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 的监控数据,并且可以对其配置限流降级规则。


3.png


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


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


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


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


配置运行时白屏化规则


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


4.png


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


5.png


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


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


6.png


配置流控规则


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


7.png


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


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


8.png


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


总结


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


9.png


Target:


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


Action:


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


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


10.png


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


MSE 云原生网关预付费、MSE 注册配置预付费首购 8 折,首购 1 年及以上 7 折。点击此处,查看更多详情~

相关文章
|
10月前
|
JavaScript 前端开发 API
二、ArkTS 快速入门
ArkTS 是鸿蒙生态的应用开发语言,继承了 TypeScript 的语法,扩展了声明式 UI 开发能力。它支持状态管理、自定义组件、并发编程等特性,提高了代码的健壮性和运行性能。本文介绍了 ArkTS 的快速入门,包括声明式 UI、基本组成、@State 装饰器、组件声明和自定义组件等内容。
667 1
|
11月前
|
机器学习/深度学习 监控 自动驾驶
基于深度学习的图像识别技术研究进展###
本文旨在探讨深度学习在图像识别领域的最新研究进展,重点分析卷积神经网络(CNN)的技术创新、优化策略及其在实际应用中的成效。通过综述当前主流算法结构、损失函数设计及数据集增强技巧,本文揭示了提升模型性能的关键因素,并展望了未来发展趋势。尽管未直接涉及传统摘要中的研究背景、方法、结果与结论等要素,但通过对关键技术点的深度剖析,为读者提供了对领域现状与前沿动态的全面理解。 ###
|
12月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
413 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
Windows
修改Windows语言出现“我们无法获取此Windows显示语言”问题怎么办?
本文介绍在Windows 10操作系统中,修改系统的显示语言的方法;并解决在这一过程中,出现的“很抱歉,我们无法获取此Windows显示语言”报错问题~
525 2
修改Windows语言出现“我们无法获取此Windows显示语言”问题怎么办?
|
11月前
|
物联网 Linux 5G
Linux操作系统的演变与未来趋势####
本文深入探讨了Linux操作系统的发展历程,从最初的一个学生项目到如今全球最流行的开源操作系统之一。文章将分析Linux的核心优势、关键特性以及它在云计算、物联网和嵌入式系统中的应用前景。通过具体案例展示Linux如何推动技术创新,并预测其在未来技术生态中的角色。本文旨在为读者提供一个全面而深入的理解,帮助他们认识到Linux在现代计算环境中的重要性及其未来的潜力。 ####
|
12月前
|
存储 安全 网络协议
阿里云服务器通用型g7、通用型g8y、通用型g8i实例性能和适用场景对比与选择参考
目前阿里云在售的云服务器中,主要包含了第6代、第7代、第8代实例规格的云服务器产品,在选择云服务器实例规格时,对于需要平衡计算、存储和网络性能的应用场景来说,通用型g7、通用型g8y和通用型g8i实例是许多用户的热门选择。为了帮助大家更好地了解这三款实例的区别,并为选择提供参考,本文将详细对比它们的实例规格、CPU、内存、计算、存储、网络等方面的性能,并附上活动价格对比。让大家了解一下他们之间的不同,以供参考选择。
|
12月前
|
存储 自然语言处理 小程序
微信小程序多语言切换神器:简繁体切换功能完全指南
随着全球化的发展,支持多种语言的应用程序愈发重要。本文介绍了如何在微信小程序中实现简体与繁体字体之间的切换功能,以满足不同地区用户的需求。通过创建utils文件夹并编写相应的转换函数,开发者可以方便地实现语言切换,从而提升用户体验。文章中还附带了示例代码和效果图,帮助读者更好地理解和应用这一功能。
580 0
微信小程序多语言切换神器:简繁体切换功能完全指南
|
12月前
|
人工智能 安全 物联网
《龙蜥操作系统:开启自主创新的新纪元》
在数字化时代,操作系统作为信息技术核心,至关重要。龙蜥操作系统由国内顶尖团队研发,旨在打破国外技术垄断,实现自主可控。其具备高度安全性、卓越性能、良好兼容性和强大可扩展性,广泛应用于企业级应用、个人用户及物联网领域,并展现出广阔发展前景。通过持续技术创新、生态建设和国际化发展,龙蜥操作系统正推动我国信息技术产业迈向新高度。
360 1
|
传感器 供应链 安全
大数据技术的应用场景
大数据技术的应用场景
|
12月前
|
JavaScript 前端开发 NoSQL
无界 SaaS 数字生态工具:去平台中心化助力企业数字化转型
无界 SaaS 数字生态工具通过去平台中心化助力企业数字化转型,涵盖技术实现、商业逻辑、数据架构、用户界面设计等多方面。本文提供了一个简化的框架和示例代码,包括前端(React.js)和后端(Node.js + Express)的实现,帮助企业和开发者快速启动项目。示例代码涵盖了用户注册、登录和产品列表的获取功能,并提供了安全性、用户认证、数据确权等方面的注意事项。