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

php网站开发 实战教程如何建设酒店预订系统网站

php网站开发 实战教程,如何建设酒店预订系统网站,织梦网站密码忘记了,seo的优化步骤熔断降级 Slot 责任链上的最后一环#xff1a;熔断降级 DegradeSlot,熔断降级作为保护系统的一种强大手段,可以根据慢调用、异常比例和异常数进行熔断,并自定义持续时间以实现系统保护 规则配置 规则类中属性解析 与控制面板对应 // 其中资源名称在 AbstractRule 里。 pu…熔断降级 Slot 责任链上的最后一环熔断降级 DegradeSlot,熔断降级作为保护系统的一种强大手段,可以根据慢调用、异常比例和异常数进行熔断,并自定义持续时间以实现系统保护 规则配置 规则类中属性解析 与控制面板对应 // 其中资源名称在 AbstractRule 里。 public class DegradeRule extends AbstractRule {/*熔断策略 (0: 平均RT1: 异常比例2: 异常计数)*/private int grade RuleConstant.DEGRADE_GRADE_RT;// 阈值计数, 含义取决于所选择的熔断策略private double count;// 断路器断开后恢复时间(单位秒), 超时后, 断路器转换成半开状态, 允许部分请求通过private int timeWindow;// 触发熔断最低请求数private int minRequestAmount RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT;// RT模式下慢请求比例的阈值private double slowRatioThreshold 1.0d;// 间隔统计持续时间 (毫秒)private int statIntervalMs 1000; }grade熔断降级规则的类型取值范围为 慢调用比例: RuleConstant.DEGRADE_GRADE_RT0, 默认值就是慢比例异常比例: RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO1异常数: RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT2 count熔断降级的阈值具体含义取决于 grade 字段的值 慢调用比例: count 表示慢调用比例阈值异常比例: count 表示异常比例阈值异常数: count 表示异常数阈值 timeWindow: 熔断降级发生后的降级持续时间(单位秒)在这段时间内对应的资源将被降级, 超时后, 断路器转换成半开状态, 允许部分请求通过, 如果这部分请求还是不通过, 那么断路器转换成开状态, 继续熔断, 如果通过, 那么断路器转换成关状态 minRequestAmount: 熔断降级统计周期内的最小请求总数。仅当周期内的请求总数达到此值时才会根据 grade 和 count 进行熔断降级。 默认值为 RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT5 slowRatioThreshold慢调用比例阈值仅当 grade 为慢调用比例时生效。取值范围为 0 到 1 之间的小数表示慢调用请求占总请求的比例, 默认值为1 statIntervalMs熔断降级统计周期(单位毫秒)。在这个周期内Sentinel 会对请求进行统计以判断是否需要进行熔断降级。默认值为 1000 毫秒(1 秒) 断路器 不同的策略底层使用的算法不一样, 我们可以通过if-else进行, 也可以通过switch进行, 但是都不够优雅, 更加优雅的做法是, 使用策略模式, sentinel底层就是采用策略模式实现的 什么是策略模式不在赘述, 见这个链接策略模式 | 菜鸟教程 (runoob.com) CircuitBreaker 是一个断路器接口, 用于实现 Sentinel 的熔断降级功能。它定义了一些关键方法和一个内部枚举类型 State public interface CircuitBreaker {DegradeRule getRule();boolean tryPass(Context context);State currentState();void onRequestComplete(Context context);enum State {OPEN, // 开启HALF_OPEN, // 半开CLOSED // 关闭} }DegradeRule getRule()获取当前断路器所对应的熔断降级规则。boolean tryPass(Context context)尝试通过断路器 关闭状态(CLOSED): 则允许请求通过打开状态(OPEN): 则拒绝请求半开状态(HALF_OPEN): 则根据规则允许部分请求通过。 State currentState()获取当前断路器的状态(OPEN, HALF_OPEN, CLOSED)void onRequestComplete(Context context)在请求完成后调用此方法用于更新断路器的统计数据。 内部枚举类型 State OPEN表示断路器处于打开状态此时会拒绝所有请求HALF_OPEN表示断路器处于半开状态此时允许部分请求通过以检测系统是否已经恢复正常CLOSED表示断路器处于关闭状态此时允许所有请求通过 断路器接口实现类图如下 AbstractCircuitBreaker完成一些功能的基础功能 public abstract class AbstractCircuitBreaker implements CircuitBreaker {}具体的策略实现类会继承该抽象类完成一些独有的逻辑 public class ExceptionCircuitBreaker extends AbstractCircuitBreaker {}public class ResponseTimeCircuitBreaker extends AbstractCircuitBreaker {}规程初始化 熔断降级规则的初始化也是通过监听器模式来完成的。监听器就像是一个基础框架所有的规则都是基于这套框架来实现的 规则的存储和转换 两个Map用户存储熔断策略和熔断规则 public final class DegradeRuleManager {// 熔断策略private static volatile MapString, ListCircuitBreaker circuitBreakers new HashMap();// 熔断规则private static volatile MapString, SetDegradeRule ruleMap new HashMap(); }将调用者传入的 ListDegradeRule 转换为上述两个 HashMap private synchronized void reloadFrom(ListDegradeRule list) {// ListDegradeRule 转 ListCircuitBreakerMapString, ListCircuitBreaker cbs buildCircuitBreakers(list);// 将断路器策略MapString, ListDegradeRule rules buildCircuitBreakerRules(cbs);circuitBreakers.updateRules(cbs);ruleMap.updateRules(rules); }buildCircuitBreakers 这里使用了策略模式, 并使用swtich进行分发 /* ListDegradeRule 转 ListCircuitBreaker */ private MapString, ListCircuitBreaker buildCircuitBreakers(ListDegradeRule list) {// cbMap用于存储CircuitBreakerMapString, ListCircuitBreaker cbMap new HashMap(8);// 非空判断if (list null || list.isEmpty()) {return cbMap;}// 遍历列表for (DegradeRule rule : list) {// 非法校验if (!isValidRule(rule)) {RecordLog.warn([DegradeRuleManager] Ignoring invalid rule when loading new rules: {}, rule);continue;}// 如果规则的limitApp为空则将其设置为默认值if (StringUtil.isBlank(rule.getLimitApp())) {rule.setLimitApp(RuleConstant.LIMIT_APP_DEFAULT);}// 根据规则获取已存在的CircuitBreaker或创建新的CircuitBreakerCircuitBreaker cb getExistingSameCbOrNew(rule);if (cb null) {RecordLog.warn([DegradeRuleManager] Unknown circuit breaking strategy, ignoring: {}, rule);continue;}// 使用规则的资源名作为键将CircuitBreaker添加到cbMap对应的列表中如果cbMap中不存在该键则先创建空列表String resourceName rule.getResource();ListCircuitBreaker cbList cbMap.get(resourceName);if (cbList null) {cbList new ArrayList();cbMap.put(resourceName, cbList);}cbList.add(cb);}return cbMap; }/* 获取与给定降级规则相同的现有断路器或创建新的断路器 */ private static CircuitBreaker getExistingSameCbOrNew(/*Valid*/ DegradeRule rule) {// 根据给定的降级规则获取所有断路器的列表ListCircuitBreaker cbs getCircuitBreakers(rule.getResource());// 非空校验if (cbs null || cbs.isEmpty()) {return newCircuitBreakerFrom(rule);}// 遍历断路器for (CircuitBreaker cb : cbs) {// 果找到与给定降级规则相同的断路器则重用该断路器并返回if (rule.equals(cb.getRule())) {// Reuse the circuit breaker if the rule remains unchanged.return cb;}}// 执行到这里说明, 没有找到相同的断路器, 根据给定的规则创建新的断路器, 并返回return newCircuitBreakerFrom(rule); }/* 根据指定的降级规则创建一个断路器 */ private static CircuitBreaker newCircuitBreakerFrom(/*Valid*/ DegradeRule rule) {// 根据断路器策略进行分发switch (rule.getGrade()) {// RT响应时间case RuleConstant.DEGRADE_GRADE_RT:return new ResponseTimeCircuitBreaker(rule);// 异常比例, 异常数case RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO:case RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT:return new ExceptionCircuitBreaker(rule);default:return null;} }核心流程 熔断验证 public class DegradeSlot extends AbstractLinkedProcessorSlotDefaultNode {Overridepublic void entry(...) throws Throwable {// 熔断验证逻辑performChecking(...);// 放行fireEntry(context, resourceWrapper, node, count, prioritized, args);}Overridepublic void exit(...) {} }可以看到核心熔断验证逻辑在performChecking(), 那么它做了什么事 获取断路器熔断相关的校验, 失败就抛出降级异常 /* 熔断检查 */ void performChecking(Context context, ResourceWrapper r) throws BlockException {// 先根据资源name获取断路器ListCircuitBreaker circuitBreakers DegradeRuleManager.getCircuitBreakers(r.getName());if (circuitBreakers null || circuitBreakers.isEmpty()) {return;}// 调用每个断路器的 tryPass 方法进行验证for (CircuitBreaker cb : circuitBreakers) {// 验证失败则抛出异常进行熔断if (!cb.tryPass(context)) {throw new DegradeException(cb.getRule().getLimitApp(), cb.getRule());}} }可以看到真正判断是否触发熔断的是tryPass() tryPass()做了什么事? 检查当前断路器状态 关闭: 不需要熔断, 放行打开: 继续往下执行 断路器是打开状态, 判断当前系统时间大于等于下一次尝试恢复的时间 是: 将断路器状态更改成半开启否: 放行 /* 如果此次请求已经达到了断路器恢复时间并且将断路器的状态从打开变为半开启HALF_OPEN则放行反之拒绝 */ Override public boolean tryPass(Context context) {// 断路器为关闭状态if (currentState.get() State.CLOSED) {return true;}// 断路器为开启状态if (currentState.get() State.OPEN) {// 如果此次请求已经达到了断路器恢复时间并且将断路器的状态从打开变为半开启HALF_OPEN则放行反之拒绝return retryTimeoutArrived() fromOpenToHalfOpen(context);}return false; }retryTimeoutArrived() // nextRetryTimestamp下一次尝试恢复的时间 protected boolean retryTimeoutArrived() {// 如果当前系统时间大于等于下一次尝试恢复的时间也就是说已经到达了可以尝试恢复的时间则返回 true反之返回 falsereturn TimeUtil.currentTimeMillis() nextRetryTimestamp; }fromOpenToHalfOpen() /* 尝试将断路器的状态从打开OPEN更改为半开启HALF_OPEN。如果状态切换成功返回 true 表示请求放行否则返回 false 表示拒绝请求 */ protected boolean fromOpenToHalfOpen(Context context) {if (currentState.compareAndSet(State.OPEN, State.HALF_OPEN)) {// 这里使用观察者模式, 通知观察者, 当前断路器的状态从OPEN变成了HALF_OPENnotifyObservers(State.OPEN, State.HALF_OPEN, null);Entry entry context.getCurEntry();entry.whenTerminate(new BiConsumerContext, 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 wont 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 blockedcurrentState.compareAndSet(State.HALF_OPEN, State.OPEN);notifyObservers(State.HALF_OPEN, State.OPEN, 1.0d);}}});return true;}return false; }流程如下 断路器开关时机 熔断开关时期应该是触发配置阈值时, 但是数据何时采集? entry()为请求入口, 此时还没结束, 无法获取到异常数, RT相关信息, 而exit()请求出口, 此时请求已经结束, 可以获取到RT, 异常数相关信息, 所以数据再exit()中采集 代码如下 Override public void exit(Context context, ResourceWrapper r, int count, Object... args) {Entry curEntry context.getCurEntry();if (curEntry.getBlockError() ! null) {fireExit(context, r, count, args);return;}ListCircuitBreaker circuitBreakers DegradeRuleManager.getCircuitBreakers(r.getName());if (circuitBreakers null || circuitBreakers.isEmpty()) {fireExit(context, r, count, args);return;}// 如果没报错那就调用 onRequestComplete 方法来计数if (curEntry.getBlockError() null) {// 放行该请求// 这里使用for循环的原因: 因为一个资源的断路器有多个, 完全可以对某个资源既按照慢调用比例进行熔断又按照异常数进行熔断for (CircuitBreaker circuitBreaker : circuitBreakers) {circuitBreaker.onRequestComplete(context);}}fireExit(context, r, count, args); }onRequestComplete的作用计数, 当请求结束时会根据配置的熔断策略异常比例或异常数来更新计数器。如果达到阈值断路器状态将从 CLOSED 变为 OPEN , 具体实现看ExceptionCircuitBreaker和ResponseTimeCircuitBreaker, 下边分析 ExceptionCircuitBreaker 异常数: errorCount异常数 异常比例: 额外使用totalCount记录请求总数, 异常比例 errorCount / totalCount public class ExceptionCircuitBreaker extends AbstractCircuitBreaker {/*请求数据统计*/Overridepublic void onRequestComplete(Context context) {Entry entry context.getCurEntry();if (entry null) {return;}Throwable error entry.getError();// 获取当前值SimpleErrorCounter counter stat.currentWindow().value();// 如果此次请求报错了则将 errorCount 1if (error ! null) {counter.getErrorCount().add(1);}// 将 totalCount 总数 1用于计算异常比例counter.getTotalCount().add(1);// 根据当前请求的异常数/异常比例与设定阈值的关系调用handleStateChangeWhenThresholdExceeded(error)方法来执行相应的状态变更操作handleStateChangeWhenThresholdExceeded(error);}/*断路器开关变化逻辑处理*/private void handleStateChangeWhenThresholdExceeded(Throwable error) {// 如果当前断路器已经打开了则直接返回。if (currentState.get() State.OPEN) {return;}// 如果是半开启状态if (currentState.get() State.HALF_OPEN) {// 如果本次请求没出现异常则代表可以关闭断路器了因此 fromHalfOpenToClose 关闭断路器if (error null) {// 这里面会通知各个观察者fromHalfOpenToClose();} else {// 如果本次请求还是异常那就继续熔断打开断路器// 这里面会通知各个观察者fromHalfOpenToOpen(1.0d);}return;}// 执行到这里, 说明断路器处于一个关的状态ListSimpleErrorCounter 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;}// curCount表示为当前配置熔断触发阈值, 配置熔断策略不同, 含义也不同double curCount errCount;// 熔断策略为异常比例if (strategy DEGRADE_GRADE_EXCEPTION_RATIO) {// 计算异常比例, 公式: 异常比例 异常数 / 总请求数curCount errCount * 1.0d / totalCount;}// 当错误率或者错误数大于阈值则打开断路器if (curCount threshold) {// 这里面会通知各个观察者transformToOpen(curCount);}} }异常数/异常比例的熔断降级了流程如下 ResponseTimeCircuitBreaker 这里主要统计的是慢比例调用数据, 慢比例计算公式如下 响应时间RT 请求结束时间 - 请求开始时间 public class ResponseTimeCircuitBreaker extends AbstractCircuitBreaker {Overridepublic 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();// 判断响应时间是否超过最大允许响应时间若超过则将慢请求计数加1if (rt maxAllowedRt) {counter.slowCount.add(1);}// 不论请求是否为慢请求都将总请求计数加1counter.totalCount.add(1);// 根据当前请求的响应时间与设定阈值的关系调用handleStateChangeWhenThresholdExceeded(rt)方法来执行相应的状态变更操作handleStateChangeWhenThresholdExceeded(rt);} }降级 降级就是抛出异常, 抛出异常也是降级的一种手段Slot 相当于过滤器链过滤器阶段就给拦截了就不会进入到主业务流程当中也就不会去查询数据库等一系列业务逻辑。当然你可以捕获这个异常做一些你想做的事情这就是降级 总结 断路器分类和原理 异常断路器 负责异常数/异常比例请求结束时统计异常数和请求总数, 判断是否达到阈值, 达到阈值更改断路器状态 RT断路器: 负责的是响应时间计算请求结束和请求开始的差值, 和阈值比较, 判断是否达到阈值, 达到阈值更改断路器状态 断路器大体流程 计数对比阈值断路器验证 状态流转 OPEN: 断路器打开, 系统进入熔断状态HALF_OPEN: 断路器半开, 系统放行部分请求, 如果请求通过, 断路器切回关闭状态, 如果请求出现异常, 断路器切回打开, 继续熔断CLAOSE: 断路器关闭, 系统正常 如下图 HALF_OPEN像是一个中间态 参考资料 通关 Sentinel 流量治理框架 - 编程界的小學生 服务熔断是指什么
http://www.zqtcl.cn/news/970741/

相关文章:

  • 商城网站建设公司价格海安县建设局网站
  • 做精美得ppt网站知乎厦门官网建设公司
  • 做一个中型网站需要多少钱网站建设的费用是不是含税的
  • 网站上的广告是怎么做的连云港 网站 建设
  • 济南做网站的好公司有哪些怎么做自己的app软件
  • 淄博网站建设团队企业门户网站有哪些
  • 东莞网站建设 织梦建设茶叶网站的目的
  • 做网站的背景图片要多大做房产网站
  • 洛阳做网站公司在哪无锡网络营销推广软件
  • 医疗机械网站怎么做无锡短视频seo
  • 做网站建设哪家公司好如何营销推广
  • 陕西百威建设监理有限司网站做吉祥物设计看什么网站
  • 网络营销站点推广的方法高端网站开发价格
  • 内部优惠券网站怎么做最新国际新闻事件今天
  • 辽宁大学网站怎么做app开发用什么编程语言
  • 3d建模在线制作网站阿里云域名注册官网
  • 创建网站大约多少钱网站建设排序题
  • 大庆做网站找谁机构编制网站建设
  • 网站标题特效网站弹出的对话框怎么做
  • 找深圳网站建设wordpress 页面背景
  • 企业网站怎么维护上海注册建网站
  • 四川省建设工程造价信息网站便宜做网站价格
  • 医院网站优化策划网站开发的项目需求
  • 网站优化公司服务直播软件怎么开发
  • 网站建设 有道翻译织梦修改网站后备份
  • 苏州网联盛网站建设做最好的在线看片网站
  • 一个空间怎么放2个网站陕西城乡住房建设部网站
  • 如何购买虚拟主机做网站企业查名
  • 动易网站默认密码网站怎么做 吸引人
  • 站长工具国产2023二级建造师证书查询官方网站