Sentinel原理与SpringBoot整合实战

news2025/5/24 2:18:42

前言

随着微服务架构的广泛应用,服务和服务之间的稳定性变得越来越重要。在高并发场景下,如何保障服务的稳定性和可用性成为了一个关键问题。阿里巴巴开源的Sentinel作为一个面向分布式服务架构的流量控制组件,提供了从流量控制、熔断降级、系统负载保护等多个维度来保障服务稳定性的解决方案。

本文将详细介绍Sentinel的核心原理和基本功能点,并提供一个完整的SpringBoot整合Sentinel的案例,帮助读者快速掌握Sentinel的使用方法。

一、Sentinel简介

1.1 什么是Sentinel

Sentinel是阿里巴巴开源的,面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保障服务的稳定性。

Sentinel的主要特性包括:

  • 丰富的应用场景:Sentinel承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel同时提供实时的监控功能。用户可以在控制台中看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel提供开箱即用的与其它开源框架/库的整合模块,例如与Spring Cloud、Apache Dubbo、gRPC、Quarkus的整合。用户只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。同时Sentinel提供Java/Go/C++等多语言的原生实现。
  • 完善的SPI扩展机制:Sentinel提供简单易用、完善的SPI扩展接口。用户可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

1.2 Sentinel与其他熔断降级工具的对比

相比于其他熔断降级工具(如Hystrix),Sentinel具有以下优势:

  1. 丰富的流量控制:Sentinel提供了更丰富的流量控制策略,包括基于调用关系的流量控制、热点参数限流等。
  2. 实时监控:Sentinel提供了实时的监控功能,可以实时查看接入应用的运行情况。
  3. 轻量级设计:Sentinel采用轻量级设计,不依赖任何框架/库,能够运行于所有Java运行时环境。
  4. 多语言支持:Sentinel提供了Java/Go/C++等多语言的原生实现。
  5. 完善的SPI扩展机制:Sentinel提供了完善的SPI扩展接口,用户可以通过实现扩展接口来快速地定制逻辑。

二、Sentinel核心原理

2.1 基本工作原理

Sentinel的核心工作原理可以概括为:

  1. 资源定义:资源是Sentinel的核心概念,它可以是Java应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。只要通过Sentinel API定义的代码,就是资源。

  2. 规则配置:Sentinel通过规则来指定资源的访问控制策略。规则包括流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则和热点参数规则等。

  3. 统计与判断:Sentinel会实时统计资源的调用数据,并根据预设的规则进行判断,若超出阈值,则采取相应的流量控制措施。

2.2 Sentinel的执行流程

Sentinel的执行流程主要分为以下几个步骤:

  1. 资源埋点:通过SphU.entry(resourceName)entry.exit()方法对资源进行埋点。
  2. 规则判断:当资源被访问时,Sentinel会根据预设的规则进行判断。
  3. 流量控制:如果触发了规则条件,Sentinel会执行相应的流量控制措施,例如直接拒绝、排队等待或预热模式。
  4. 熔断降级:对于响应时间过长或异常比例过高的服务,Sentinel会进行熔断降级处理。
  5. 系统自适应保护:当系统负载过高时,Sentinel会自动进行系统保护。

2.3 Sentinel的核心组件

Sentinel的核心组件主要包括:

  1. Sentinel核心库:不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo/Spring Cloud等框架也有较好的支持。
  2. Sentinel控制台:基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。

三、Sentinel基本功能点

3.1 流量控制

流量控制(flow control)是Sentinel最核心的功能之一,其原理是监控应用流量的QPS或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

流量控制主要有以下几个维度:

  1. 基于QPS/并发数的流量控制

    • 并发数控制:用于保护业务线程池不被慢调用耗尽。
    • QPS控制:当QPS超过某个阈值的时候,采取措施进行流量控制。
  2. 流量控制效果

    • 直接拒绝:默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝。
    • Warm Up:预热/冷启动方式,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限。
    • 匀速排队:严格控制请求通过的间隔时间,让请求以均匀的速度通过,对应的是漏桶算法。
  3. 基于调用关系的流量控制

    • 根据调用方来源进行流量控制。
    • 支持针对不同的调用方设置不同的流控策略。

3.2 熔断降级

熔断降级(circuit breaking)是Sentinel的另一个重要功能,它用于当调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。

熔断降级主要有以下几个维度:

  1. 慢调用比例:当资源的响应时间超过阈值(慢调用)的比例超过设定的比例阈值时,触发熔断。
  2. 异常比例/异常数:当资源的异常比例或异常数超过阈值时,触发熔断。
  3. 恢复策略:熔断触发后,经过一段时间(即熔断超时时间),熔断器会进入探测恢复状态,若接下来的一个请求处理成功,则结束熔断,否则继续熔断。

3.3 热点参数限流

热点参数限流是一种更细粒度的流量控制,它允许用户针对某个热点参数进行限流,例如针对某个用户ID限流。

热点参数限流的特点:

  1. 可以针对某个参数的特定值单独设置限流阈值。
  2. 支持多种参数类型,包括基本类型和字符串类型。
  3. 可以设置参数例外项,对特定的参数值进行不同的限流处理。

3.4 系统自适应限流

系统自适应限流从整体维度对应用入口流量进行控制,结合应用的Load、CPU使用率、总体平均RT、入口QPS和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统规则包含以下几个重要的参数:

  1. Load:当系统load1超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。
  2. CPU使用率:当系统CPU使用率超过阈值即触发系统保护。
  3. 平均RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护。
  4. 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  5. 入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护。

3.5 黑白名单控制

黑白名单控制根据资源的请求来源(origin)限制资源是否通过:

  1. 白名单:来源(origin)在白名单内的请求才可通过。
  2. 黑名单:来源(origin)在黑名单内的请求不允许通过。

3.6 实时监控

Sentinel提供实时的监控功能,用户可以实时查看接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。监控数据包括:

  1. 通过的请求数(pass):一秒内到来到的请求。
  2. 被阻止的请求数(blocked):一秒内被流量控制的请求数量。
  3. 成功处理的请求数(success):一秒内成功处理完的请求。
  4. 总请求数(total):一秒内到来的请求以及被阻止的请求总和。
  5. 平均响应时间(RT):一秒内该资源的平均响应时间。
  6. 异常数(exception):一秒内业务本身异常的总和。

3.7 动态规则配置

Sentinel支持多种动态规则源,包括:

  1. 文件配置:规则存储在文件中,定期轮询文件获取规则。
  2. Nacos配置中心:规则存储在Nacos配置中心,通过监听配置变更事件即时获取规则。
  3. ZooKeeper:规则存储在ZooKeeper中,通过监听节点变更事件即时获取规则。
  4. Apollo配置中心:规则存储在Apollo配置中心,通过监听配置变更事件即时获取规则。
  5. Redis:规则存储在Redis中,通过定期轮询获取规则。

四、SpringBoot整合Sentinel完整案例

下面我们将通过一个完整的案例,演示如何在SpringBoot项目中整合Sentinel。

4.1 项目结构

springcloud-sentinel
├── src
│   └── main
│       ├── java
│       │   └── com.example
│       │       ├── config
│       │       │   └── SentinelConfig.java
│       │       ├── controller
│       │       │   └── TestSentinelController.java
│       │       ├── service
│       │       │   └── HelloService.java
│       │       └── SentinelApplication.java
│       └── resources
│           └── application.properties
└── pom.xml

4.2 Maven依赖配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>springboot-sentinel-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <spring-boot.version>2.6.3</spring-boot.version>
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot 依赖管理 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <!-- Spring Cloud Alibaba 依赖管理 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- Sentinel 依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

4.3 应用配置文件

# application.properties
spring.application.name=sentinel-demo
server.port=8080

# Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard=localhost:8080
# 取消Sentinel控制台懒加载
spring.cloud.sentinel.eager=true
# 设置应用与Sentinel控制台的心跳间隔时间
spring.cloud.sentinel.transport.heartbeat-interval-ms=3000

4.4 Sentinel配置类

package com.example.config;

import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Sentinel配置类
 * 注册SentinelResourceAspect,用于支持@SentinelResource注解
 */
@Configuration
public class SentinelConfig {
    
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

4.5 服务类

package com.example.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;

/**
 * 业务服务类
 * 使用@SentinelResource注解定义资源点
 */
@Service
public class HelloService {
    
    /**
     * 定义一个资源点,指定blockHandler处理限流异常
     * @param name 参数
     * @return 返回结果
     */
    @SentinelResource(value = "sayHello", blockHandler = "sayHelloExceptionHandler")
    public String sayHello(String name) {
        return "Hello, " + name;
    }
    
    /**
     * 定义一个资源点,同时指定blockHandler和fallback
     * blockHandler: 处理限流异常
     * fallback: 处理业务异常
     * @param name 参数
     * @return 返回结果
     */
    @SentinelResource(value = "circuitBreaker", 
                     fallback = "circuitBreakerFallback", 
                     blockHandler = "sayHelloExceptionHandler")
    public String circuitBreaker(String name) {
        // 模拟业务逻辑,当name为"test"时抛出异常
        if ("test".equals(name)) {
            return "Hello, " + name;
        }
        throw new RuntimeException("发生异常");
    }
    
    /**
     * 熔断降级处理方法,处理业务异常
     * @param name 参数
     * @return 降级返回结果
     */
    public String circuitBreakerFallback(String name) {
        return "服务异常,熔断降级,请稍后重试!";
    }
    
    /**
     * 限流降级处理方法,处理限流异常
     * @param name 参数
     * @param ex 限流异常
     * @return 限流返回结果
     */
    public String sayHelloExceptionHandler(String name, BlockException ex) {
        return "访问过快,限流降级,请稍后重试!";
    }
}

4.6 控制器类

package com.example.controller;

import com.example.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 测试Sentinel的控制器
 */
@RestController
@RequestMapping("/sentinel")
public class TestSentinelController {
    
    @Autowired
    private HelloService helloService;
    
    /**
     * 测试限流功能
     * @param name 参数
     * @return 返回结果
     */
    @GetMapping("/hello")
    public String hello(@RequestParam("name") String name) {
        return helloService.sayHello(name);
    }
    
    /**
     * 测试熔断功能
     * @param name 参数
     * @return 返回结果
     */
    @GetMapping("/circuit")
    public String circuitBreaker(@RequestParam("name") String name) {
        return helloService.circuitBreaker(name);
    }
}

4.7 应用启动类

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Sentinel示例应用启动类
 */
@SpringBootApplication
public class SentinelApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(SentinelApplication.class, args);
    }
}

4.8 运行与测试

4.8.1 下载并启动Sentinel控制台
  1. 下载Sentinel控制台jar包:

    wget https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar
    
  2. 启动Sentinel控制台:

    java -Dserver.port=8080 -jar sentinel-dashboard-1.8.6.jar
    
  3. 访问Sentinel控制台:

    http://localhost:8080
    

    默认用户名和密码都是:sentinel

4.8.2 启动SpringBoot应用
  1. 启动应用:

    mvn spring-boot:run
    
  2. 测试限流功能:

    http://localhost:8080/sentinel/hello?name=world
    
  3. 测试熔断功能:

    http://localhost:8080/sentinel/circuit?name=test
    
    http://localhost:8080/sentinel/circuit?name=other
    
4.8.3 在Sentinel控制台配置规则
  1. 登录Sentinel控制台后,可以看到应用已经注册到控制台

  2. 配置流控规则:

    • 点击"簇点链路",找到"sayHello"资源
    • 点击"流控"按钮,设置QPS阈值为5
    • 保存规则
  3. 配置熔断规则:

    • 点击"簇点链路",找到"circuitBreaker"资源
    • 点击"降级"按钮,设置异常比例阈值为0.5,时间窗口为10s
    • 保存规则
  4. 测试规则效果:

    • 快速刷新限流接口,当QPS超过5时,会触发限流
    • 多次访问熔断接口并传入非"test"参数,当异常比例超过50%时,会触发熔断

4.9 高级配置

4.9.1 持久化规则配置

Sentinel支持多种数据源来持久化规则配置,以下是使用文件配置的示例:

# 配置Sentinel规则持久化到文件
spring.cloud.sentinel.datasource.ds1.file.file=classpath:sentinel/flow-rule.json
spring.cloud.sentinel.datasource.ds1.file.data-type=json
spring.cloud.sentinel.datasource.ds1.file.rule-type=flow

spring.cloud.sentinel.datasource.ds2.file.file=classpath:sentinel/degrade-rule.json
spring.cloud.sentinel.datasource.ds2.file.data-type=json
spring.cloud.sentinel.datasource.ds2.file.rule-type=degrade
4.9.2 Nacos配置中心持久化
# 配置Sentinel规则持久化到Nacos
spring.cloud.sentinel.datasource.ds1.nacos.server-addr=localhost:8848
spring.cloud.sentinel.datasource.ds1.nacos.data-id=sentinel-flow-rules
spring.cloud.sentinel.datasource.ds1.nacos.group-id=SENTINEL_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.data-type=json
spring.cloud.sentinel.datasource.ds1.nacos.rule-type=flow

spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848
spring.cloud.sentinel.datasource.ds2.nacos.data-id=sentinel-degrade-rules
spring.cloud.sentinel.datasource.ds2.nacos.group-id=SENTINEL_GROUP
spring.cloud.sentinel.datasource.ds2.nacos.data-type=json
spring.cloud.sentinel.datasource.ds2.nacos.rule-type=degrade
4.9.3 自定义全局异常处理
package com.example.config;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
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 com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义Sentinel全局异常处理
 */
@Configuration
public class SentinelBlockExceptionHandler implements BlockExceptionHandler {
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        // 设置响应类型
        response.setStatus(429);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        
        Map<String, Object> result = new HashMap<>();
        result.put("code", 429);
        result.put("success", false);
        
        if (e instanceof FlowException) {
            result.put("message", "请求被限流了");
        } else if (e instanceof DegradeException) {
            result.put("message", "请求被降级了");
        } else if (e instanceof ParamFlowException) {
            result.put("message", "热点参数限流");
        } else if (e instanceof SystemBlockException) {
            result.put("message", "系统规则限制");
        } else if (e instanceof AuthorityException) {
            result.put("message", "授权规则不通过");
        } else {
            result.put("message", "未知限流降级");
        }
        
        // 返回JSON数据
        PrintWriter out = response.getWriter();
        out.write(new ObjectMapper().writeValueAsString(result));
        out.flush();
        out.close();
    }
}

五、总结

本文详细介绍了Sentinel的核心原理和基本功能点,包括流量控制、熔断降级、热点参数限流、系统自适应限流等,并提供了一个完整的SpringBoot整合Sentinel的案例。

Sentinel作为一个面向分布式服务架构的流量控制组件,在微服务架构中扮演着重要的角色。它不仅提供了丰富的流量控制策略,还提供了实时的监控功能,可以帮助开发者更好地了解服务的运行情况,及时发现和解决问题。

在实际应用中,我们可以根据业务需求,灵活配置Sentinel的各种规则,以达到最佳的保护效果。同时,Sentinel还提供了多种规则持久化的方式,可以方便地将规则存储到配置中心,实现规则的动态更新。

参考资料

  1. Sentinel 官方文档
  2. Sentinel 工作原理
  3. Sentinel 流量控制
  4. Spring Cloud Alibaba Sentinel

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能守护校园“舌尖安全“:AI视频分析赋能名厨亮灶新时代

引言&#xff1a; 在校园食品安全备受关注的今天&#xff0c;一套融合视频监控管理平台与AI视频分析盒子的智能解决方案正在全国多地学校食堂悄然落地&#xff0c;为传统的"名厨亮灶"工程注入科技新动能。这套系统不仅实现了后厨操作的"透明化"&#xff0…

初步尝试AI应用开发平台——Dify的本地部署和应用开发

随着大语言模型LLM和相关应用的流行&#xff0c;在本地部署并构建知识库&#xff0c;结合企业的行业经验或个人的知识积累进行定制化开发&#xff0c;是LLM的一个重点发展方向&#xff0c;在此方向上也涌现出了众多软件框架和工具集&#xff0c;Dify就是其中广受关注的一款&…

卷积神经网络中的局部卷积:原理、对比与应用解析

【内容摘要】 本文聚焦卷积神经网络中的局部卷积&#xff0c;重点解析全连接、局部连接、全卷积与局部卷积四种连接方式的差异&#xff0c;结合人脸识别任务案例&#xff0c;阐述局部卷积的应用场景及优势&#xff0c;为理解卷积网络连接机制提供技术参考。 关键词&#xff1a…

重拾童年,用 CodeBuddy 做自己的快乐创作者

某个炎炎的夏日午后&#xff0c;阳光透过稀疏的树叶洒落在地上&#xff0c;一道道光影斑驳陆离。那时候的我们&#xff0c;还只是三五个小朋友&#xff0c;蹲坐在村头的一棵老槐树下&#xff0c;手里握着并不属于自己的游戏掌机&#xff0c;轮流按动着手柄的按键&#xff0c;在…

HarmonyOS实战:自定义时间选择器

前言 最近在日常鸿蒙开发过程中&#xff0c;经常会使用一些时间选择器&#xff0c;鸿蒙官方提供的时间选择器满足不了需求&#xff0c;所以自己动手自定义一些经常会使用到的时间选择器&#xff0c;希望能帮到你&#xff0c;建议点赞收藏&#xff01; 实现效果 需求分析 默认…

6:OpenCV—图像滤波

过滤图像和视频 图像滤波是一种邻域运算&#xff0c;其中输出图像中任何给定像素的值是通过对相应输入像素附近的像素值应用某种算法来确定的。该技术通常用于平滑、锐化和检测图像和视频的边缘。 让我们了解在讨论图像过滤技术、内核和卷积时使用的一些术语的含义。 内核 内…

pytorch语法学习

启动 python main.py --config llve.yml --path_y test -i output

5:OpenCV—图像亮度、对比度变换

1.更改图像和视频的亮度 更改亮度 更改图像的亮度是常用的点操作。在此操作中&#xff0c;图像中每个像素的值应增加/减少一个常数。要更改视频的亮度&#xff0c;应对视频中的每一帧执行相同的操作。 如果要增加图像的亮度&#xff0c;则必须为图像中的每个像素添加一些正常…

Oracle 的V$ACTIVE_SESSION_HISTORY 视图

Oracle 的V$ACTIVE_SESSION_HISTORY 视图 V$ACTIVE_SESSION_HISTORY显示数据库中的 Sampled Session 活动。 它包含每秒拍摄一次的活动数据库会话的快照。如果数据库会话位于 CPU 上或正在等待不属于等待类的事件&#xff0c;则认为该会话处于活动状态。请参阅 view 以了解有…

【Python 算法零基础 4.排序 ② 冒泡排序】

目录 一、引言 二、算法思想 三、时间复杂度和空间复杂度 1.时间复杂度 2.空间复杂度 四、冒泡排序的优缺点 1.算法的优点 2.算法的缺点 五、实战练习 88. 合并两个有序数组 算法与思路 ① 合并数组 ② 冒泡排序 2148. 元素计数 算法与思路 ① 排序 ② 初始化计数器 ③ 遍历数组…

Python:操作Excel设置行高和列宽

Python 操作 Excel:轻松设置行高与列宽 📊✨ 在处理 Excel 表格时,除了正确展示数据本身,合理设置行高与列宽也是提升可读性和专业度的关键因素。本文将带你了解如何使用 Python 的 openpyxl 库,优雅地控制 Excel 表格的排版布局,实现行高、列宽的灵活设置与自动适配! …

docker-volume-backup 备份 ragflow volumes

自定义项目名称 这里我自定义了 ragflow 项目的名称&#xff0c;修改 .env&#xff0c;添加环境配置 # 自定义项目名称 COMPOSE_PROJECT_NAMEragflow创建备份脚本配置文件 在 ragflow/docker 目录下创建文件 docker-compose-backup.yml version: 3services:backup:image: o…

Axure设计数字乡村可视化大屏:从布局到交互的实战经验分享

乡村治理正从传统模式向“数据驱动”转型。数字乡村可视化大屏作为数据展示的核心载体&#xff0c;不仅能直观呈现乡村发展全貌&#xff0c;还能为决策提供科学依据。本文以Axure为工具&#xff0c;结合实际案例&#xff0c;分享如何从零设计一个功能完备、交互流畅的数字乡村大…

算法第26天 | 贪心算法、455.分发饼干、376. 摆动序列、 53. 最大子序和

弹性算法理论基础 想清楚 局部最优 是什么&#xff0c;如果可以推导出全局最优&#xff0c;那就是正确的贪心算法 455. 分发饼干 题目 思路与解法 class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:res 0i 0j 0g.sort()s.sort()whi…

PDF处理控件Aspose.PDF教程:以编程方式将 PDF 导出为 JPG

在本节中&#xff0c;我们将探讨如何使用 Aspose.PDF 库将 PDF 文档转换为 JPG 图像。Aspose.PDF 是一个功能强大且用途广泛的库&#xff0c;专为需要以编程方式处理 PDF 文件的开发人员而设计。它提供了丰富的功能&#xff0c;可用于跨多个平台创建、编辑和转换 PDF 文档。其主…

AI大模型应用之评测篇

在看到公司对于AI 工程师 的岗位要求 &#xff1a;“能够熟练使用各种自动化评测工具与方法&#xff0c;对AI 模型的输出进行有效评估” 时&#xff0c;其实比较疑惑&#xff0c;这个是对大模型能力例如像Deepseek ,GPT-4 ,千问&#xff0c;LLAMA这些模型的能力评测&#xff0c…

力扣小题, 力扣113.路径总和II力扣.111二叉树的最小深度 力扣.221最大正方形力扣5.最长回文子串更加优秀的算法:中心扩展算法

目录 力扣113.路径总和II 力扣.111二叉树的最小深度 力扣.221最大正方形 力扣5.最长回文子串 更加优秀的算法:中心扩展算法 力扣113.路径总和II 这道题&#xff0c;让我明白回溯了到底啥意思 之前我找的时候&#xff0c;我一直在想&#xff0c;如果可以&#xff0c;请你对比…

el-form elform 对齐方式调整

如下页面表单&#xff0c;展示后就很丑。 页面表单&#xff0c;有时候我们想着最左侧的应该合理整齐的左对齐&#xff0c;右侧的表单都是右对齐&#xff0c;这样页面看起来会整洁很多。 <el-form class"w-100 a_form" style"padding: 0 15px 0px 15px"…

JESD204 ip核使用与例程分析(二)

JESD204 ip核使用与例程分析(二) JESD204时钟方案专用差分时钟对例程分析jesd204_0_transport_layer_demapperjesd204_0_sig_chkjesd204_0_clockingjesd204_0 ip核port寄存器AXI-LITE寄存器配置jesd204_phy ip核JESD204时钟方案 图3-1所示为最通用、灵活的时钟解决方案。在图…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Blurry Loading (毛玻璃加载)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— Blurry Loading 组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ ✨ 组件目标 实现一个加载进度条&#xff0c;随着加载进度的…