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

【PmHub后端篇】PmHub集成 Sentinel+OpenFeign实现网关流量控制与服务降级

在微服务架构中,保障服务的稳定性和高可用性至关重要。本文将详细介绍在 PmHub 中如何利用 Sentinel + Gateway 进行网关限流,以及集成 Sentinel + OpenFeign 实现自定义的 fallback 服务降级。

1 熔断降级的必要性

在微服务架构中,服务间的调用错综复杂。一个服务可能会调用远程服务、数据库或第三方 API,例如支付时调用银联 API、查询商品价格时访问数据库等。然而,依赖的服务稳定性不可控,若其出现不稳定情况,请求响应时间过长,调用服务的方法会阻塞,耗尽业务线程资源,最终导致服务不可用。为避免这种情况,对不稳定的弱依赖服务调用进行熔断降级是保障高可用的重要措施。

2 Sentinel 的发展历史

早些年,Netflix 的 Hystrix 是熔断降级的热门组件,但在 2018 年底 Netflix 宣布不再维护它。此后,阿里巴巴开源的 Sentinel 成为了不错的替代产品。此外,Resilience4J 也是 Hystrix 官方推荐的替代产品,具有轻量、简单、文档清晰丰富的特点。Sentinel 是面向分布式的流量治理组件,以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、自适应过载保护、热点流量防护等多个维度保障微服务的稳定性。Sentinel 自 2012 年诞生,历经多次版本更新。

在这里插入图片描述

3 Sentinel 的基本概念

  • 资源
    资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。

    只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。

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

4 Sentinel 的原理

在 Sentinel 中,所有资源对应一个资源名称和一个 Entry。Entry 可通过对主流框架的适配自动创建,也可通过注解或调用 API 显式创建。每个 Entry 创建时,会同时创建一系列功能插槽(slot chain)。

这些插槽有不同的职责,例如:

  • NodeSelectorSlot 负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级;
  • ClusterBuilderSlot 则用于存储资源的统计信息以及调用者信息,例如该资源的 RT, QPS, thread count 等等,这些信息将用作为多维度限流,降级的依据;
  • StatisticSlot 则用于记录、统计不同纬度的 runtime 指标监控信息;
  • FlowSlot 则用于根据预设的限流规则以及前面 slot 统计的状态,来进行流量控制;
  • AuthoritySlot 则根据配置的黑白名单和调用来源信息,来做黑白名单控制;
  • DegradeSlot 则通过统计信息以及预设的规则,来做熔断降级;
  • SystemSlot 则通过系统的状态,例如 load1 等,来控制总的入口流量;

总体的框架如下:
在这里插入图片描述

Sentinel 将 ProcessorSlot 作为 SPI 接口进行扩展(1.7.2 版本以前 SlotChainBuilder 作为 SPI),使 Slot Chain 具备扩展能力,可加入自定义 slot 并编排顺序,为 Sentinel 添加自定义功能。
在这里插入图片描述

5 Sentinel 的下载和使用

5.1 下载Sentinel

  • 下载地址:https://github.com/alibaba/Sentinel/releases
  • 官方参考文档地址:https://sentinelguard.io/zh-cn/docs/quick-start.html

在这里插入图片描述

5.2 启动Sentinel

Sentinel 控制台的运行依赖 JDK 1.8 及以上版本,在搭建环境前需确保本地已安装符合要求的 JDK。

Sentinel 控制台本质上是一个可执行的 jar 包,使用 Java 命令即可运行。在启动前,需要确认默认端口 8080 是否被占用,可通过以下命令进行查看:

linux版:lsof -i :8080
windows版:netstat -ano | findstr "8080"

若命令执行后无任何输出,表明 8080 端口未被占用,可直接使用以下命令启动 Sentinel 控制台:

java -jar sentinel-dashboard-1.8.7.jar

若 8080 端口已被占用,则需切换至其他端口,例如 8081,启动命令如下:

java -jar sentinel-dashboard-1.8.7.jar --server.port=8081

当控制台输出类似 “Starting DashboardApplication using Java” 等相关信息时,即表明 Sentinel 控制台启动成功。
在这里插入图片描述

5.3 访问管理界面​

启动成功后,可通过浏览器访问 Sentinel 管理界面,若使用默认 8080 端口,访问地址为 http://localhost:8080;若使用 8081 端口,则访问地址为 http://localhost:8081。默认的登录账号和密码均为 “sentinel”,登录后即可进入 Sentinel 控制台管理界面。
在这里插入图片描述
在这里插入图片描述

5.4 功能验证

为验证 Sentinel 环境搭建是否成功,可编写测试用例进行验证。

5.4.1 引入依赖​

在项目的 pom.xml 文件中引入 Sentinel 的核心依赖:

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.6</version>
</dependency>
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.6</version>
</dependency>

其中,sentinel-core 为 Sentinel 的核心包,sentinel-transport-simple-http 用于实现与控制台的连通。

5.4.2 编写测试代码​

新建一个测试类,示例代码如下:

class Demo {public static void main(String[] args) {// 配置规则initFlowRules();while (true) {// 1.5.0版本开始可以直接利用try-with-resources特性try (Entry entry = SphU.entry("HelloWorld")) {// 被保护的逻辑System.out.println("hello world");} catch (BlockException ex) {// 处理被流控的逻辑System.out.println("blocked!");}}}private static void initFlowRules() {List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();rule.setResource("HelloWorld");rule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置QPS限制为20rule.setCount(20);rules.add(rule);FlowRuleManager.loadRules(rules);}
}

上述代码通过 initFlowRules 方法配置了流量控制规则,将 “HelloWorld” 资源的 QPS 限制为 20,在 main 方法中通过 SphU.entry 方法尝试进入资源保护块,若超出流量限制,则会捕获 BlockException 并执行相应的处理逻辑。

5.4.3 运行测试​

以 debug 模式运行上述测试类,在控制台可观察到输出信息。
在这里插入图片描述

当循环次数达到 21 次时,由于超出了设定的 QPS 限制,将进入 BlockException 处理逻辑,输出 “blocked!”,这表明 Sentinel 的流量控制功能已正常生效,至此,PmHub 中 Sentinel 环境搭建成功。
在这里插入图片描述

6 Sentinel 配合 Gateway 实现网关限流

Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。在 1.6.0 版本,Sentinel 提供了 Gateway 的适配模块,支持两种维度的限流:

  1. route 维度:在配置文件中配置路由条目,资源名为对应的 routeId,常用于对某个微服务进行限流,PmHub 主要使用该维度。
  2. 自定义 API 维度:利用 Sentinel 提供的 API 自定义一些 API 分组,可针对 URI 进行限流,跨多个服务。

具体实现步骤如下:

6.1 引入 Sentinel 依赖

在需要 Sentinel 的微服务中引入 Sentinel 依赖,可在 PmHub 中搜索 alibaba-sentinel 关键字查看。

<!-- SpringCloud Alibaba Sentinel 核心依赖-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency><!-- SpringCloud Alibaba Sentinel Gateway,如果不是gateway可以不用引入 -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency><!-- Sentinel Datasource Nacos 用来做持久化存储-->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

6.2 修改 yml 配置

在 pmhub-gateway 的服务配置 bootstrap.yml 中,增加 Sentinel 的配置。其中

  • eager 用于取消控制台的懒加载;
  • dashboard 为 Sentinel 控制台地址;
  • port 为 Sentinel 客户端与 Sentinel 控制台通信的端口,用于上报网关的流量数据、接收动态规则配置、进行心跳检测等。
    在这里插入图片描述

6.3 使用 Nacos 对 Sentinel 进行持久化配置

Sentinel 的配置默认放在内存中,服务重启后配置会丢失。使用 Nacos 进行持久化配置,若 Nacos 已启动,可在 Nacos 的控制台找到 sentinel-pmhub-gateway
在这里插入图片描述
在这里插入图片描述

6.4 在 Sentinel 控制台查看 Gateway 的流量规则

在这里插入图片描述
Sentinel 之所以能够对流量进行控制,是因为它会监控应用的 QPS 流量或者并发线程数等指标,如果达到指定的阈值,就会进行流量控制,避免服务被瞬时的高并发流量击垮,从而保证服务的可靠性。

QPS 即每秒查询率,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。即每秒的响应请求数,也就是最大吞吐能力。

这里以 pmhub-gateway 网关流控规则为例:
在这里插入图片描述

在这里插入图片描述
这里 pmhub-system 配置的 1000,代表每秒最多可以处理 1000 个请求。

7 Sentinel 配合 OpenFeign 实现自定义 fallback 服务降级

7.1 @SentinelResource 注解

@SentinelResource 是 Sentinel 中重要的注解,能在代码层面对资源进行保护,结合控制台的规则配置,实现高效的限流与降级策略。

例如,在 PmHub 的系统服务中,可为获取用户信息的接口加上@SentinelResource 注解,blockHandler 参数用于限流,fallback 参数用于降级处理。

代码路径:com.laigeoffer.pmhub.system.controller.SysUserController#info

/*** 根据用户名获取当前用户信息*/
@InnerAuth
@GetMapping("/info/{username}")
@SentinelResource(value = "infoSentinelResource",blockHandler = "handlerBlockHandler", fallback = "doActionFallback") // 演示SentinelResource细粒度管控服务流控和降级
public R<LoginUser> info(@PathVariable("username") String username) {SysUser sysUser = userService.selectUserByUserName(username);if (StringUtils.isNull(sysUser)) {return R.fail("用户名或密码错误");}// 角色集合Set<String> roles = permissionService.getRolePermission(sysUser);// 权限集合Set<String> permissions = permissionService.getMenuPermission(sysUser);LoginUser loginUser = new LoginUser();loginUser.setUser(sysUser);loginUser.setRoles(roles);loginUser.setPermissions(permissions);loginUser.setUserId(sysUser.getUserId());loginUser.setDeptId(sysUser.getDeptId());loginUser.setNickName(sysUser.getNickName());return R.ok(loginUser);
}

来看一下登录接口涉及到的服务交互,用户发起请求,网关服务(pmhub-gateway)接收到后进行服务转发,转发到认证服务(pmhub-auth),认证服务调用系统服务(pmhub-system)获取用户。
在这里插入图片描述

7.2 fallback 服务降级

fallback 服务降级是指当调用一个服务出现异常时,给访问者一个友好的反馈,降低服务负载,避免因异常请求引发其他服务崩溃。

7.3 通过 OpenFeign 进行过渡降级处理

对于用户的登录请求,认证服务不直接调用系统服务,PmHub 抽离出公共包 pmhub-api,将用户接口统一放入,认证服务通过 OpenFeign 调用系统服务,并在 pmhub-api 服务中进行统一的服务降级。
在这里插入图片描述

7.3.1 OpenFeign的概念

OpenFeign 是一个 声明式 HTTP 客户端,用于在 Spring Cloud 微服务架构 中简化服务之间的通信。它提供了一种声明式的方式来定义和调用 HTTP 服务,我们开发者无需手动构建 HTTP 请求,就能轻松实现服务调用。

7.3.2 具体实现步骤

  1. 使用 @FeignClient 注解:在 UserFeignService 中,在 @FeignClient 注解上添加自定义的 fallbackFactory
    代码路径:com.laigeoffer.pmhub.api.system.UserFeignService
@FeignClient(contextId = "userFeignService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = UserFeginFallbackFactory.class)
public interface UserFeignService {/*** 根据用户名获取当前用户信息*/@GetMapping("/system/user/info/{username}")R<LoginUser> info(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);/*** 根据 userId 获取用户信息*/@GetMapping("/system/user/getInfoByUserId/{userId}")R<LoginUser> getInfoByUserId(@PathVariable("userId") Long userId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);/*** 根据条件获取用户列表*/@PostMapping("/system/user/listOfInner")R<List<SysUserVO>> listOfInner(@RequestBody SysUserDTO sysUserDTO, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);/*** 注册用户信息** @param sysUser 用户信息* @param source 请求来源* @return 结果*/@PostMapping("/system/user/register")R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}
  1. 创建 UserFeginFallbackFactory:进行自定义的降级处理,在 FallbackFactory 中,不仅能捕获异常进行处理,还能通过 Throwable 获取详细的异常信息,处理复杂的限流逻辑。
    代码路径:com.laigeoffer.pmhub.api.system.factory.UserFeginFallbackFactory
@Component
public class UserFeginFallbackFactory implements FallbackFactory<UserFeignService>
{private static final Logger log = LoggerFactory.getLogger(UserFeginFallbackFactory.class);@Overridepublic UserFeignService create(Throwable throwable){log.error("用户服务调用失败:{}", throwable.getMessage());return new UserFeignService(){@Overridepublic R<LoginUser> info(String username, String source) {return R.fail("根据用户名获取用户失败:" + throwable.getMessage());}@Overridepublic R<LoginUser> getInfoByUserId(Long userId, String source) {return R.fail("根据userId获取用户失败:" + throwable.getMessage());}@Overridepublic R<List<SysUserVO>> listOfInner(SysUserDTO sysUserDTO, String source) {return R.fail("根据调教获取用户列表失败:" + throwable.getMessage());}@Overridepublic R<Boolean> registerUserInfo(SysUser sysUser, String source) {return R.fail("注册用户失败:" + throwable.getMessage());}};}
}

8 总结

本文围绕 PmHub,介绍 Sentinel 在微服务架构中熔断降级的必要性、基本概念、原理等,阐述其下载使用方法,以及配合 Gateway 实现网关限流、配合 OpenFeign 实现自定义 fallback 服务降级,助力开发者保障微服务架构稳定性。

9 参考链接

  1. PmHub集成 Sentinel+OpenFeign实现网关流量控制,以及自定义fallback服务降级
  2. 项目仓库(GitHub)
  3. 项目仓库(码云): (国内访问速度更快)

相关文章:

【PmHub后端篇】PmHub集成 Sentinel+OpenFeign实现网关流量控制与服务降级

在微服务架构中&#xff0c;保障服务的稳定性和高可用性至关重要。本文将详细介绍在 PmHub 中如何利用 Sentinel Gateway 进行网关限流&#xff0c;以及集成 Sentinel OpenFeign 实现自定义的 fallback 服务降级。 1 熔断降级的必要性 在微服务架构中&#xff0c;服务间的调…...

2025最新出版 Microsoft Project由入门到精通(八)

目录 查找关键路径方法 方法1:格式->关键任务 方法2:插入关键属性列 方法3&#xff1a;插入“可宽延的总时间”进行查看&#xff0c;>0不是关键路径&#xff0c;剩余的全是关键路径 方法4:设置关键路径的工作表的文本样式​编辑 方法5&#xff1a;突出显示/筛选器…...

3.0/Q2,Charls最新文章解读

文章题目&#xff1a;Development of a visualized risk prediction system for sarcopenia in older adults using machine learning: a cohort study based on CHARLS DOI&#xff1a;10.3389/fpubh.2025.1544894 中文标题&#xff1a;使用机器学习开发老年人肌肉减少症的可视…...

使用matlab进行数据拟合

目录 一、工作区建立数据 二、曲线拟合器(在"APP"中) 三、曲线拟合函数及参数 四、 在matlab中编写代码 一、工作区建立数据 首先&#xff0c;将数据在matlab工作区中生成。如图1所示&#xff1a; 图 1 二、曲线拟合器(在"APP"中) 然后&#xff0c;…...

分布式1(cap base理论 锁 事务 幂等性 rpc)

目录 分布式系统介绍 一、定义与概念 二、分布式系统的特点 三、分布式系统面临的挑战 四、分布式系统的常见应用场景 CAP 定理 BASE 理论 BASE理论是如何保证最终一致性的 分布式锁的常见使用场景有哪些&#xff1f; 1. 防止多节点重复操作 2. 资源互斥访问 3. 分…...

Myshell与清华联合开源TTS模型OpenVoiceV2,多语言支持,风格控制进一步增强~

项目背景 开发团队与发布 OpenVoice2 由 MyShell AI&#xff08;加拿大 AI 初创公司&#xff09;与 MIT 和清华大学的研究人员合作开发&#xff0c;技术报告于 2023 年 12 月发布 &#xff0c;V2 版本于 2024 年 4 月发布 。 项目目标是提供一个高效、灵活的语音克隆工具&…...

2025-05-14 Word Embedding

Word Embedding 词嵌入&#xff08;Word Embedding&#xff09;是自然语言处理&#xff08;NLP&#xff09;中的一种表征学习技术&#xff0c;旨在将单词映射为连续的低维向量&#xff0c;从而使计算机能够理解和处理文本信息。它通过学习大量文本数据中的上下文关系&#xff…...

YOLO11解决方案之热力图探索

概述 Ultralytics提供了一系列的解决方案,利用YOLO11解决现实世界的问题,包括物体计数、模糊处理、热力图、安防系统、速度估计、物体追踪等多个方面的应用。 使用YOLO11生成的热力图把复杂的数据转换成生动的彩色编码矩阵。这种可视化工具采用色谱来表示不同的数据值,暖色…...

如何在终端/命令行中把PDF的每一页转换成图片(PNG)

今天被对象安排了一个任务&#xff1a; 之前自己其实也有这个需要&#xff0c;但是吧&#xff0c;我懒&#xff1a;量少拖拽&#xff0c;量大就放弃。但这次躲不过去了&#xff0c;所以研究了一下有什么工具可以做到这个需求。 本文记录我这次发现的使用 XpdfReader 的方法。…...

计算机系统结构——Cache性能分析

一、实验目的 加深对Cache的基本概念、基本组织结构以及基本工作原理的理解。掌握Cache容量、相联度、块大小对Cache性能的影响。掌握降低Cache不命中率的各种方法以及这些方法对提高Cache性能的好处。理解LRU与随机法的基本思想以及它们对Cache性能的影响。 二、实验平台 实…...

C++ 在 Windows 的开发经验与解决方案

一、开发环境搭建 在 Windows 上进行 C 开发&#xff0c;主流的集成开发环境&#xff08;IDE&#xff09;有 Visual Studio 和 CLion。Visual Studio 是微软官方推出的强大开发工具&#xff0c;对 Windows 平台有着原生的支持&#xff0c;集成了编译器、调试器、代码编辑器等一…...

GESP2023年12月认证C++八级( 第三部分编程题(2)大量的工作沟通)

参考程序&#xff1a; #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <string> #include <map> #include <iostream> #include <cmath> #include <vector> #include <qu…...

LeetCode 题解 41. 缺失的第一个正数

41. 缺失的第一个正数 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围 [1,…...

015枚举之滑动窗口——算法备赛

滑动窗口 最大子数组和 题目描述 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 原题链接 思路分析 见代码注解 代码 int maxSubArray(vector<int>& num…...

SQL 索引优化指南:原理、知识点与实践案例

SQL 索引优化指南&#xff1a;原理、知识点与实践案例 索引的基本原理 索引是数据库中用于加速数据检索的数据结构&#xff0c;类似于书籍的目录。它通过创建额外的数据结构来存储部分数据&#xff0c;使得查询可以快速定位到所需数据而不必扫描整个表。 索引的工作原理 B-…...

centos服务器,疑似感染phishing家族钓鱼软件的检查

如果怀疑 CentOS 服务器感染了 Phishing 家族钓鱼软件&#xff0c;需要立即进行全面检查并采取相应措施。以下是详细的检查和处理步骤&#xff1a; 1. 立即隔离服务器 如果可能&#xff0c;将服务器从网络中隔离&#xff0c;以防止进一步传播或数据泄露。如果无法完全隔离&…...

新型深度神经网络架构:ENet模型

语义分割技术能够为图像中的每个像素分配一个类别标签&#xff0c;这对于理解图像内容和在复杂场景中找到目标对象至关重要。在自动驾驶和增强现实等应用中&#xff0c;实时性是一个硬性要求&#xff0c;因此设计能够快速运行的卷积神经网络非常关键。 尽管深度卷积神经网络&am…...

【免杀】C2免杀技术(三)shellcode加密

前言 shellcode加密是shellcode混淆的一种手段。shellcode混淆手段有多种&#xff1a;加密&#xff08;编码&#xff09;、偏移量混淆、UUID混淆、IPv4混淆、MAC混淆等。 随着杀毒软件的不断进化&#xff0c;其检测方式早已超越传统的静态特征分析。现代杀软往往会在受控的虚…...

3、ubantu系统docker常用命令

1、自助查看docker命令 1.1、查看所有命令 docker 客户端非常简单&#xff0c;可以直接输入 docker 命令来查看到 Docker 客户端的所有命令选项。 angqiangwangqiang:~$ dockerUsage: docker [OPTIONS] COMMANDA self-sufficient runtime for containersCommon Commands:ru…...

【Linux】shell内置命令fg,bg和jobs

​Shell 内置命令​​ fg&#xff08;foreground 的缩写&#xff09;。它用于将​​后台挂起的任务恢复到前台运行​​。 例如&#xff1a; 假设你运行了一个耗时的 SVN 操作&#xff08;如 svn update 或 svn checkout&#xff09;。按下 CtrlZ 将该进程挂起到后台。输入 fg…...

Java GUI开发全攻略:Swing、JavaFX与AWT

Swing 界面开发 Swing 是 Java 中用于创建图形用户界面&#xff08;GUI&#xff09;的库。它提供了丰富的组件&#xff0c;如按钮、文本框、标签等。 import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class SwingExa…...

WPF之集合绑定深入

文章目录 引言ObservableCollection<T>基础什么是ObservableCollectionObservableCollection的工作原理基本用法示例ObservableCollection与MVVM模式ObservableCollection的局限性 INotifyCollectionChanged接口深入接口定义与作用NotifyCollectionChangedEventArgs详解自…...

LeetCode 每日一题 3341. 到达最后一个房间的最少时间 I + II

3341. 到达最后一个房间的最少时间 I II 有一个地窖&#xff0c;地窖中有 n x m 个房间&#xff0c;它们呈网格状排布。 给你一个大小为 n x m 的二维数组 moveTime &#xff0c;其中 moveTime[i][j] 表示在这个时刻 以后 你才可以 开始 往这个房间 移动 。你在时刻 t 0 时从…...

(C语言)超市管理系统(测试2版)(指针)(数据结构)(清屏操作)

目录 前言&#xff1a; 源代码&#xff1a; product.h product.c fileio.h fileio.c main.c 代码解析&#xff1a; 一、程序结构概述 二、product.c 函数详解 1. 初始化商品列表 Init_products 2. 添加商品 add_product 3. 显示商品 display_products 4. 修改商品 mo…...

什么是虚拟同步发电机

虚拟同步发电机&#xff08;Virtual Synchronous Generator, VSG&#xff09; 是一种基于电力电子技术的先进控制策略&#xff0c;通过模拟传统同步发电机的机电特性和动态行为&#xff0c;使逆变器或储能系统能够像传统发电机一样为电网提供惯性支撑、频率调节和电压稳定性支持…...

Python字符串全面指南:从基础到高级

文章目录 Python字符串全面指南&#xff1a;从基础到高级1. 字符串基础概念2. 字符串的基本操作2.1 字符串拼接2.2 字符串索引和切片 3. 字符串常用方法3.1 大小写转换3.2 字符串查找和替换3.3 字符串分割和连接3.4 字符串格式化3.5 字符串验证 4. 字符串的不可变性5. 字符串编…...

基于大模型的TIA诊疗全流程智能决策系统技术方案

目录 一、多模态数据融合与预处理系统1.1 数据接入模块1.2 数据预处理伪代码二、TIA智能预测模型系统2.1 模型训练流程2.2 混合模型架构伪代码三、术中智能监测系统3.1 实时监测流程3.2 实时预测伪代码四、智能诊疗决策系统4.1 手术方案推荐流程4.2 麻醉方案生成伪代码五、预后…...

编译openssl源码

openssl版本 1.1.1c windows 安装环境 perl 先安装perl&#xff0c;生成makefile需要 https://strawberryperl.com/releases.html nasm nasm 也是生成makefile需要 https://www.nasm.us/ 安装完perl输入一下nasm&#xff0c;看看能不能找到&#xff0c;找不到的话需要配…...

CMake入门与实践:现代C++项目的构建利器

文章目录 CMake入门与实践&#xff1a;现代C项目的构建利器引言什么是CMake&#xff1f;快速入门&#xff1a;从Hello World开始1. 安装CMake2. 最小项目示例3. 构建项目 核心概念详解1. 项目结构组织2. 常用指令3. 变量与条件控制 进阶技巧1. 多目录项目管理2. 集成第三方库3.…...

OpenCV实现数字水印的相关函数和示例代码

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 实现数字水印的相关函数 用OpenCV来实现数字水印功能&#xff0c;需要使用一些位操作函数&#xff0c;我们需要先了解一下这些函数。 1. bitwise_and函数 bitwise_and函数是OpenCV中的位运算函数之一&…...