【限流与Sentinel超详细分析】

Sentinel

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来保障微服务的稳定性。

1 Sentinel 基本概念

资源 (Resource):

  • 资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码;
  • 只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,服务名称作为资源名来标示资源。

规则 (Rule):围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

2 Sentinel核心功能

2.1 流量控制

任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求进行整型,如下图所示

在这里插入图片描述

流量控制主要有如下三个角度:

  • 限流指标,例如QPS,并发线程数等指标
  • 限流策略,例如直接限流(根据自己的指标来限流,关联限流(根据有关联关系的其他资源来限流),调用链路限流(根据指定路调用链路涌入的的流量来限流)
  • 限流效果,触发限流以后的请求该如何处理, 例如快速失败(fast fail),慢启动(warm up), 排队等待

2.2 熔断降级

除了流量控制以外,对调用链路中的不稳定资源进行处理, 保护整个调用链路, 也是 Sentinel 的作用之一。

2.2.1 熔断

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。

在服务内调用其它服务时, 比如基于 RestTemplate 进行调用时, 是同步式的调用, 发起调用的服务在被调用的服务返回前, 不能去做别的事情;

如果下游服务出现故障, 迟迟无法返回, 那么上游服务就被阻塞在调用下游服务的位置

随着新的请求不断到来, 将有越来越多的上游服务线程被阻塞在调用故障服务的位置, 进而使上游服务没有线程可用, 最终使上游服务也发生故障,

以此类推, 导致整个调用链路中的服务都不可用, 造成雪崩;

预防雪崩问题有以下几个方法:

  1. 超时时间: 设定超时时间, 请求超过一定时间没有响应, 就立即返回一个错误状态, 不会无休止等待;

    缺点是仍然会有请求到达故障, 并且数量没有限制, 服务器的线程被阻塞直到超时时间才被释放;

  2. 线程隔离: 遵循仓壁模式, 对当前服务的不同API, 设置其所能占用的并发线程数量的上限, 这样, 即使当前 API 内调用了某个故障的下游服务, 也不会耗尽当前服务的所有线程资源;

    sentinel中, 配置限流规则时, 设置最大线程数, 就有线程隔离的作用;
    缺点是仍然有一定数量的请求可以到达故障服务;

  3. 熔断机制: 根据响应时间, 错误响应比例等依据, 对故障业务进行熔断, 拦截访问该业务的请求; 对这些请求, 也不能置之不理, 比如我可以对这些请求进行降级处理;

2.2.2 降级

服务调用无法正常完成时, 例如被限流, 超时, 或者出现异常, 或者服务被熔断等后, 最好是我不能把请求扔在那不管, 对到来的请求, 可以执行一个替代的简化的处理逻辑, 这就是降级;

2.3 熔断和降级辨析

目的上来说, 熔断和降级, 都是为了提高系统的可用性, 都是为了防止系统崩溃;

熔断的侧重点是防止服务雪崩, 阻止对故障服务的调用, 防止因为调用故障服务导致当前服务资源耗尽,保护上游服务的稳定性。

降级侧重点是在服务出现问题时或者 QPS 过大时取消问题服务或者边缘服务的完整业务, 转而提供基本的服务。比如服务被熔断时, 就可以使用降级; 比如电商平台大促期间, 就可以对边缘业务进行降级处理;

熔断的时候, 可以配合降级机制, 阻止对故障服务调用的同时, 提供保底的基本的服务; 但降级一般不会触发熔断机制;

3 Sentinel的使用

Sentinel 可以分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。

使用 Dashboard 只需要下载 jar 包Releases · alibaba/Sentinel (github.com), 并通过命令行启动; 网页访问时, 默认用户名和密码都是 sentinel

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.3.jar

使用核心库, 需要导包

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

在服务中进行配置

spring:cloud:sentinel:transport:# 指定操作面板的地址dashboard: localhost:8080

3.1 定义资源

定义资源的方式有多种,其中比较常用是注解方式定义,框架自适配定义。

  • 框架自适配

    为了减少开发的复杂程度,Sentinel 对大部分的主流框架,例如 Web Servlet、Dubbo、Spring Cloud等都做了适配

    例如使用SpringMVC时, 一个请求的应用内路径就会被自动识别为资源;

  • 注解方式定义资源

    Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandlerfallback 函数来进行降级处理。示例:

    // 使用注解声明资源时, 一定要指定blockHandler, 并blockHandler一定要是public的
    // 否则触发限流时, 直接服务器内部错误500; 而自动识别的资源, 会自动输出
    // Blocked by Sentinel (flow limiting)
    @SentinelResource(blockHandler = "blockHandlerForGetUser")
    public User getUserById(String id) {//......
    }// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
    public User blockHandlerForGetUser(String id, BlockException ex) {return new User("admin");
    }
    

3.2 定义规则

Sentinel 的所有规则都可以在内存中动态地查询及修改,修改之后立即生效; 规则可以分为流控规则, 熔断规则, 热点规则, 授权规则等;

推荐使用 Dashboard 去定义规则;

4 流控规则

顾名思义, 用于流量控制的规则; 同一个资源可以对应多条限流规则。Sentinel 会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。

阈值类型

主要有两种统计类型,一种是统计线程数,另外一种则是统计 QPS; 其中线程数、QPS 值,都是 Sentinel 实时统计获取的。

  • 线程数限流用于保护服务器线程数不被耗尽, 可以防止雪崩。
  • 基于QPS的限流,直接限制同时处理请求的数量。当 QPS 超过某个阈值的时候,则采取措施进行流量控制;

流控模式

直接限流

即最直接的方式,根据被访问资源本身的流量,决定是否要限流;

关联流量限流

当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。

比如不同的 Sentinel Resource 对数据库同一个字段进行写操作,如果放任这两个 Sentinel Resource 争抢数据库资源,则争抢本身带来的开销会降低整体的吞吐量。

可使用关联限流来避免具有关联关系的资源之间过度的争抢,举例来说

  • read_dbwrite_db 这两个资源分别代表数据库读写;
  • 我们可以给 read_db 设置限流规则来达到写优先的目的:设置限流策略为关联流量限流, 同时设置关联资源为write_db
  • 这样当写库操作过于频繁时,读数据的请求会被限流。

链路限流

在高版本 Sentinel中, 已经不支持链路限流;

sentinel中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一棵调用树。这棵树的根节点是一个名字为 machine-root 的虚拟节点,调用链的入口都是这个虚节点的子节点。

                  machine-root/       \/         \Entrance1     Entrance2/             \/               \DefaultNode(nodeA)   DefaultNode(nodeA)

上图中来自入口 Entrance1Entrance2 的请求都调用到了资源 NodeA,Sentinel 允许只根据某个入口的统计信息对资源限流。比如我们可以设置 限流策略为 链路限流,同时设置 访问入口为 Entrance1 来表示只有从入口 Entrance1 的调用才会记录到 NodeA 的限流统计当中,而对来自 Entrance2 的调用漠不关心。

流控效果

只有在阈值类型为QPS的时候, 才能设置流控效果;

快速失败

该方式是默认的流量控制方式,当QPS超过阈值后,新的请求就会被立即拒绝,拒绝方式为直接抛出 FlowException, FlowExceptionBlockException 的子类;

慢启动

系统启动时, 不能上来就把流量拉到系统稳定运行时能承受的最大QPS, 多种原因:

  • 这时候各级缓存还没有产生, 所以启动时的平均响应时间要大于稳定后的平均响应时间, 所以启动的时候能承受的 QPS 要更小;

  • 刚启动时, 所有请求到来需要先建立TCP连接, 比较耗时, 稳定运行后只有部分请求 ( 新的客户端发来的请求 ) 需要建立连接;

通过慢启动,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮的情况。

如果将流控效果设置为慢启动, 则实际进行流控时, 实际的阈值是逐渐提高的, 一开始是设定值的 1/3, 最后才变为设定值;

流量达到阈值后新的请求还是快速失败的逻辑处理;

排队等待方式

根据设置的QPS计算出两个请求处理的最小间隔时间, 例如 QPS = 10, 则 间隔时间 = 100ms;

当请求到达时,如果当前请求速率未超过设置QPS,请求立即通过。

如果当前请求速率超过阈值,请求将进入等待队列,每经过间隔时间处理队列中的一个请求。

当队列非空时, 新到来的请求肯定超过了流量阈值(因为就是按阈值的速度在处理队列中的请求), 进入队列;

如果请求入队前, 根据队列大小计算预期等待时间, 如果超过设定的最大等待时间,请求将直接被拒绝。

热点规则

热点参数限流会统计资源方法传入的参数,并根据配置进行限流,热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

可以对某个位置上的参数进行控制

对 id 参数进行控制, 不论 id 的值是多少, 只要是携带 id 的请求, 就会参与限流;

@GetMapping("testSen")
@SentinelResource(value = "testSen", blockHandler = "testSenBlockHandler")
String testSen(@RequestParam(value = "id", required = false) Integer id){return "test Sen SUCCESS";
}

对固定位置上的参数的某个固定值进行限流, 也叫参数例外项

例如 一秒内, 最多有 2 个 id 值为 2022001 的请求通过;

5 熔断规则

熔断时, 新请求来到直接抛 DegradeException

限流时, 抛FlowException, 二者都继承自BlockException

熔断策略

Sentinel中, 有三种熔断触发策略,分别是慢调用比例 (SLOW_REQUEST_RATIO),异常比例 (ERROR_RATIO),异常数 (ERROR_COUNT)触发;

慢调用比例 (SLOW_REQUEST_RATIO):

  • 选择以慢调用比例作为阈值,需要设置最大 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。需要设置统计时长, 比例阈值, 最小请求数, 熔断时长;

  • 当统计时长内请求数目大于设置的最小请求数,并且慢调用的比例大于最大 RT,则接下来的熔断时长内请求会自动被熔断。

  • 经过熔断时长后熔断器会进入半开状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

异常比例 (ERROR_RATIO):

  • 当单位统计时长内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。

  • 经过熔断时长后熔断器会进入半开状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

  • 异常比率的阈值范围是 0 ~ 1, 代表百分比。

异常数 (ERROR_COUNT):

  • 当统计时长内总请求数目大于最小请求数, 并且异常请求的数目超过阈值之后, 会自动进行熔断。

  • 经过熔断时长后熔断器会进入半开状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

熔断效果

熔断时, 如果指定了降级逻辑 fallback, 就会执行降级的逻辑;

如果没有指定降级逻辑, 请求来到时就直接抛出降级异常, 将被 BlockHandler 处理, 如果有自定义的, 就用自定义的, 没有就用公用的 BlockHandler, 显示Blocked by Sentinel (flow limiting)

public class TestService {// 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,// 并且必须为 public static 函数.@SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})public void test() {System.out.println("Test");}// fallback方法位于同类中, 必须为public @SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")public String hello(long s) {return String.format("Hello at %d", s);}// Fallback 函数,必须为public, 函数签名与原函数一致或加一个 Throwable 类型的参数.public String helloFallback(long s) {return String.format("Halooooo %d", s);}// Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.public String exceptionHandler(long s, BlockException ex) {// Do some log here.ex.printStackTrace();return "Oops, error occurred at " + s;}
}
value

资源名称,必需项(不能为空)

blockHandler / blockHandlerClass:

blockHandler 指定的函数, 将处理当前资源的 BlockException;

blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException

blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意这时, 对应的函数必需为 static 函数,否则无法解析。

blockHandler 和 fallback 本质上, 都是一种降级逻辑, 早期 fallback 函数只针对降级异常(DegradeException)进行处理, 而这个异常只在发生熔断的时候抛出; 相当于 fallback 专门针对熔断提供降级服务;

后来, fallback 支持所有类型的异常, 这时, 它和 BlockHandler 的区别在于, BlockHanlder 只对限流, 熔断提供降级服务, 而 fallback 还可以对业务异常提供降级服务

fallback / fallbackClass:

fallback 函数名称,可选项,用于提供降级处理逻辑。

在被熔断, 或者被限流, 或者出现业务异常的时候, 都会交由 fallback 提供降级服务;

fallback 函数可以针对所有类型的异常, 包括BlockException进行处理。

fallback 函数签名和位置要求:

  • 返回值类型必须与原函数返回值类型一致;

  • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。

  • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

  • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

注:1.6.0 之前的版本 fallback 函数只针对降级异常(DegradeException)进行处理;

如果只配置了 fallback, 那么限流, 熔断, 抛出业务异常时, 均进入 fallback 进行处理;

如果 blockHandler 和 fallback同时配置, 发生熔断和限流的时候, 都会由 fallback 处理;

如果两个都没配置, 发生限流和熔断时, 由 Sentinel 提供的默认BlockHandler 处理; 显示Blocked by Sentinel (flow limiting), 熔断的时候也显示 flow limiting;

与OpenFeign整合

Sentinel 适配了 Feign 组件。如果想使用,需要引入 spring-cloud-starter-alibaba-sentinelspring-cloud-starter-openfeign的依赖;

并且在使用 FeignClient 的服务的配置文件中设置 feign.sentinel.enabled = true

与Feign整合后, 可以指定降级类或者降级类工厂, BlockException 和 其它业务异常, 都会在降级类中处理;

方式一:

编写 OpenFeignClient 接口, 提供一个实现类, 实现类中重写方法, 该方法实现降级后的策略, 向容器注册该实现类;

在 @FeignClient 注解中, 指定 降级实现类;

@FeignClient(name = "order-service", fallback = OrderServiceFallback.class)
public interface OrderFeignClient {@GetMapping("order/getOrder")String getOrder(@RequestParam("order_id") Integer id);
}@Configuration
class FeignConfiguration {@Beanpublic OrderServiceFallback orderServiceFallback() {return new OrderServiceFallback();}
}class OrderServiceFallback implements OrderFeignClient {@Overridepublic String getOrder(@RequestParam("order_id") Integer id) {return "order-service fallback";}
}

需要注意的是:

FeignClient 对应的接口的资源名为:method:protocol://requesturl,例如GET:http://account-service/account/test

方式二

@FeignClient(value = "stock-service", fallbackFactory = StockFallbackFactory.class)
public interface StockClient {@GetMapping("/stock/test")public Stock test(){//......}
}public class StockFallbackFactory implements FallbackFactory<StockClient> {@Overridepublic StockClient create(Throwable throwable) {return new StockClient() {@Overridepublic Stock test() {// 可以获取异常信息, 可以处理异常; 降级时抛出的异常类型是DegradeExceptionthrowable.printStackTrace();return new Stock();}}};
}@Configuration
public FallbackConfig{@Beanpublic StockFallbackFactory stockClientFallbackFactory(){return new StockFallbackFactory();}
}

6 Gateway规则

本质是做成了 Gateway 应用的热点规则;

配置Gateway

Sentinel 从 1.6.0 版本开始,提供了 Spring Cloud Gateway 的适配模块,可提供两种资源维度的限流:

  • route 维度:在 Spring 配置路由条目时,资源名为 routeId
  • 自定义 API 维度,用户可以用 Sentinel 提供的 API 来定义一些 API 分组

网关应用引入依赖

<!--加入nacos的依赖-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>2.1.0.RELEASE</version>
</dependency><!--添加Sentinel的依赖-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2.2.0.RELEASE</version>
</dependency>
<!-- sentinel整合gateway-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!-- sentinel-nacos持久化 -->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

编写bootstrap.yaml

server:port: 7770spring:application:name: gateway-servercloud:nacos:config:server-addr: localhost:8848file-extension: yaml

其余配置

spring:main:allow-bean-definition-overriding: truecloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:routes:- id: duolai-orderuri: lb://duolai-orderpredicates:- Path=/shopping/order/**,/shopping/cancelOrder- id: duolai-useruri: lb://duolai-userpredicates:- Path=/user/**, /shopping/addresses# sentinel配置sentinel:transport:dashboard: 127.0.0.1:8080port: 9719clientIp: 127.0.0.1datasource:# 从nacos获取路由条目对应的流控规则gateway-flow-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-flow-rulesgroupId: SENTINEL_GATEWAY_GROUPdata-type: jsonrule-type: gw-flow#  从nacos获取api分组流控规则gateway-api-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-api-groupsgroupId: SENTINEL_GATEWAY_GROUPdata-type: jsonrule-type: gw-api-group

然后就是在nacos对应dataId的配置文件中,添加流控规则即可,具体流控规则,可以在dashboard中添加并获取

获取网关流控规则

GET http://ip:端口/gateway/getRules

获取api分组

GET http://ip:端口/gateway/getApiDefinitions

Sentinel配置

路由ID模式

API分组模式, 对匹配到同一个API分组的请求, 进行流量控制;

7 自定义BlockExceptionHandler

自定义BlockExceptinHandler, 只对SpringMVC默认的路径资源有效; 对 @SentinelResource 注解定义的资源无效;

抛出的 ExceptionHandler 类型异常将由自定义的BlockExceptionHandler处理;

@Component
public class MyBlockHandler implements BlockExceptionHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {httpServletResponse.setContentType("application/json;charset=utf-8");httpServletResponse.getWriter().println(e.toString());}
}

8 规则持久化

Sentinel还做了和Nacos的适配,我们只需要把我们的规则配置存储在Nacos中,就可以实现Sentinel规则的持久化保存;

之后 Sentinel 会自动从 Nacos 读取规则配置,并且当 Nacos 中配置内容发生变更的时候,Sentinel 也会实时感知到规则的变化,从而让规则生效。

但是 Sentinel 中修改添加新的规则, 不会自动推送到 Nacos, 如果想实现, 需要修改 Sentinel dashboard 的源码;

为了实现Sentinel和Nacos的整合,我们首先需要在项目中导入依赖

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

并且在配置文件中添加如下依赖

spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080port: 8719datasource:# ds1 是第一个数据源的名字,我们可以定义多个数据源ds1:nacos:# nacos地址server-addr: localhost:8848# 配置的 dataIddataId: sentinel-rules# 配置的 groupgroupId: SENTINEL_GROUP# 配置的 namespacenamespace: 41a9d584-4dbd-480b-aadd-d53c1700ecb4# 配置的数据类型data-type: json# 规则类型rule-type: flow  #flow、degrade、param-flow、gw-flow        

然后,我们在nacos中去配置好,对应的规则即可。

那么如何通过json字符串去定义规则呢?我们可以在 Dashboard 中配置规则, 然后通过给定的API直接获取规则的 JSON 格式;

GET http://ip:port/getRules?type=xxx
  • ip是你进行限流的那个服务所在的ip地址
  • port是你的服务与dashboard通信的端口号
  • type指查询的规则类型,这里可以取flow,degrade等,分别代表流控规则和降级规则。

其实请求地址 Sentinel 已经自动生成

在这里插入图片描述

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

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

相关文章

MySQL —— 聚合查询,分组查询 与 联合查询

聚合函数 常见的统计总数、计算平局值等操作&#xff0c;可以使用聚合函数来实现&#xff0c;常见的聚合函数有&#xff1a; 函数说明count()统计数据总数sum()求和avg()求平均值max()求最大值min()求最小值 注意凡是涉及运算的&#xff0c;数据库会自动掉 NULL 值 注意NULL …

本地安Stable Diffusion全记录

这里写自定义目录标题 资料 资料 AI绘图软件Stable Diffusion 之本地安装 手把手教你在本机安装Stable Diffusion秋叶整合包 让 stable diffusion 局域网访问&#xff1a;详细解析配置步骤【Stable Diffusion 实战教程】 局域网多设备访问stable diffusion Stable Diffusion 老…

Lua语言基础学习:安装Lua和Lua库管理工具

Lua语言简介 Lua是一种轻量、高效、可嵌入的脚本语言&#xff0c;由巴西里约热内卢天主教大学的研究小组于1993年开发&#xff0c;Lua的解释器非常小巧&#xff0c;编译后的体积很小&#xff08;如完整解释器不过200KB&#xff09;&#xff0c;这使得它非常适合嵌入到其他应用程…

谷粒商城实战笔记-126-全文检索-ElasticSearch-整合-测试保存

文章目录 一&#xff0c;谷粒商城实战笔记-126-全文检索-ElasticSearch-整合-测试保存1&#xff0c;在Elasticsearch的配置类中增加通用设置2&#xff0c;索引数据3&#xff0c;验证 一&#xff0c;谷粒商城实战笔记-126-全文检索-ElasticSearch-整合-测试保存 1&#xff0c;在…

汇编语言基础及常见汇编指令

一、实验原理 x64dbg 是一款开源且免费的 Ring 3 级动态调试器&#xff0c;采用 QT 编写&#xff0c;支持 32 / 64 位程序。其反汇编引擎 BeaEngine 和 Capstone 功能极其强大&#xff0c;也有丰富的插件和脚本功能&#xff0c;且并保持更新&#xff0c;目前已经基本替代了 Ol…

数字医学影像系统PACS源码,三甲以下医院都能满足,C#语言开发,C/S架构系统成熟稳定,支持二次开发项目使用。

数字医学影像系统&#xff08;RIS/PACS&#xff09;源码&#xff0c;三甲以下的医院都能满足。开发技术&#xff1a;C/S架构&#xff0c;C#开发语言&#xff0c;数据库服务器采用Oracle数据库。 PACS系统模块组成 &#xff1a; 工作站&#xff1a; 分诊工作站、超声工作站、放…

学习鸿蒙-应用市场申请签名

1.需要的文件概念 .cer / .p7b / .p12 / .csr HarmonyOS应用/服务通过数字证书&#xff08;.cer文件&#xff09;和Profile文件&#xff08;.p7b文件&#xff09;来保证应用/服务的完整性。在申请数字证书和Profile文件前&#xff0c;首先需要通过DevEco Studio来生成密钥&am…

为具有公网IPV6地址的服务器安装nextcloudAIO并使用NginxProxyManager配置反向代理

软件和硬件环境 ubuntu server 24.04&#xff0c;并已配置好ipv6公网地址&#xff0c;已安装好docker和docker-compose。一块单独的硬盘&#xff0c;用于单独存储nextcloud数据。&#xff08;非必需&#xff09;有一个能够正常解析的域名&#xff0c;并已配置好AAAA记录解析。…

【Linux学习】动静态库从原理到制作

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f351;动静态库&#x1f41f;动静态库的制作与使用&#x1f680;生成静态库&#x1f512;生成动态库 &#x1f98c;动态库的查…

Maven下载、配置以及IDEA配置Maven新建Maven项目(超详细版)

Maven下载配置&#xff1a; 一、下载apache-maven-3.5.2并解压 二、创建一个本地仓库 三、在解压文件中的conf文件夹中的settings.xml文件中配置本地仓库 四、环境变量配置 1.此电脑(右击)------->属性------->高级系统设置------->环境变量 2.新建MAVEN_HOME&…

IP实现https访问的教程

IP地址实现HTTPS地址访问&#xff0c;首先要获得浏览器可信的SSL证书&#xff0c;并且该SSL证书是操作系统默认根证书信任证书。那有的人问&#xff1a;“内网的IP地址可以吗&#xff1f;答案是肯定不可以的”内网的IP地址只能用自建发的SSL证书实现HTTPS&#xff0c;不会被浏览…

数据结构——栈(Stack)

目录 前言 一、栈的概念 1、栈的基本定义 2、栈的特性 二、栈的基本操作 1.相关操作概念 2.实现方式 &#xff08;1&#xff09;顺序栈 &#xff08;2&#xff09;链式栈 三、栈的应用 总结 前言 栈&#xff08;Stack&#xff09;是一种常见且重要的数据结构&#xff0c;它遵循…

“tcp控制协议”的理解

情景解释&#xff1a; 1.过程&#xff1a; 在用户进行网络间通信时&#xff0c;不管是客户端还是服务端&#xff0c;都会有两个缓冲区——发送缓冲区和接受缓冲区。 通过4个缓冲区进行数据交流。 用户通过write()将数据发送到他的发送缓冲区中&#xff0c;再传输到服务端的…

C# Winform 多窗体切换方式一

一、简介 在 Winform 开发中&#xff0c;多窗体的切换是一个常见的需求&#xff0c;比如登录成功后&#xff0c;切换至主界面&#xff0c;在网上查阅相关的资料&#xff0c;你会发现很多都是用 form2.Show(); this.Hide(); 这种方式&#xff0c;这种方式也存在一些问题&#…

【学习笔记】Day 9

一、进度概述 1、inversionnet_train 试运行——成功 二、详情 1、inversionnet_train 试运行 在经历了昨天的事故后&#xff0c;今天最终成功运行了 inversionnet_train&#xff0c;运行结果如下&#xff1a; 经观察&#xff0c;最开始 loss 值大概为 0.5 左右 随着训练量的增…

ECR绕过技巧

一、预编译与sql注入 预编译SQL有两个优势&#xff1a; 1、性能更高&#xff1a;预编译SQL&#xff0c;编译一次之后会将编译后的SQL语句缓存起来&#xff0c;后面再次执行这条语句时&#xff0c;不会再次编译。&#xff08;只是输入的参数不同&#xff09;。 2、更安全(防止S…

漏洞复现-Apache Struts2 文件上传漏洞(CVE-2023-50164)

1.漏洞描述 Apache Struts2 是一个开源的 Java Web 应用程序开发框架&#xff0c;旨在帮助开发人员构建灵活、可维护和可扩展的企业级Web应用程序。 由于文件上传逻辑存在缺陷&#xff0c;攻击者可以操纵文件上传参数来实现路径穿越&#xff0c;在某些情况下&#xff0c;通过…

HTTP的场景实践

HTTP的场景实践&#xff1a;任选一个浏览器&#xff0c;对于其涉及的请求中的缓存策略展开具体分析 1. 强缓存&#xff1a; Cache-Control用于指定缓存的最长有效时间。 Expires用于指定资源过期的日期。 2. 协商缓存&#xff1a; ETag用于标识资源的唯一标识符&#xff0c;…

ISP代理与双ISP代理的区别

在网络营销、数据采集及隐私保护等领域&#xff0c;代理服务器扮演着至关重要的角色。而在代理服务器的选择中&#xff0c;ISP代理与双ISP代理是两种常见的选择。本文将对这两种代理服务进行详细分析&#xff0c;探讨它们之间的区别以及各自的优势和适用场景。 一、ISP代理概述…

代码规范 —— QMQ 开发规范

优质博文&#xff1a;IT-BLOG-CN 一、代码规范 【1】消费者必须以Consumer结尾&#xff0c;生产者必须以Producer结尾。 【2】选择合适的消费模式&#xff1a;根据业务判断消费模式是集群模式还是广播模式&#xff0c;具体为&#xff1a;MessageConsumerProvider.addListene…