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

【深入理解SpringCloud微服务】Sentinel源码解析——DegradeSlot熔断规则

Sentinel源码解析——DegradeSlot熔断规则

  • 断路器原理复习
  • DegradeSlot熔断规则原理
  • 源码解析
    • DegradeSlot#entry()
    • DegradeSlot#exit(Context, ...)
      • ResponseTimeCircuitBreaker
      • ExceptionCircuitBreaker

断路器原理复习

断路器一般有三个状态:关闭、打开、半开,三种状态间的转换如下图:

在这里插入图片描述

首先断路器一开始是闭合状态。

当调用失败达到阈值时,就会切换为打开状态。当断路器处于打开状态时,由于接口的正常逻辑无法执行,此时就会进行降级处理。

当断路器处于打开状态一段时间后,就会变成半开状态,此时断路器允许一次请求调用,如果这次请求调用成功,那么断路器切换为闭合状态,否则重新变成打开状态。

DegradeSlot熔断规则原理

DegradeSlot在entry方法中进行断路器状态的校验。如果断路器状态为关闭,则请求正常通过(执行正常的业务处理逻辑);如果断路器为打开状态,则判断断路器打开的持续时长是否已经大于等于允许重试的时间,如果是则变成半开状态并允许本次请求正常通过;否则本次请求不能正常通过,抛出DegradeException异常。

在这里插入图片描述

但是实际上我们可以给一个资源配置多个熔断规则,每个熔断规则对应一个断路器,因此entry方法实际上是这样:

在这里插入图片描述

只有所有的断路器都校验通过,才算真正的通过,否则有一个断路器校验不通过,都会抛出DegradeException。

如果都校验通过了,则进入目标业务逻辑的处理(如果其他规则也校验通过)。

业务逻辑执行完后,DegradeSlot的exit方法将被调用。DegradeSlot的exit方法的作用是根据本次调用的情况给断路器做统计,然后根据断路器最新的统计值以及断路器当前状态判断是否需要进行断路器状态切换。

在这里插入图片描述

Sentinel的断路器也是利用时间窗进行统计。并且根据我们设置的熔断策略的不同,会使用不同类型的断路器进行统计。

如果我们设置的熔断策略是“慢调用比例”,那么断路器会利用滑动时间窗统计总调用数和慢调用数,如果本次调用超过了设置的最大响应时长,那么就记一次慢调用。

如果我们设置的熔断策略是“异常数”或“异常比例”,那么断路器会利用滑动时间窗统计总调用数和异常调用数,如果本次调用发生了异常,会记一次异常调用。

在这里插入图片描述

不管是什么类型的断路器,最后都会根据统计值与当前状态判断是否需要切换状态。

如果当前断路器状态是打开,那么不需要干啥,继续维持打开状态。如果当前断路器是半开状态,当前调用是慢调用或者是异常调用,那么切换为打开状态,否则切换为闭合状态。以上两种状态都不是,那么当前断路器状态就是闭合状态,那么就根据统计值判断是否超过阈值,如果超了则切换为打开状态,否则保持闭合状态。

在这里插入图片描述

源码解析

DegradeSlot#entry()

    @Overridepublic void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,boolean prioritized, Object... args) throws Throwable {// 熔断规则校验performChecking(context, resourceWrapper);fireEntry(...);}
    void performChecking(Context context, ResourceWrapper r) throws BlockException {// 根据资源名称,从DegradeRuleManager中获取对应的所有断路器List<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());...// 遍历每个断路器,进行规则校验,如果其中一个校验失败,则抛出DegradeExceptionfor (CircuitBreaker cb : circuitBreakers) {if (!cb.tryPass(context)) {throw new DegradeException(cb.getRule().getLimitApp(), cb.getRule());}}}

DegradeSlot方法会从DegradeRuleManager中根据资源名称取得对应的所有断路器,然后遍历这些断路器,进行规则校验,如果其中有一个校验失败,则抛出DegradeException。

在这里插入图片描述

AbstractCircuitBreaker#tryPass(Context)

    @Overridepublic boolean tryPass(Context context) {// 如果是闭合状态,返回true,表示校验通过if (currentState.get() == State.CLOSED) {return true;}// 如果是打开状态,判断是否到了重试时间,如果是,则切换为半开状态,允许本次校验通过if (currentState.get() == State.OPEN) {return retryTimeoutArrived() && fromOpenToHalfOpen(context);}// 否则校验失败return false;}

如果当前断路器状态是闭合状态,那么直接放行。

如果当前断路器状态是打开状态,那么调用retryTimeoutArrived()判断是否到了可以重试的时间。如果到了可以重试的时间,那么调用fromOpenToHalfOpen方法尝试切换为半开状态,这里有可能会切换失败,因为有可能有多个线程并发尝试切换,只有成功切换的那一个线程被放行,其他的都会被拦截掉;如果没到可以重试的时间,那么返回false表示校验失败。

除了上面两种情况,还有一种情况是当前断路器本身处于半开状态,也就是上面两个if判断都不通过,那么这种请求也是返回false不允许当前请求通过的。

在这里插入图片描述

AbstractCircuitBreaker#retryTimeoutArrived()

    protected boolean retryTimeoutArrived() {return TimeUtil.currentTimeMillis() >= nextRetryTimestamp;}

retryTimeoutArrived方法很简单,就是判断一下当前时间戳是否大于等于断路器记录的下一次重试的时间戳nextRetryTimestamp。

在这里插入图片描述

AbstractCircuitBreaker#fromOpenToHalfOpen(Context)

    protected boolean fromOpenToHalfOpen(Context context) {// 使用CAS尝试切换为半开状态if (currentState.compareAndSet(State.OPEN, State.HALF_OPEN)) {...return true;}return false;}

fromOpenToHalfOpen方法则是通过CAS的方式尝试进行状态切换。

在这里插入图片描述

整个entry方法的流程如下:

在这里插入图片描述

DegradeSlot#exit(Context, …)

    @Overridepublic void exit(Context context, ResourceWrapper r, int count, Object... args) {Entry curEntry = context.getCurEntry();// 如果前面的校验没通过,这里就不需要统计了if (curEntry.getBlockError() != null) {fireExit(context, r, count, args);return;}// 根据资源名称获取所有的断路器List<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());...// 遍历每一个断路器,进行统计,以及状态切换for (CircuitBreaker circuitBreaker : circuitBreakers) {circuitBreaker.onRequestComplete(context);}fireExit(context, r, count, args);}

exit方法首先判断前面的规则校验是否没有通过,如果是,那么这里就不用做统计以及切换断路器状态了,因为规则校验没通过的话,当前请求是不会正常处理的。

如果请求被正常处理了,那么根据资源名称获取对应的所有断路器,然后遍历每一个断路器,进行统计和状态切换。

在这里插入图片描述

onRequestComplete方法又两个实现类,具体是什么类型,视我们选取的熔断策略而定。

ResponseTimeCircuitBreaker#onRequestComplete(Context):选择“慢调用比例”熔断策略时,断路器就是ResponseTimeCircuitBreaker类型,统计的是慢调用数和总调用数。
ExceptionCircuitBreaker#onRequestComplete(Context):选择“异常数”或者“异常比例”熔断策略时,断路器的类型就是ExceptionCircuitBreaker,统计的异常调用数和总调用数。

在这里插入图片描述

ResponseTimeCircuitBreaker

    @Overridepublic void onRequestComplete(Context context) {// slidingCounter.currentWindow()获取当前时间窗,返回的是WindowWrap类型// value()方法返回WindowWrap里面的泛型对象SlowRequestCounterSlowRequestCounter counter = slidingCounter.currentWindow().value();...// 完成时间long completeTime = entry.getCompleteTimestamp();...// 响应时长 = 完成时间 - 开始时间long rt = completeTime - entry.getCreateTimestamp();// 如果响应时长超过了最大允许的响应时长,则慢调用数+1if (rt > maxAllowedRt) {counter.slowCount.add(1);}// 总调用数+1counter.totalCount.add(1);// 处理断路器状态的切换handleStateChangeWhenThresholdExceeded(rt);}
  1. ResponseTimeCircuitBreaker的onRequestComplete首先获取当前时间窗WindowWrap,然后获取WindowWrap里面的泛型对象SlowRequestCounter。
  2. 然后计算根据entry对象记录的开始时间和结束时间计算响应时长,判断是否超过最大允许响应时长,如果超了,那么慢调用数+1。
  3. 然后总调用数+1,不管响应时长超没超。
  4. 最后处理断路器状态的切换。

在这里插入图片描述

ResponseTimeCircuitBreaker#handleStateChangeWhenThresholdExceeded(long)

    private void handleStateChangeWhenThresholdExceeded(long rt) {// 如果断路器状态是打开,不需要处理,继续维持打开if (currentState.get() == State.OPEN) {return;}// 断路器状态是半开if (currentState.get() == State.HALF_OPEN) {// 当前调用是慢调用,切换为打开状态if (rt > maxAllowedRt) {fromHalfOpenToOpen(1.0d);} else {// 当前调用时正常调用,切换为闭合状态fromHalfOpenToClose();}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);}...}
  1. 如果断路器状态是打开,那么不需要处理,继续维持打开。
  2. 如果断路器状态是半开,那么判断当前请求是否是慢调用,如果是慢调用,切换为打开状态,否则切换为闭合状态。
  3. 如果即不是打开状态也不是半开状态,那么计数当前慢调用数和总调用数。
  4. 判断总调用数是否小于最小请求数,如果是,那么直接返回,不往下处理,熔断规则不生效。
  5. 如果总调用数大于等于最小请求数,那么计数慢调用比例。
  6. 如果慢调用比例超过阈值,切换断路器状态为打开。

在这里插入图片描述

整个ResponseTimeCircuitBreaker的统计与状态切换流程如下图:

在这里插入图片描述

ExceptionCircuitBreaker

ExceptionCircuitBreaker#onRequestComplete(Context):

    @Overridepublic void onRequestComplete(Context context) {...Throwable error = entry.getError();// 获取当前时间窗的计数器SimpleErrorCounter counter = stat.currentWindow().value();// 处理过程是否发生异常if (error != null) {// 异常调用数+1counter.getErrorCount().add(1);}// 总调用数+1counter.getTotalCount().add(1);// 处理断路器状态切换handleStateChangeWhenThresholdExceeded(error);}

ExceptionCircuitBreaker类型断路器的处理流程大体上与ResponseTimeCircuitBreaker是类型的。

  1. 先取得当前时间窗对应的计数器。
  2. 判断处理过程是否发生异常,如果是,那么异常调用数加1,如果不是则异常调用数不用加1。
  3. 不管有没有发生异常,总调用数都加1。
  4. 最后处理断路器状态切换。

在这里插入图片描述

ExceptionCircuitBreaker#handleStateChangeWhenThresholdExceeded(Throwable)

    private void handleStateChangeWhenThresholdExceeded(Throwable error) {// 如果断路器状态是打开,不需要处理,继续维持打开if (currentState.get() == State.OPEN) {return;}// 断路器状态是半开if (currentState.get() == State.HALF_OPEN) {if (error == null) {// 当前调用是正常调用,切换为闭合状态fromHalfOpenToClose();} else {// 当前调用是异常调用,切换为打开状态fromHalfOpenToOpen(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) {// 如果熔断策略是“异常比例”,则计算异常比例赋值给curCount// 异常比例 = 异常调用数 / 总调用数curCount = errCount * 1.0d / totalCount;}// 如果大于阈值,则切换为打开状态if (curCount > threshold) {transformToOpen(curCount);}}

ExceptionCircuitBreaker处理状态切换的方法与ResponseTimeCircuitBreaker是高度相似的,与ResponseTimeCircuitBreaker不同的有以下两点:

  1. 如果熔断策略是“异常数”,那么curCount取值就是当前断路器记录的异常调用数;如果熔断策略是“异常比例”,那么curCount就要修改为计算得出的异常比例。
  2. 阈值threshold根据熔断策略的不同,记录的数值有不一样的意义。如果熔断策略是“异常数”,threshold记录的是异常数阈值;如果熔断策略是“异常比例”,threshold记录的时慢调用比例阈值。

在这里插入图片描述

整个ExceptionCircuitBreaker的统计与状态切换处理流程如下:

在这里插入图片描述

exit方法的整体处理流程如下:

在这里插入图片描述

相关文章:

【深入理解SpringCloud微服务】Sentinel源码解析——DegradeSlot熔断规则

Sentinel源码解析——DegradeSlot熔断规则 断路器原理复习DegradeSlot熔断规则原理源码解析DegradeSlot#entry()DegradeSlot#exit(Context, ...)ResponseTimeCircuitBreakerExceptionCircuitBreaker 断路器原理复习 断路器一般有三个状态&#xff1a;关闭、打开、半开&#xf…...

电脑系统bcd文件损坏修复方法:小白也会的修复方法

电脑系统bcd文件损坏怎么办?当电脑开机时出现bcd文件损坏&#xff0c;一般情况是由于电脑系统的引导坏了&#xff0c;需要进行修复。现在越来越多的小伙伴遇到电脑引导丢失或者安装后无法正常引导的问题&#xff0c;我们现在一般是pe下进行修复引导&#xff0c;那么电脑系统bc…...

链式存储结构

不强制要求数据在内存中集中存储&#xff0c;各个元素可以分散存储在内存中。 结点 结点由数据域、指针域组成。 头结点、头指针和首元结点 头指针&#xff1a;一个和结点类型相同的指针&#xff0c;它的特点是&#xff1a;永远指向链表中的第一个结点。上文提到过&#xf…...

Oracle 创建用户和表空间

Oracle 创建用户和表空间 使用sys 账户登录 建立临时表空间 --建立临时表空间 CREATE TEMPORARY TABLESPACE TEMP_POS --创建名为TEMP_POS的临时表空间 TEMPFILE /oracle/oradata/POS/TEMP_POS.DBF -- 临时文件 SIZE 50M -- 其初始大小为50M AUTOEXTEND ON -- 支持…...

媒体新闻发稿要求有哪些?什么类型的稿件更好通过?

为了保证推送信息的内容质量&#xff0c;大型新闻媒体的审稿要求一向较为严格。尤其在商业推广的过程中&#xff0c;不少企业的宣传稿很难发布在这些大型新闻媒体平台上。 媒体新闻发稿要求有哪些&#xff1f;就让我们来了解下哪几类稿件更容易过审。 一、媒体新闻发稿要求有哪…...

Qt中QVariant的使用

1.使用QVariant实现不同类型数据的相加 方法&#xff1a;通过type函数返回数值的类型&#xff0c;然后通过setValue来构造一个QVariant类型的返回值。 函数&#xff1a; QVariant mainPage::dataPlus(QVariant a, QVariant b) {QVariant ret;if ((a.type() QVariant::Int) &a…...

3.4 Go函数作用域(标识符)

作用域标识符 简单来说&#xff0c;作用域指的是标识符可以起作用的范围&#xff0c;即其可见范围。将标识符的可见性限制在一定范围内&#xff0c;这个范围就是作用域。 把标识符约束在一定的可见范围内&#xff0c;这个范围就是作用域。 1. 宇宙块 特点&#xff1a;预定义…...

搭建Spring Boot开发环境

JDK&#xff08;1.8及以上版本&#xff09; Apache Maven 3.6.0 修改settings.xml 设置本地仓库位置 <localRepository>D:/repository</localRepository> 设置远程仓库镜像 <mirror><id>alimaven</id><name>aliyun maven</name&…...

洛谷 P5709:Apples Prologue / 苹果和虫子

【题目来源】 https://www.luogu.com.cn/problem/P5709 【题目描述】 小 B 喜欢吃苹果。她现在有 m&#xff08;1≤m≤100&#xff09;个苹果&#xff0c;吃完一个苹果需要花费 t&#xff08;0≤t≤100&#xff09;分钟&#xff0c;吃完一个后立刻开始吃下一个。现在时间过去了…...

PyTorch张量操作reshape view permute transpose

1. reshape() 和 view() view和reshape都用于改变张量的shape view是reshape的一个特例&#xff0c;view要求张量在内存中是连续的&#xff0c;否则会抛出错误&#xff0c;view只能用于contiguous的张量 reshape会自动处理contiguous的情况&#xff0c;如果张量是contiguous…...

JAVAweb学习日记(八) 请数据库模型MySQL

一、MySQL数据模型 二、SQL语言 三、DDL 详细见SQL学习日记内容 四、DQL-条件查询 五、DQL-分组查询 聚合函数&#xff1a; 分组查询&#xff1a; 六、DQL-分组查询 七、分页查询 八、多表设计-一对多&一对一&多对多 一对多-外键&#xff1a; 一对一&#xff1a; 多…...

【ElasticSearch】 Java API Client 7.17文档

​ 本文章内容根据 Elastic Search Java API Client 7.17 版本官方文档 内容翻译而来&#xff0c;用于方便后续学习翻阅 序言 这是适用于 Elasticsearch 的官方 Java API Client 文档。该客户端针对所有 Elasticsearch API 提供强类型的请求和响应。 功能 所有 Elasticsearc…...

Python “字典” 实战案例:5个项目开发实例

Python “字典” 实战案例&#xff1a;5个项目开发实例 内容摘要 本文包括 5 个使用 Python 字典的综合应用实例。具体是&#xff1a; 电影推荐系统配置文件解析器选票统计与排序电话黄页管理系统缓存系统&#xff08;LRU 缓存&#xff09; 以上每一个实例均有完整的程序代…...

Qt中Widget及其子类的相对位置移动

Qt中Widget及其子类的相对位置移动 最后更新日期&#xff1a;2025.01.25 下面让我们开始今天的主题… 一、开启篇 提出问题&#xff1a;请看上图&#xff0c;我们想要实现的效果是控件黄色的Widge&#xff08;m_infobarWidget&#xff09;t随着可视化窗口&#xff08;m_glWidge…...

4.flask-SQLAlchemy,表Model定义、增删查改操作

介绍 SQLAlchemy是对数据库的一个抽象 开发者不用直接与SQL语句打交道 Python对象来操作数据库 SQLAlchemy是一个关系型数据库 安装 flask中SQLAlchemy的配置 from flask import Flask from demo.user_oper import userdef create_app():app Flask(__name__)# 使用sessi…...

字节跳动自研HTTP开源框架Hertz简介附使用示例

字节跳动自研 HTTP 框架 Hertz Hertz 是字节跳动自研的高性能 HTTP 框架&#xff0c;专为高并发、低延迟的场景设计。它基于 Go 语言开发&#xff0c;结合了字节跳动在微服务架构中的实践经验&#xff0c;旨在提供更高效的 HTTP 服务开发体验。 1. 背景介绍 随着字节跳动业务…...

Effective C++ 规则51:编写 new 和 delete 时需固守常规

1、背景 在 C 中&#xff0c;如果你需要为类自定义 new 和 delete&#xff0c;必须遵循一些约定和规则&#xff0c;以确保内存管理的一致性、可维护性和安全性。当我们使用 new 和 delete 操作时&#xff0c;C 编译器会&#xff1a; 调用全局或类特定的 operator new 来分配内…...

[RoarCTF 2019]Easy Calc1

题目 查看页面源代码 <script>$(#calc).submit(function(){$.ajax({url:"calc.php?num"encodeURIComponent($("#content").val()),type:GET,success:function(data){$("#result").html(<div class"alert alert-success">…...

【Bug 记录】el-sub-menu 第一次进入默认不高亮

项目场景&#xff1a; 项目场景&#xff1a;el-sub-menu 第一次进入默认不高亮 问题描述 例如&#xff1a;sub-menu 的 index 后端默认传过来是 number&#xff0c;我们需要手动转为 string&#xff0c;否则会有警告&#xff0c;而且第一次进入 sub-menu 默认不高亮。 解决方…...

自然语言处理——从原理、经典模型到应用

1. 概述 自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是一门借助计算机技术研究人类语言的科学&#xff0c;是人工智能领域的一个分支&#xff0c;旨在让计算机理解、生成和处理人类语言。其核心任务是将非结构化的自然语言转换为机器可以…...

Linux——冯 • 诺依曼体系结构

目录 一、冯•诺依曼体系结构原理二、内存提高冯•诺依曼体系结构效率的方法三、当用QQ和朋友聊天时数据的流动过程四、关于冯诺依曼五、总结 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系 流程&#…...

【FISCO BCOS】二十四、通过Java SDK对FISCO BCOS进行压力测试

Java SDK Demo是基于Java SDK的基准测试集合,能够对FISCO BCOS节点进行压力测试。Java SDK Demo提供有合约编译功能,能够将Solidity合约文件转换成Java合约文件,此外还提供了针对转账合约、CRUD合约以及AMOP功能的压力测试示例程序。本篇我们来讲讲使用java SDK压力测试的操…...

Gurobi基础语法之字典

Python中的字典&#xff1a;dict 我们先来介绍一下Python语法中的 dict 类型, 字典中可以通过任意键值来对数据进行映射&#xff0c;任何无法修改的python对象都可以当作键值来使用&#xff0c;这些无法修改的Python对象包括&#xff1a;整数(比如&#xff1a;1)&#xff0c;浮…...

汽车OEMs一般出于什么目的来自定义Autosar CP一些内容

汽车OEMs在使用AUTOSAR CP(Classic Platform)协议时,可能会根据自身的特定需求对标准协议进行修改,形成自己的企业标准(企标)。这种修改通常是为了满足特定的硬件平台、功能需求、安全要求或优化性能。以下是一些常见的修改场景和例子: 1. 硬件平台适配 企业可能会根据…...

设计模式的艺术-享元模式

结构性模式的名称、定义、学习难度和使用频率如下表所示&#xff1a; 1.如何理解享元模式 当一个软件系统在运行时产生的对象数量太多&#xff0c;将导致运行代价过高&#xff0c;带来系统性能下降等问题。 在享元模式中&#xff0c;存储这些共享实例对象的地方称为享元池&…...

Java使用FFM API调用SDL

首发于Enaium的个人博客 首先我们需要创建一个Gradle项目&#xff0c;之后设置项目的JDK版本&#xff0c;设置为22及以上版本。 plugins {kotlin("jvm") version "2.1.0" }group "cn.enaium" version "1.0-SNAPSHOT"repositories {…...

bash: ./xxx: No such file or directory

问题现象 在使用开源或他人可执行文件的时候&#xff0c;可能会遇到 bash: ./squashfs2sparse: No such file or directory 的报错&#xff1b;实际测试发现该文件存在&#xff0c;并且有可执行权限&#xff1b; 问题分析 通过对报错文件的分析 1&#xff1a;文件具有可执行…...

Linux(Centos 7.6)命令详解:wc

1.命令作用 打印文件的行数、单词数、字节数&#xff0c;如果指定了多个文件&#xff0c;还会打印以上三种数据的总和(Print newline, word, and byte counts for each FILE, and a total line if more than one FILE is specified) 2.命令语法 Usage: wc [OPTION]... [FIL…...

PHP EOF (Heredoc) 详解

PHP EOF (Heredoc) 详解 PHP 中的 EOF(End Of File)是一种非常有用的语法特性,允许开发者创建多行字符串。它特别适合于创建格式化文本,如配置文件、HTML 模板等。本文将详细讲解 PHP EOF 的用法、优势以及注意事项。 什么是 EOF? EOF 是一种特殊的字符串定义方式,它允…...

面向长文本的多模型协作摘要架构:多LLM文本摘要方法

多LLM摘要框架在每轮对话中包含两个基本步骤:生成和评估。这些步骤在多LLM分散式摘要和集中式摘要中有所不同。在两种策略中,k个不同的LLM都会生成多样化的文本摘要。然而在评估阶段,多LLM集中式摘要方法使用单个LLM来评估摘要并选择最佳摘要,而分散式多LLM摘要则使用k个LLM进行…...

第27章 测试驱动开发模式:深入测试技术

写在前面 这本书是我们老板推荐过的&#xff0c;我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后&#xff0c;我突然思考&#xff0c;对于测试开发工程师来说&#xff0c;什么才更有价值呢&#xff1f;如何让 AI 工具更好地辅助自己写代码&#xff0c;或许…...

C语言教程——文件处理(2)

目录 前言 一、顺序读写函数&#xff08;续&#xff09; 1.1fprintf 1.2fscanf 1.3fwrite 1.4fread 二、流和标准流 2.1流 2.2标准流 2.3示例 三、sscanf和sprintf 3.1sprintf 3.2sscanf 四、文件的随机读写 4.1fseek 4.2ftell 4.3rewind 五、文件读取结束的…...

QT TLS initialization failed

qt使用QNetworkAccessManager下载文件&#xff08;给出的链接可以在浏览器里面下载文件&#xff09;&#xff0c;下载失败&#xff0c; 提示“TLS initialization failed”通常是由于Qt在使用HTTPS进行文件下载时&#xff0c;未能正确初始化TLS&#xff08;安全传输层协议&…...

金融级分布式数据库如何优化?PawSQL发布OceanBase专项调优指南

前言 OceanBase数据库作为国产自主可控的分布式数据库&#xff0c;在金融、电商、政务等领域得到广泛应用&#xff0c;优化OceanBase数据库的查询性能变得愈发重要。PawSQL为OceanBase数据库提供了全方位的SQL性能优化支持&#xff0c;助力用户充分发挥OceanBase数据库的性能潜…...

在Kubernets Cluster中部署LVM类型的StorageClass - 上

适用场景 看到B站技术部门的文章&#xff0c;是关于如何在k8s集群部署Elastic Search和Click House等IO密集型数据库应用的。 因为要充分利用NvME SSD盘的IOPS&#xff0c;所有数据库应用都直接调用本地SSD盘做为stateful application的 Persistent Volumes。为了可用动态的分…...

mysql 学习6 DML语句,对数据库中的表进行 增 删 改 操作

添加数据 我们对 testdatabase 数据中 的 qqemp 这张表进行 增加数据&#xff0c;在这张表 下 打开 命令行 query console 在 软件中就是打开命令行的意思 可以先执行 desc qqemp; 查看一下当前表的结构。 插入一条数据 到qqemp 表&#xff0c;插入时要每个字段都有值 insert…...

【全栈】SprintBoot+vue3迷你商城(10)

【全栈】SprintBootvue3迷你商城&#xff08;10&#xff09; 往期的文章都在这里啦&#xff0c;大家有兴趣可以看一下 后端部分&#xff1a; 【全栈】SprintBootvue3迷你商城&#xff08;1&#xff09; 【全栈】SprintBootvue3迷你商城&#xff08;2&#xff09; 【全栈】Sp…...

2025年01月25日Github流行趋势

项目名称&#xff1a;it-tools 项目地址url&#xff1a;https://github.com/CorentinTh/it-tools项目语言&#xff1a;Vue历史star数&#xff1a;25298今日star数&#xff1a;212项目维护者&#xff1a;CorentinTh, apps/renovate, cgoIT, sharevb, marvin-j97项目简介&#xf…...

java后端之登录认证

基础登录功能&#xff1a;根据提供的用户名和密码判断是否存在于数据库 LoginController.java RestController Slf4j public class LoginController {Autowiredprivate UserService userService;PostMapping("/login")public Result login(RequestBody User user) {…...

2024年AI多极竞争:技术创新与商业突破

标题&#xff1a;2024年AI多极竞争&#xff1a;技术创新与商业突破 文章信息摘要&#xff1a; 2024年初&#xff0c;人工智能领域呈现多极竞争格局。OpenAI、Google和Mistral等公司在视频生成、大语言模型架构和模型能力方面实现突破性创新。这些进展体现了AI技术在多模态能力…...

25.1.25Java复习|数组

一、数组复习&#xff1a; import java.util.Scanner; import java.*; public class Example1 {public static void main(String[] args){Scanner scnew Scanner(System.in);String[] namesnew String[5];//创建了一个可以容纳5个字符串的数组for(int i0;i<5;i){System.ou…...

总结8..

#include <stdio.h> // 定义结构体表示二叉树节点&#xff0c;包含左右子节点编号 struct node { int l; int r; } tree[100000]; // 全局变量记录二叉树最大深度&#xff0c;初始为0 int ans 0; // 深度优先搜索函数 // pos: 当前节点在数组中的位置&#xff0c…...

谈谈对JavaScript 中的事件冒泡(Event Bubbling)和事件捕获(Event Capturing)的理解

JavaScript 中的事件冒泡&#xff08;Event Bubbling&#xff09;和事件捕获&#xff08;Event Capturing&#xff09;&#xff0c;是浏览器在处理事件时采用的两种机制&#xff0c;它们在事件的传播顺序上有显著区别。这两种机制帮助开发者在事件触发时&#xff0c;能够以不同…...

tcp/ip协议和ip协议,tcp/ip协议 ip协议

TCP/IP协议和IP协议在网络通信中扮演着重要的角色&#xff0c;它们之间既有联系又有区别。以下是对两者的详细解释&#xff1a; TCP/IP协议 定义&#xff1a; TCP/IP协议&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;是网络通信协议的一种&…...

【JavaEE进阶】Spring留言板实现

目录 &#x1f38d;预期结果 &#x1f340;前端代码 &#x1f384;约定前后端交互接口 &#x1f6a9;需求分析 &#x1f6a9;接口定义 &#x1f333;实现服务器端代码 &#x1f6a9;lombok介绍 &#x1f6a9;代码实现 &#x1f334;运行测试 &#x1f384;前端代码实…...

【模型】RNN模型详解

1. 模型架构 RNN&#xff08;Recurrent Neural Network&#xff09;是一种具有循环结构的神经网络&#xff0c;它能够处理序列数据。与传统的前馈神经网络不同&#xff0c;RNN通过将当前时刻的输出与前一时刻的状态&#xff08;或隐藏层&#xff09;作为输入传递到下一个时刻&…...

软件测试压力太大了怎么办?

本文其实是知乎上针对一个问题的回答&#xff1a; 目前在做软件测试&#xff0c;主要负责的是手机端的项目测试&#xff0c;项目迭代很快&#xff0c;每次上线前验正式都会发现一些之前验测试包时候没有发现的问题&#xff0c;压力太大了&#xff0c;应该怎么调整 看过我之前其…...

ES6 类语法:JavaScript 的现代化面向对象编程

Hi&#xff0c;我是布兰妮甜 &#xff01;ECMAScript 2015&#xff0c;通常被称为 ES6 或 ES2015&#xff0c;是 JavaScript 语言的一次重大更新。它引入了许多新特性&#xff0c;其中最引人注目的就是类&#xff08;class&#xff09;语法。尽管 JavaScript 一直以来都支持基于…...

【时时三省】(C语言基础)二进制输入输出

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 二进制输入 用fread可以读取fwrite输入的内容 字符串以文本的形式写进去的时候&#xff0c;和以二进制写进去的内容是一样的 整数和浮点型以二进制写进去是不一样的 二进制输出 fwrite 字…...

【2024年华为OD机试】(A卷,200分)- 农场施肥 (JavaScriptJava PythonC/C++)

一、问题描述 题目描述 某农场主管理了一大片果园,fields[i] 表示不同果林的面积,单位:平方米(m)。现在需要为所有的果林施肥,且必须在 n 天之内完成,否则会影响收成。小布是果林的工作人员,他每次选择一片果林进行施肥,且一片果林施肥完后当天不再进行施肥作业。 …...