1.Sentinel控制台的安装

下载地址: 

Releases · alibaba/Sentinelx

下载后是一个jar包

进入目录

CMD命令

java -jar "sentinel-dashboard-1.8.8 .jar"

 如果发生了端口冲突则使用以下命令启动 修改端口号为8090

java  -Dserver.port=8090  -jar "sentinel-dashboard-1.8.8 .jar"

启动成功:

访问控制台

Sentinel Dashboard

账号密码默认都是sentinel

进入首页:

此时控制台已经安装完成

2.整合微服务

sentinel 的 starter 依赖:

将此sentinel依赖引入项目中

          <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>

yml配置:

spring:cloud:sentinel:transport:# 添加sentinel的控制台地址dashboard: 127.0.0.1:8090

如果是mvc的接口无需 @SentinelResource. 如果是业务方法, 需要 @SentinelResource

 @SentinelResource("hello")public String hello() {return "Hello Sentinel";}

@SentinelResource 注解用来标识资源是否被限流、降级。上述例子上该注解的属性 hello 表示资源名。 @SentinelResource 还提供了其它额外的属性如 blockHandler,blockHandlerClass,fallback 用于表示限流或降级的操作,更多内容可以参考 Sentinel 注解支持。

启用feign对sentinel的支持:

#启用feign对sentinel的支持
feign:sentinel:enabled: true  # 启用 Sentinel 对 Feign 的支持

此时我们只需要访问集成服务中的任意一个路径就能在sentinel中查看到

2.1 sentinel限流(blockHandler) 讲解

2.1.1没有使用@SentinelResource注解(使用默认限流响应)

创建一个类用于测试限流

SentinelRatilimitConteroller

@RestController
@RequestMapping("/order/sentinelRatilimitConteroller")
public class SentinelRatilimitConteroller {/*** 测试sentinel限流 (没有添加@)* @return*/@GetMapping("/testSentinelRatilimitA")public String testSentinelRatilimitA() {return "没有达到限流的规则 --- 正常访问";}}

此时我们启动服务 访问地址

localhost:8082/order/sentinelRatilimitConteroller/testSentinelRatilimitA

能够正常访问

进入sentinel的控制台,给当前路径添加限流规则

当QPS超过1时的请求会快速失败返回默认的失败响应

此时限流返回到响应为默认的响应

2.1.2使用@SentinelResource注解自定义限流响应

写法1:

在controller中添加以下代码

    /*** 测试sentinel限流 (添加了@SentinelResource)* @SentinelResource value 为 限流规则的资源名称 blockHandler 为限流规则的异常处理方法*/@GetMapping("/testSentinelRatilimitB")@SentinelResource(value = "testSentinelRatilimitB",blockHandler = "testSentinelRatilimitBHandleException")public String testSentinelRatilimitB() {return "没有达到限流的规则 --- 添加了@SentinelResource 正常访问";}/***作为(testSentinelRatilimitB)的限流异常返回方法*/public String testSentinelRatilimitBHandleException(BlockException e) {return "限流了 --- 添加了@SentinelResource 异常处理";}

* @SentinelResource value 为 限流规则的资源名称 blockHandler 为限流规则的异常处理方法

     使得方法testSentinelRatilimitB 触发限流时 返回 testSentinelRatilimitBHandleException方法

正常访问:localhost:8082/order/sentinelRatilimitConteroller/testSentinelRatilimitB

添加限流规则:
 

快速访问:

执行了自定义限流处理

对应关系图

写法2:(推荐)

如果需要独立设置一个 限流类还可以这样写

添加一个新的controller

指定了blockHandler类中的指定方法作为限流处理

    @GetMapping("/testSentinelRatilimitC")@SentinelResource(value = "testSentinelRatilimitC",blockHandlerClass = OrderBlockHandler.class,// 限流异常返回方法所在类blockHandler = "testSentinelRatilimitC") //指定限流异常返回方法public String testSentinelRatilimitC() {return "没有达到限流的规则 --- 添加了@SentinelResource 默认异常处理";}

访问localhost:8082/order/sentinelRatilimitConteroller/testSentinelRatilimitC

为他编写一个类 和方法 (方法必须被 pblic static 修饰

public class OrderBlockHandler {// 必须是public static方法// 参数和返回类型要与原方法一致,最后加一个BlockException参数public static String testSentinelRatilimitC(BlockException ex) {return "触发限流了";}}

设置限流规则

快速访问:

2.2异常处理(fallback)

为一个接口配置 @SentinelResource(value = "testSentinelRatilimitD",

fallback = "testSentinelRatilimitDfallback")

fallback属性表示当前方法遇到异常会调用指定的方法

    @GetMapping("/testSentinelRatilimitD/{id}")@SentinelResource(value = "testSentinelRatilimitD",blockHandler = "testSentinelRatilimitDBlockHandler",fallback = "testSentinelRatilimitDfallback")public String testSentinelRatilimitD(@PathVariable("id") Integer id) {if (id == 0){throw new RuntimeException("id 不能为0");}return "没有达到限流的规则 --- id为"+ id;}//作为限流 处理public String testSentinelRatilimitDBlockHandler(@PathVariable("id") Integer id,BlockException e) {return "已触发限流 --- id为"+ id;}//作为 熔断 降级 异常处理public String testSentinelRatilimitDfallback(@PathVariable("id") Integer id,Throwable e) {return "触发率异常处理,传入id为:"+ id;}

2.2.1测试限流

访问地址:localhost:8082/order/sentinelRatilimitConteroller/testSentinelRatilimitD/1

为他设置限流规则:

多次访问:

触发限流规则,走了BlockHandler 所配置的方法

2.2.2测试异常

访问

http://localhost:8082/order/sentinelRatilimitConteroller/testSentinelRatilimitD/0

传入id值为0,我们设置id为0时会抛出异常,看看是否会走fallback所配置的方法

成功触发fallback

3.热点参数限流

在我们比如商城服务中的商品流量是不均匀的,我们可能要对同一个接口的不同参数进行限流

例如

在查询某个商品信息时,同样根据商品id进行查询商品,商品ID: 1:华为 2:小米 3:苹果

查询接口

queryPhone(int id);

传入id为1的量较大,那么我们就需要对id为1的商品进行限流,如图:

写一个方法:

    /*** 热点参数限流*/@GetMapping("/testSentinelRatilimitE/{id}")@SentinelResource(value = "testSentinelRatilimitE",blockHandler = "testSentinelRatilimitEBlockHandler")public String testSentinelRatilimitE(@PathVariable("id") int id){return "没有触发限流传入id为:"+ id;}/*** 热点参数限流处理*/public String testSentinelRatilimitEBlockHandler(int id,BlockException ex){return "触发限流处理,传入id为:"+ id;}

访问 :localhost:8082/order/sentinelRatilimitConteroller/testSentinelRatilimitE/0

参数索引: 写0时则为接口中的第一个参数

索引为0

统计窗口:表示*秒内统计的量

表示这个接口 带上参数ID时 QPS达到1开始限流

访问接口:localhost:8082/order/sentinelRatilimitConteroller/testSentinelRatilimitE/0

触发了限流

参数例外项:

例如当我们传入id为1时,我们的限流规则变成QPS为3才进行限流

上面的参数表示,当带参数索引为0时,限流QPS为1 ,参数例外项:当参数索引0 传入值为1 时,限流阈值QPS提升为3才限流

务必要点击添加按钮

测试发现id等于1时 ,只有QPS达到3才会触发限流

4.sentinel规则持久化(不会因为微服务重启丢失配置)

我们服务配置完成后,我们的微服务重启会导致我们这个服务的所有的配置丢失,不可能每重启一次我们就重新配置一次限流规则,所以需要持久化,持久化到哪里呢? 我们会选择持久化到配置中心 nacos中 

在服务中引入新的Maven坐标

<!--sentinel持久化-->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

修改yml配置

配置ds1 ds2 ds3 分别代表(流控规则)(熔断降级规则) (热点参数规则)的持久化配置

我们以流控规则作为演示

打开nacos创建对应的配置文件

内容:

[{"resource": "testSentinelRatilimitE","limitApp": "default","grade": 1,"count": 1,"strategy": 0,"controlBehavior": 0,"clusterMode": false}
]
// [
//   {
//     // 🔹【资源名称】你想保护的是哪个接口或功能?
//     // 这里是:testSentinelRatilimitE
//     // 代码中要用 SphU.entry("testSentinelRatilimitE") 来标记这个资源
//     "resource": "testSentinelRatilimitE",//     // 🔹【限流对象】对谁限流?
//     // "default" 表示:所有人都一样,一视同仁
//     // 你也可以写成 "appA"、"appB",实现不同应用不同策略
//     "limitApp": "default",//     // 🔹【限流方式】按什么标准限流?
//     // 1 = 按每秒请求数(QPS)来限
//     // 0 = 按并发线程数来限(不常用)
//     "grade": 1,//     // 🔹【限流阈值】最多允许多少流量?
//     // 这里是:每秒最多 1 个请求
//     // 超过第 1 个就直接拒绝,不让进
//     "count": 1,//     // 🔹【限流策略】怎么判断要不要限?
//     // 0 = 直接对自己限流(最简单常用)
//     // 1 = 当另一个资源被限流时,我也跟着限(关联限流)
//     // 2 = 只对某个调用链路限流(比如 A 调 B 才限)
//     "strategy": 0,//     // 🔹【触发限流后怎么办?】
//     // 0 = 立刻拒绝,抛出“被限流”错误(快速失败)
//     // 1 = 先预热,慢慢放行(适合突发流量)
//     // 2 = 排队等待,一个一个处理(削峰填谷)
//     "controlBehavior": 0,//     // 🔹【是单机还是集群?】
//     // false = 每台机器独立限流(单机模式,适合大多数场景)
//     // true = 多台机器共享一个总限流值(需要额外配置集群)
//     "clusterMode": false
//   }
// ]

!!!!非常非常难用,需要自己手动写json用于配置持久化,Sentinel控制台配置成为摆设,因为控制台上写的配置不会持久化,必须自己写!!!!

同样是阿里巴巴的产品 Nacos比sentinel好用太多了!

重启 当前服务

访问localhost:8082/order/sentinelRatilimitConteroller/testSentinelRatilimitE/1

nacos 配置限流规则成功

来到sentinel控制台查看限流规则

成功从nacos中读取限流规则

5.Sentinel集成OpenFeign实现fallback熔断降级

往公共API模块中引入sentinel maven 依赖

<!--sentinel-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

在api接口中添加fallbackFactory属性并创建对应的类

创建

StockApiFallback.class
@Component
public class StockApiFallback implements FallbackFactory<stockApi> {@Overridepublic stockApi create(Throwable cause) {return new stockApi() {@Overridepublic ResultData<String> reduceInventory() {throw new RPCException("201","调用库存服务调用失败");}@Overridepublic Integer reduceStock() {throw new RPCException("201","调用库存服务调用失败");}};}}

在fallback 的时候为了保证fallback后全局事务还能正常的回滚,fallback一般抛出自定义异常让事务回滚,并且全局异常处理器 处理整形后才返回给用户

自定义异常类:

@Data
public class RPCException extends RuntimeException{private String code;private String message;private Object data;public RPCException(String code,String message,Object data) {super(message);this.message = message;this.code = code;this.data =data ;}public RPCException(String code,String message) {super(message);this.message = message;this.code = code;}}

自定义异常捕获

@RestControllerAdvice
@Slf4j
public class RPCExceptionHandler {// 拦截自定义业务异常@ExceptionHandler(RPCException.class)public ResultData handleBizException(RPCException e) {log.warn("远程调用异常: code={}, msg={}", e.getCode(), e.getMessage());return ResultData.fail(e.getCode(),"系统出现错误,请稍后再试"); // 通常返回 200,业务码区分}}

重点:!!!!   然后在调用者模块 配置文件中开启OpenFeign 支持Sentinel

feign:sentinel:enabled: true  # 启用 Sentinel 对 Feign 的支持

,然后重新启动 测试全局事务回滚是否正常

发现系统出现异常后,使用的是全局异常处理器返回的消息

并且,事务全部正确回滚

任务完成

6.Sentinel结合网关Gateway(限流熔断,貌似有BUG希望得到指点)

在Gateway网关服务中添加Maven依赖

<!--Gateway 结合 Sentinel做限流-->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
<!--javax-->
<dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</version><scope>compile</scope>
</dependency>

创建Gateway配置类

package com.xiaog.config;import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.PostConstruct;
import java.util.*;@Configuration
public class GatewaySentinelConfiguration {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewaySentinelConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {// Register the block exception handler for Spring Cloud Gateway.return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}/*** ========================================分割线======================================= 以上的代码不需要改动*//*** Spring 容器初始化的时候执行该方法*/@PostConstructpublic void doInit() {// 加载网关限流规则 initGatewayRules(); //  加载网关限流规则和熔断规则// 加载自定义限流异常处理器(处理+自定义返回信息的内容,类似触发流控规则保护)initBlockHandler(); //触发限流和熔断时会调用自定义的限流异常处理器}/*** 网关限流规则* 建议直接在 Sentinel 控制台上配置*/private void initGatewayRules() {Set<GatewayFlowRule> rules = new HashSet<>();/*resource:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称count:限流阈值intervalSec:统计时间窗口,单位是秒,默认是 1 秒*/rules.add(new GatewayFlowRule("order-service") //限流id 在yml中配置的id Gatewa.routes.id.setCount(3) // 限流阈值.setIntervalSec(3)); // 统计时间窗口,单位是秒,默认是 1 秒rules.add(new GatewayFlowRule("stock-service").setCount(5) // 限流阈值.setIntervalSec(3)); // 统计时间窗口,单位是秒,默认是 1 秒// --------------------限流分组-----------end-----------// 加载网关限流规则GatewayRuleManager.loadRules(rules);// 加载限流分组
//        initCustomizedApis();// ---------------熔断-降级配置-------------DegradeRule degradeRule = new DegradeRule("order-service") // 资源名称.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) // 异常比率模式(秒级).setCount(0.5) // 异常比率阈值(50%).setTimeWindow(10) // 熔断降级时间(10s).setMinRequestAmount(2);//最小请求数为2DegradeRule degradeRule2 = new DegradeRule("stock-service") //调用这个服务 的时候 异常比例过高则会触发熔断.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) // 异常比率模式(秒级).setCount(0.5) // 异常比率阈值(50%).setTimeWindow(10).setMinRequestAmount(2);// 加载规则.DegradeRuleManager.loadRules(Arrays.asList(degradeRule,degradeRule2));// 打印当前所有规则System.out.println("=== 当前生效的熔断规则 ===");DegradeRuleManager.getRules().forEach(System.out::println);//        DegradeRuleManager.loadRules(Collections.singletonList(degradeRule));}/*** 自定义限流异常处理器(当服务被限流或者熔断时都会执行这个方法)*/private void initBlockHandler() {BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {Map<String, String> result = new HashMap<>(3);result.put("code", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));result.put("message", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase()+"系统繁忙");if (throwable instanceof DegradeException) {result.put("中文信息", "服务熔断,请稍后重试");} else if (throwable instanceof FlowException ||throwable instanceof ParamFlowException ||throwable instanceof SystemBlockException) {result.put("中文信息", "请求过多,请稍后重试");} else {// 兜底逻辑result.put("中文信息", "系统限流或熔断,请稍后重试");}return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON)//.body(BodyInserters.fromValue(result));.body(BodyInserters.fromObject(result));}};// 加载自定义限流异常处理器 GatewayCallbackManager.setBlockHandler(blockRequestHandler);}}

当前存在熔断BUG 当服务异常请求很多时 没办法进行熔断 依旧可以继续访问

有懂的通信麻烦帮忙找一下bug解决一下博主的疑惑

!!!!这个注解务必使用 

package javax.annotation;下的

然后重启测试限流

限流成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/92294.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92294.shtml
英文地址,请注明出处:http://en.pswp.cn/web/92294.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Numpy科学计算与数据分析:Numpy数学函数入门与实践

Numpy数学函数实战&#xff1a;探索数学运算的无限可能 学习目标 通过本课程的学习&#xff0c;学员将掌握Numpy中常用的数学函数&#xff0c;包括三角函数、指数函数和对数函数的使用方法&#xff0c;以及如何利用这些函数对数组进行高效的数学运算。本课程不仅会讲解理论知识…

BIGO Ads是什么?BIGO广告营销核心玩法解析

在全球化竞争白热化的当下&#xff0c;BIGO Ads凭借其覆盖150国家的庞大流量池和AI驱动的精准营销能力&#xff0c;已成为出海企业突破增长瓶颈的利器。2025年Q1数据显示&#xff0c;BIGO Ads广告业务同比增长27%&#xff0c;非直播收入占比达24.9%&#xff0c;成为欢聚集团第二…

人工智能领域、图欧科技、IMYAI智能助手2025年3月更新月报

2025年3月AI领域重要技术进展与平台更新概览 2025年3月&#xff0c;人工智能领域迎来一系列重要技术更新与平台功能迭代&#xff0c;尤其在多模态模型、图像生成编辑、视频生成、大型语言模型&#xff08;LLM&#xff09;性能提升等方面表现活跃。以下是对关键进展的梳理&#…

STM32HAL 快速入门(一):点灯前的准备 —— 从软件安装到硬件原理

前言 大家好&#xff0c;这里是 Hello_Embed。嵌入式开发的 “Hello World” 是点灯 —— 通过控制单片机引脚的高低电平&#xff0c;让 LED 亮灭。要实现这个功能&#xff0c;前期准备必不可少&#xff1a;从软件安装到硬件原理理解&#xff0c;每一步都很关键。本文就来详细说…

Python网络编程技术

一、网络编程基础概念 1.1 什么是网络编程&#xff1f; 定义&#xff1a;程序通过网络与其他程序进行通信的技术。核心目标&#xff1a;实现数据在不同主机或进程间的传输与交互。应用场景&#xff1a;Web服务、API调用、实时通信、分布式系统等。 1.2 网络通信模型 OSI七层…

基于PHP的快递管理系统的设计与实现

管理员&#xff1a;登录&#xff1a;管理员可以通过用户名和密码登录系统&#xff0c;进入管理员后台管理界面。个人中心&#xff1a;管理员可以查看和编辑个人信息&#xff0c;如姓名、联系方式等。用户管理&#xff1a;管理员可以管理系统中的用户信息&#xff0c;包括添加新…

WPF的C1FlexGrid的单元格回车换行输入

重写C1FlexGrid的按键事件PreviewKeyDown"flex_PreviewKeyUp" 定义按键方法private void flex_PreviewKeyUp(object sender, KeyEventArgs e){if (e.Key Key.Enter){// 获取当前编辑的单元格var cell CfgReviewItem.Selection;if (cell.Column > 0 && …

简单部署普罗米修斯(Promethus)与Grafana配置

环境信息&#xff1a;系统版本ubuntu2404k8s版本v1.22.2promethus节点IP192.168.31.210Grafana节点IP192.168.31.210node1节点IP192.168.31.214node2节点IP192.168.31.215部署Promethus&#xff08;https://prometheus.io/download/&#xff09; wget https://ghfast.top/https…

Redis 编译错误:缺少静态库文件,如何解决?

目录 一、问题背景 二、问题分析 三、解决方案&#xff1a;手动编译缺失依赖 四、重新编译 Redis 主程序 五、小结与补充建议 一、问题背景 在从源代码编译 Redis&#xff08;如 8.0.3 版本&#xff09;时&#xff0c;很多开发者可能会遇到如下错误信息&#xff1a; /us…

vscode+latex本地英文期刊环境配置

1、首先进行vscode的配置安装&#xff0c;这个网上很多教程直接安装就可以&#xff0c;我建议安装vscode就行&#xff08;https://code.visualstudio.com/Download&#xff09;&#xff0c;vs studio稍微有点复杂而且有点大没必要&#xff0c;单写论文和简单的代码编译&#xf…

8.6 CSS3rem布局

rem布局 rem &#xff08;font size of the root element&#xff09;是指相对于根元素的字体大小的单位。简单的说它就是一个相对单位。看到rem大家一定会想起em单位&#xff0c;em&#xff08;font size of the element&#xff09;是指相对于父元素的字体大小的单位。它们之…

第十五章、非合作关系设定下的多智能体强化学习

0 前言 根据上一章的内容&#xff0c;已知完全合作关系下的多智能体利益一致有相同的目标&#xff0c;而非合作关系下实际上智能体的奖励和回报都是不一样的&#xff0c;它们都在努力让自己的利益最大化而并不考虑整体利益。 1 非合作关系设定下的策略学习要注意的点&#xff1…

分布式微服务--GateWay(过滤器及使用Gateway注意点)

前言、Spring Cloud Gateway 与 Web 依赖冲突 <!-- 下面两个依赖不能同时使用 --><!-- Gateway 组件 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><ve…

latex in overleaf快速通关论文排版

文章目录 0 有效连接汇总 1 简介 1.1 latex是什么 1.2 overleaf是什么? 2 快速上手 步骤1 注册 步骤2 使用 (1) 找模板 (2) 整体论文的overleaf结构 (3) 编辑内容 打开可视化编辑 实时编译 编辑 (4) 导出 3 常规操作 3.1 公式 3.2 表格 3.3 图片 3.4 引用 3.5 代码块 3.6 设置…

OO SALV的栏位功能

SALV的栏位功能主要是通过CL_SALV_COLUMN_TABLE和CL_SALV_COLUMNS_TABLE这两个类的实现的。 SALV的栏位属性的详细功能包括异常状态图标、图标、符号、复选框、按钮、热点、超链接、单元格类型、单元格颜色、某一栏位颜色、某一行颜色&#xff0c;栏位隐藏等。关于颜色等样式属…

第2章:建模篇——第1节:点线面的选择与控制

目录 1.模式的切换 &#xff08;1&#xff09;编辑模式的切换 &#xff08;2&#xff09;点线面的切换 2.点线面的选择 &#xff08;1&#xff09;选择的设置 &#xff08;2&#xff09;循环选择 3.点线面的控制 4.总结 1.模式的切换 &#xff08;1&#xff09;编辑模…

深入解析嵌套事务:原理与应用

嵌套事务是指在事务执行过程中启动另一个事务形成的层级调用结构&#xff0c;主要用于处理跨服务或复杂业务场景的事务一致性控制。其核心是通过事务传播机制管理多个操作的原子性&#xff0c;具体原理和应用如下&#xff1a;一、核心概念与工作原理层级结构 嵌套事务由顶层事务…

[激光原理与应用-168]:测量仪器 - 对光学指标进行测量的仪器

一、基础光学参数测量仪器 - 频率/波长/功率光学显微镜用途&#xff1a;观察微小物体的显微图像&#xff0c;用于材料科学、生物学等领域。特点&#xff1a;高放大倍数和分辨率&#xff0c;可清晰显示微观结构。光谱分析仪用途&#xff1a;测量发光体的辐射光谱&#xff0c;分析…

MPC-in-the-Head 转换入门指南

1. 引言 本文将探讨构建零知识证明&#xff08;ZKP&#xff09;的一种非常有趣的方法&#xff1a; MPC-in-the-Head Transformation&#xff08;转换&#xff09;。 该方法最早由 2007 年的论文 Zero-knowledge from secure multiparty computation 提出&#xff0c;通常被称…

SpringBoot的优缺点

题目详细答案优点快速开发&#xff1a;Spring Boot 通过自动配置和大量的开箱即用功能&#xff0c;使得开发者可以快速启动和运行一个应用程序&#xff0c;无需进行繁琐的配置工作。简化配置&#xff1a;Spring Boot 提供了自动配置和 "starter" 依赖&#xff0c;简化…