当前位置: 首页 > news >正文

常熟建设设银行网站百度关键词优化曝光行者seo

常熟建设设银行网站,百度关键词优化曝光行者seo,后台管理网站开发,淮南本地网概述 除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方API等。例如,支付的时候,可能需要远程调用银联…

概述

除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方API等。例如,支付的时候,可能需要远程调用银联提供的API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。

在这里插入图片描述

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

Sentinel在1.8.0版本对熔断降级做了大的调整,可以定义任意时长的熔断时间,参照Hystrix引入了半开启恢复的支持。

熔断状态有以下三种:

状态说明
OPEN熔断开启状态,拒绝所有请求
HALF_OPEN半开状态,如果接下来的一个请求顺利通过则表示结束熔断,否则继续熔断
CLOSE熔断关闭状态,请求顺利通过

熔断状态参考枚举类com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreaker.State

/*** Circuit breaker state.*/
enum State {/*** In {@code OPEN} state, all requests will be rejected until the next recovery time point.*/OPEN,/*** In {@code HALF_OPEN} state, the circuit breaker will allow a "probe" invocation.* If the invocation is abnormal according to the strategy (e.g. it's slow), the circuit breaker* will re-transform to the {@code OPEN} state and wait for the next recovery time point;* otherwise the resource will be regarded as "recovered" and the circuit breaker* will cease cutting off requests and transform to {@code CLOSED} state.*/HALF_OPEN,/*** In {@code CLOSED} state, all requests are permitted. When current metric value exceeds the threshold,* the circuit breaker will transform to {@code OPEN} state.*/CLOSED
}

在这里插入图片描述

熔断降级规则说明

熔断降级规则(DegradeRule)包含下面几个重要的属性:

Field说明默认值
resource资源名,即规则的作用对象
grade熔断策略,支持慢调用比例/异常比例/异常数策略慢调用比例
count慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值
timeWindow熔断时长,单位为s
minRequestAmount熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入)5
statIntervalMs统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入)1000 ms
slowRatioThreshold慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

在这里插入图片描述

熔断策略

慢调用比例

慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用RT(Response Time),即最大的响应时间,请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断,熔断状态变为OPEN。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用RT则结束熔断(CLOSED),若大于设置的慢调用RT则会再次被熔断(OPEN)。

举个例子:针对资源/sentinel/slowRatio进行降级,

@RequestMapping("/slowRatio")
public String slowRatio(Integer num) throws InterruptedException {// 模拟慢请求TimeUnit.SECONDS.sleep(5);return String.valueOf(10 / num);
}

降级规则配置如下:

在这里插入图片描述

熔断效果如下:

在这里插入图片描述

异常比例

异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是01,代表0%100%。

注意异常降级仅针对业务异常,对Sentinel限流降级本身的异常(BlockException)不生效。为了统计异常比例或异常数,需要通过 Tracer.trace(ex)记录业务异常。

示例:

Entry entry = null;
try {entry = SphU.entry(resource);// Write your biz code here.// <<BIZ CODE>>
} catch (Throwable t) {if (!BlockException.isBlockException(t)) {Tracer.trace(t);}
} finally {if (entry != null) {entry.exit();}
}

如果使用了sentinel的适配器模块,如Sentinel Dubbo Adapter, Sentinel Web Servlet Filter或@SentinelResource注解会自动统计业务异常,无需手动调用。

异常数

异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

熔断器事件监听

Sentinel支持注册自定义的事件监听器监听熔断器状态变换事件(state change event)。

示例:

@PostConstruct
public void init() {EventObserverRegistry.getInstance().addStateChangeObserver("logging",(prevState, newState, rule, snapshotValue) -> {// 变换至 OPEN state 时会携带触发时的值log.error("{} -> {}, snapshotValue={}", prevState, newState, snapshotValue);});
}

监听上面的规则会打印如下的日志,可以从日志中看到中间会熔断5s,5s过后放一个请求进来,状态变为HALF_OPEN,这一个请求耗时500ms,超过阈值,又触发了熔断。

2023-03-25 10:56:28.422 ERROR 16296 --- [io-8030-exec-16] c.m.user.controller.DegradeController    : CLOSED -> OPEN, snapshotValue=1.0
2023-03-25 11:00:53.279 ERROR 16296 --- [nio-8030-exec-8] c.m.user.controller.DegradeController    : OPEN -> HALF_OPEN, snapshotValue=null
2023-03-25 11:00:53.839 ERROR 16296 --- [nio-8030-exec-8] c.m.user.controller.DegradeController    : HALF_OPEN -> OPEN, snapshotValue=1.0
2023-03-25 11:00:58.879 ERROR 16296 --- [nio-8030-exec-8] c.m.user.controller.DegradeController    : OPEN -> HALF_OPEN, snapshotValue=null

源码分析

DegradeSlot

Sentinel的熔断是由责任链中的最后一个DegradeSlot来实现的。

@Spi(order = Constants.ORDER_DEGRADE_SLOT)
public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> {@Overridepublic void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,boolean prioritized, Object... args) throws Throwable {// 在触发后续slot前执行熔断的检查performChecking(context, resourceWrapper);fireEntry(context, resourceWrapper, node, count, prioritized, args);}void performChecking(Context context, ResourceWrapper r) throws BlockException {// 根据资源名称查找断路器CircuitBreakerList<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());if (circuitBreakers == null || circuitBreakers.isEmpty()) {return;}// 遍历所有的CircuitBreaker,判断是否让这个请求通过for (CircuitBreaker cb : circuitBreakers) {// tryPass里面只做了状态检查,熔断是否关闭或者打开/*** @see AbstractCircuitBreaker#tryPass(com.alibaba.csp.sentinel.context.Context)*/if (!cb.tryPass(context)) {throw new DegradeException(cb.getRule().getLimitApp(), cb.getRule());}}}@Overridepublic void exit(Context context, ResourceWrapper r, int count, Object... args) {Entry curEntry = context.getCurEntry();//如果当前其他slot已经有了BlockException直接调用fireExit,不用继续走熔断逻辑了if (curEntry.getBlockError() != null) {fireExit(context, r, count, args);return;}// 根据资源名称查找断路器CircuitBreakerList<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());if (circuitBreakers == null || circuitBreakers.isEmpty()) {fireExit(context, r, count, args);return;}if (curEntry.getBlockError() == null) {// passed request//调用CircuitBreaker的onRequestComplete()方法for (CircuitBreaker circuitBreaker : circuitBreakers) {circuitBreaker.onRequestComplete(context);}}fireExit(context, r, count, args);}
}

进入DegradeSlot时,只会检查断路器是否已经打开,再根据是否超过了重试时间来开启半开状态,然后就直接返回是否通过。

而真正判断是否需要开启断路器的地方时在exit()方法里面,因为这个方法是在业务方法执行后调用的,只有在业务方法执行完成后,断路器才能收集到业务异常或者业务方法的执行时间来判断是否打开断路器。

先来看进入DegradeSlot的entry()方法,这里调用了CircuitBreaker.tryPass()方法,CircuitBreaker有ExceptionCircuitBreaker和ResponseTimeCircuitBreaker两种类型的断路器,CircuitBreaker继承关系图如下:

在这里插入图片描述

AbstractCircuitBreaker

entry()方法实际上调用了AbstractCircuitBreaker.tryPass()方法,这里只做了一个处理,如果断路器开启,但是上一个请求距离现在已经过了重试间隔时间就开启半启动状态。

public boolean tryPass(Context context) {// Template implementation.if (currentState.get() == State.CLOSED) {// 关闭状态,返回true,让请求通过return true;}if (currentState.get() == State.OPEN) {// For half-open state we allow a request for probing.// 如果断路器开启,但是上一个请求距离现在已经过了重试间隔时间就开启半开状态return retryTimeoutArrived() && fromOpenToHalfOpen(context);}// 半开状态,直接返回false,拒绝请求return false;
}protected boolean retryTimeoutArrived() {// 判断当前时间是否超过重试时间return TimeUtil.currentTimeMillis() >= nextRetryTimestamp;
}protected boolean fromOpenToHalfOpen(Context context) {// OPEN -> HALF_OPENif (currentState.compareAndSet(State.OPEN, State.HALF_OPEN)) {// 通知观察者// 可通过EventObserverRegistry.getInstance().addStateChangeObserver注册观察者监听状态的变化notifyObservers(State.OPEN, State.HALF_OPEN, null);Entry entry = context.getCurEntry();entry.whenTerminate(new BiConsumer<Context, Entry>() {@Overridepublic void accept(Context context, Entry entry) {// Note: This works as a temporary workaround for https://github.com/alibaba/Sentinel/issues/1638// Without the hook, the circuit breaker won't recover from half-open state in some circumstances// when the request is actually blocked by upcoming rules (not only degrade rules).if (entry.getBlockError() != null) {// Fallback to OPEN due to detecting request is blocked// 如果异常了// HALF_OPEN -> OPENcurrentState.compareAndSet(State.HALF_OPEN, State.OPEN);notifyObservers(State.HALF_OPEN, State.OPEN, 1.0d);}}});return true;}return false;
}

ResponseTimeCircuitBreaker

exit()方法调用了ExceptionCircuitBreaker和ResponseTimeCircuitBreaker的onRequestComplete()方法。

ResponseTimeCircuitBreaker

public void onRequestComplete(Context context) {// 取得当前滑动窗口SlowRequestCounter counter = slidingCounter.currentWindow().value();Entry entry = context.getCurEntry();if (entry == null) {return;}// 请求完成时间long completeTime = entry.getCompleteTimestamp();if (completeTime <= 0) {completeTime = TimeUtil.currentTimeMillis();}// 请求响应时间long rt = completeTime - entry.getCreateTimestamp();if (rt > maxAllowedRt) {// 请求响应时间>最大响应时间// 慢调用数+1counter.slowCount.add(1);}// 总的请求+1counter.totalCount.add(1);handleStateChangeWhenThresholdExceeded(rt);
}private void handleStateChangeWhenThresholdExceeded(long rt) {if (currentState.get() == State.OPEN) {// OPEN 直接返回,已经有其他请求触发熔断降级了return;}if (currentState.get() == State.HALF_OPEN) {// In detecting request// TODO: improve logic for half-open recovery// HALF_OPEN放了一个请求进来if (rt > maxAllowedRt) {// HALF_OPEN -> OPENfromHalfOpenToOpen(1.0d);} else {// HALF_OPEN -> CLOSEfromHalfOpenToClose();}return;}List<SlowRequestCounter> counters = slidingCounter.values();long slowCount = 0; // 慢请求数long totalCount = 0; // 总请求数for (SlowRequestCounter counter : counters) {slowCount += counter.slowCount.sum();totalCount += counter.totalCount.sum();}if (totalCount < minRequestAmount) {// 总请求数小于最小请求数,直接返回,不熔断return;}double currentRatio = slowCount * 1.0d / totalCount;if (currentRatio > maxSlowRequestRatio) {// 当前慢请求比例 > 最大慢请求比例transformToOpen(currentRatio);}if (Double.compare(currentRatio, maxSlowRequestRatio) == 0 &&Double.compare(maxSlowRequestRatio, SLOW_REQUEST_RATIO_MAX_VALUE) == 0) {// 当前慢请求比例 = 最大慢请求比例 = 1.0transformToOpen(currentRatio);}
}

ExceptionCircuitBreaker

com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.ExceptionCircuitBreaker#onRequestComplete

public void onRequestComplete(Context context) {Entry entry = context.getCurEntry();if (entry == null) {return;}Throwable error = entry.getError();SimpleErrorCounter counter = stat.currentWindow().value();if (error != null) {// 异常数+1counter.getErrorCount().add(1);}// 总请求数+1counter.getTotalCount().add(1);// 熔断逻辑,处理熔断状态的变更handleStateChangeWhenThresholdExceeded(error);
}private void handleStateChangeWhenThresholdExceeded(Throwable error) {if (currentState.get() == State.OPEN) {// OPEN 直接返回,已经有其他请求触发熔断降级了return;}if (currentState.get() == State.HALF_OPEN) {// HALF_OPEN放了一个请求进来// In detecting requestif (error == null) {// HALF_OPEN -> CLOSEfromHalfOpenToClose();} else {// HALF_OPEN -> OPENfromHalfOpenToOpen(1.0d);}return;}List<SimpleErrorCounter> counters = stat.values();long errCount = 0; // 异常请求数long totalCount = 0; // 总请求数for (SimpleErrorCounter counter : counters) {errCount += counter.errorCount.sum();totalCount += counter.totalCount.sum();}if (totalCount < minRequestAmount) {// 总请求数小于最小请求数 直接返回return;}double curCount = errCount;if (strategy == DEGRADE_GRADE_EXCEPTION_RATIO) {// Use errorRatio// 计算异常比例curCount = errCount * 1.0d / totalCount;}// 异常数大于阈值// 异常比例大于阈值if (curCount > threshold) {// CLOSE -> OPENtransformToOpen(curCount);}
}
http://www.rdtb.cn/news/21164.html

相关文章:

  • 九江有哪些做网站的公司免费推广
  • wordpress 主题名无锡网站seo顾问
  • wordpress 评论去审核优化大师安卓版
  • 平面设计与网站开发概述郑州关键词排名公司电话
  • 英文网站建设方案 ppt模板360广告推广平台
  • seo首页关键词优化什么是优化师
  • 做网站的ui陕西seo
  • 网站内做关键词连接企业营销策划是做什么的
  • 怎么给自己的网站设置关键词网站推广应该怎么做?
  • 网站建设的实施方式百度视频seo
  • 3d网页游戏平台seo快速软件
  • 四川佳和建设工程网站百度搜索资源平台token
  • 苹果做安卓游戏下载网站好网站建设案例
  • 目前做批发比较好的b2b网站怎么注册百度账号
  • 网站下做二级域名网站排名seo培训
  • 做外贸网站注册什么邮箱推广网站有哪些
  • 德州建设网站公司seo招聘信息
  • 学风建设网站版块郑州网络营销排名
  • 做图的模板下载网站有哪些广州网站优化平台
  • html编辑器的推荐个人网站seo入门
  • 哪个网站做体检预约的b2b网站排名
  • 珠海网站建设多少钱企业如何进行品牌推广
  • 网站服务器基本要素有哪些免费广告网
  • 略阳县有关作风建设的网站近期国际新闻
  • 深圳做网站推广排名百度在线客服问答
  • 推广游戏怎么拉人最快电商网站商品页的优化目标是什么
  • 平湖做网站关键词优化推广策略
  • 城阳网站改版seo高效优化
  • 做家教一般在哪个网站关键词查询的分析网站
  • 单页面的网站模板免费下载新产品推广方案策划