千家信息网

微服务治理实践中如何对单点异常进行自动摘除

发表于:2024-11-18 作者:千家信息网编辑
千家信息网最后更新 2024年11月18日,今天就跟大家聊聊有关微服务治理实践中如何对单点异常进行自动摘除,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。微服务架构下,稳定性和高可用性一个
千家信息网最后更新 2024年11月18日微服务治理实践中如何对单点异常进行自动摘除

今天就跟大家聊聊有关微服务治理实践中如何对单点异常进行自动摘除,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

微服务架构下,稳定性和高可用性一个永恒的话题,在实际的治理过程中,我们有可能会遇到以下场景:

  • 某个应用灰度发布,先上了几台机器,由于代码逻辑写的有问题,造成线程池满,出现运行异常。

  • 服务端集群中,某几台机器由于磁盘满,或者是宿主机资源争抢导致 load 过高,客户端出现调用超时。

  • 服务端集群中,某几台机器由于线程池满,造成 Full Garbage Collection。

在以上 3 种场景中,由于客户端并不法感知已经出现问题的那些服务端,依然会发送请求到这些机器上,造成业务调用报错,上游的机子将会被下游的某台机子的短暂故障拖垮,造成应用雪崩的风险。

面对这种场景,如果仅仅为此而进行服务降级,对应用的伤害未免过大,但如果我们可以检测出服务集群中某些故障机子,并对其进行短暂隔离,即可有效保障服务的高可用与系统的稳定性,同时给运维人员提供了宝贵的缓冲时间,用于问题定位,排除故障。

下面为大家介绍如何实现离群实例摘除。

Microservice Outlier Ejection (微服务离群实例摘除)

  • 什么是离群实例摘除

当单点发生夯机异常时,consumer 能主动判断,并将对应的 provider 实例短时间剔除,不再请求,在一定时间间隔后再继续访问。同时,具有全局异常判断能力,当 provider 异常实例的数量过多时,并且超过一定的控制比例,说明此时 provide 整体服务质量低下,该机制仅保持摘除一定的比例。

  • 离群实例摘除的功能

从服务层容错能力上,对业务稳定性进行增强,有效解决单点故障的问题。

  • 与熔断的区别

熔断是指当服务的输入负载激增时, 避免服务被迅速压垮导致雪崩效应,而对负载进行断路的一种方式 。 熔断一般由熔断请求判断算法,熔断恢复机制,熔断报警等模块组成。隔离是指,为了避免在依赖的服务故障时候造成的故障扩散,而采取的将系统进行单元化设计的一种架构方法。

若仅仅由于服务端集群中单点异常问题,就采用熔断降级方案,将会对应用的伤害过大,离群实例摘除可以有效地解决单点异常问题从而保证服务质量。若 provider 整体服务质量低下时,离群摘除效果不再明显,此时可以采用熔断降级功能。

  • 离群实例摘除支持的版本

只要您的应用版本在列表中,您无需改动一行代码就可以使用到离群实例摘除功能。

目前支持版本开发中版本(即将支持)
Dubbo2.5.0~2.7.3< 2.5.0 dubbox 版本
Spring CloudD、E、F、G、HC

目前已经覆盖了市面上大部分微服务场景,后续我们将会持续支持开源最新的 Dubbo/Spring Cloud 版本。

我们提供了 Dubbo 和 Spring Cloud 两种场景的离群摘除功能,本文将先介绍一下 Dubbo Microservice Outlier Ejection 的实践与效果。

下面将通过在 EDAS 上通过演示 Dubbo 离群摘除功能及效果。

企业级分布式应用服务EDAS(Enterprise Distributed Application Service)是一个应用托管和微服务管理的 PaaS 平台,提供应用开发、部署、监控、运维等全栈式解决方案,同时支持 Dubbo、Spring Cloud 等微服务运行环境。

https://www.aliyun.com/product/edas

准备

接下来以微服务Demo为例子示范离群摘除功能,读者可以从github中下载验证

https://github.com/aliyun/alibabacloud-microservice-demo/tree/master/src

微服务Demo是一个简单的电商项目,下图为项目结构,cartservice 为 Dubbo 框架的购物车服务 provider,productservice 为Spring Cloud提供的商品详情服务 provider,frontend 为web controller即前端展示页面,可以理解为consumer。

cdn.com/012c8ebbb65144e189f6731a6f021a4dc23468da.png">

我们将以cartservice服务即Dubbo服务端为例子,展示离群实例摘除功能。

EDAS 上部署微服务 Demo

首先 cd cartservice切换到 cartservice 目录下,再通过 mvn clean install 打包,通过 cd cartservice-provider/target 切换到target目录下,我们可以看到新生成的 cartservice-provider-1.0.0-SNAPSHOT.jar 包,然后在 EDAS上 创建一个 cartservice 应用。

然后启动应用,到目前为止,我们启动了一个 cartservice-provider。点击按此实例规格扩容,该服务我们部署在两个实例上。
lADPDgQ9rWd_0YNLzQLq_746_75_jpg_620x10000q90g

我们在这个 provider 的 com.alibabacloud.hipstershop.provider.CartServiceImpl 类中可以看到,这个 provider 是提供了viewCart 和 addItemToCart 的两个关于购物车的服务,我们在 viewCart 中加入一些模拟运行时异常的逻辑。

    @Value("${exception.ip}")    private String exceptionIp;    @Override    public List viewCart(String userID) {        if (exceptionIp != null && exceptionIp.equals(getLocalIp())) {            throw new RuntimeException("运行时异常");        }        return cartStore.getOrDefault(userID, Collections.emptyList());    }

其中 exceptionIp 为 ACM 配置中心的exception.ip的配置项,若该项配置为本机ip时,该服务throw RuntimeException,用于模拟业务异常的场景。

  • 为什么将 cartservice 扩容到两个实例,想必大家也猜到了,运行时通过配置ACM配置中心指定其中一个实例的IP,模拟出一个实例异常的场景。

接下来,我们需要部署 frontend / productservice 两个服务,方式一样,分别上传 frontend/target/frontend-1.0.0-SNAPSHOT.jar 和 productservice/productservice-provider/target/productservice-provider-1.0.0-SNAPSHOT.jar

从下图可以看到,我们的微服务Demo在EDAS部署上去了。

模拟业务异常

进入到 frontend 应用中,我们看到其实例的公网 ip 为 47.99.150.33。

点击View Cart 访问至 http://47.99.150.33:8080/cart

然后继续访问 http://47.99.150.33:8080/cart ,发现 50 % 的概率错误页面

11

此时,我们写一个脚本,定时大量访问 http://47.99.150.33:8080/cart 模拟请求。

while :do        result=`curl $1 -s`        if [[ "$result" == *"500"* ]]; then                echo `date +%F-%T` $result        else                echo `date +%F-%T` "success"        fi        sleep 0.1done

然后 sh curlservice.sh http://47.99.150.33:8080/cart

我们看到不断重复的每秒钟 10 次的 50% 的调用成功率。

其实也可以理解到,下游的服务质量随着上游的某台机子的异常而急剧下降,甚至可能导致下游服务被上游某些机子的(系统、业务)异常给拖垮。

开启离群摘除策略

下面我将演示离群摘除的策略的开启及其效果的展示。

创建

我们进入到 EDAS 左侧列表的 [微服务管理] 下的 [离群实例摘除] 界面中,并选择创建离群实例摘除策略。

如上图可以选择命名空间、填写策略名称、选择该策略支持的框架类型(Dubbo/Spring Cloud)。

选择生效应用

这些参数都提供了默认值,需要根据自己应用的具体情况调整最合适的值,由于需要保护的 RuntimeException 属于业务异常于是选上 网络异常+业务异常。(需要注意的是即使摘除实例比例上限配得特别低,向下取整数小于1,当集群中实例数目大于1,且某一实例异常,我们也会摘除一实例)。

创建完成

可以看到策略的信息则创建完成。

策略

看到了我们创建的离群摘除策略,且是针对Dubbo框架,并且针对的是 网络异常+业务异常 的异常类型。

验证离群摘除效果

这时,我们看到,再感知到异常后,离群摘除功能生效,请求调用一阵子后,均返回正确结果。

客户端感知到某台服务端机子异常后,主动摘除。仅仅调用业务正常的 Provider 实例,同时我们也可以通 ARMS(EDAS监控系统) 监控看到服务质量的上升,以及流量从异常 Provider 中摘除。

Dubbo框架可以从 /home/admin/.opt/ArmsAgent/logs 目录下的日志中,搜索日志中的 "OutlierRouter" 关键字可以看到一系列离群实例摘除的事件日志。

修改/关闭离群摘除策略

对于EDAS的应用我们支持通过控制台动态修改和删除离群摘除策略。

  • 对应策略规则的修改

点击 修改生效应用 或者 编辑策略。

控制台的操作,对应用中的配置都是实时生效的,若删除策略后,默认关闭相关策略。

若我们打开ARMS监控观察具体的调用情况。

ARMS监控

若我们开启监控,将会直观看到流量与请求错误等信息。

开启离群摘除前

如下图方式开启,然后跳转至ARMS(EDAS监控系统)应用监控页面,我们需要把三个应用都开启高级监控。

从以下拓扑图中我们看到,流量不断地访问到cartservice服务上。

可以看到,在开启了离群摘除的那个点只后,错误率从50%明显下降。

Dubbo Agent 方案技术架构

对于用户来说,无需改动一行代码,一行配置,即可享受到稳定性增强的能力。

离群实例摘除技术

Outlier Detection 离群检测

均是基于时间窗口的数据统计。

两种实现
1、Dubbo 2.7 版本通过向链路中嵌入一个MetricsFilter,对于链路的每个request/response做打点处理,统计rt、调用成功与否、异常类型,并且已endpoint(ip+port)为key存储

2、在 Agent 底座中统计经过的http请求,通过url、rt、状态码、异常类型等数据结果,统计最近时间窗口的数据(目前写死 10 秒,暂时不透出)

实时统计前N秒的调用信息,作为离群实例摘除动作的依据。

Outlier Ejection 离群摘除

Dubbo 基于 Dubbo Router 实现,对于调用的上游服务对应的所有 invokers 中,拉黑掉"不健康"的节点,同时记录拉黑的信息。

Dubbo-Router控制逻辑
每次请求过来仅仅check一下并标记状态,后台有专门两个线程将标记的流量进行判断是否进入隔离列表或从中剔除,修改拉黑信息等耗时操作,最大程度上保证请求的实时性。

Spring Cloud 基于 扩展 LoadBalace 实现,原理相似。

看完上述内容,你们对微服务治理实践中如何对单点异常进行自动摘除有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

0