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

Spring Cloud - 2( 12000 字详解 Spring Cloud)

一:服务注册和服务发现 - Eureka

1.1 背景

在上一章节的例子中,我们可以看到远程调用时 URL 被硬编码,这导致在更换机器或新增机器时,相关的 URL 需要进行相应的变更。这就需要让所有相关服务去修改 URL,随之而来的就是各个项目配置文件的频繁更新和项目的重复部署。这种虽然没有实际意义却又不得不进行的工作,给人带来了很大的困扰和痛苦。

String url = "http://127.0.0.1:9090/product/"+ orderInfo.getProductId();

1.2 解决思路

在我们的日常生活中,我们经常需要与各种机构打交道,比如说医院、学校、政府部门等等,因此我们需要保存它们的电话号码。但是如果构更换了电话号码,想要通知所有使用这些号码的用户就变得非常困难,因为相关的用户群体往往非常庞大。那么,我们该如何处理这种情况呢?

一种有效的解决方案是引入一个中间件 114 查号台,通过 114 查号台进行电话管理。当机构的电话号码发生变化时,服务方会将最新号码上报给 114 查号台。用户在需要联系某个机构时,可以先拨打 114 查询最新的电话号码,然后再与相应的机构取得联系。114 查号台的主要功能包括号码注册和号码查询,号码注册即服务方将电话信息提交给 114查号台,让查号台有你这个数据,号码查询即用户可以通过 114 查号台获取到相应机构的最新电话号码。

这种模式的关键是让 114 查号台随时都有着最新的信息,不直接让用户和机构进行交互,而是让用户和查号台、机构和查号台进行交互,当机构的号码变了之后就在查号台中更新信息,当用户需要知道最新号码了,就直接和查号台直接进行交互。

在这里插入图片描述
同样地,在微服务开发中,我们也可以采用类似的方案。当服务启动或发生变更时,服务会向注册中心进行注册,注册中心记录应用与其 IP 地址的关系,这样注册中心就随时都有着服务最新的一些信息。在进行远程调用时,调用方就可以向注册中心查询目标服务最新的 IP 地址,然后再通过该 IP 地址进行实际调用。这种方式有效地减少了调用方对服务提供方 IP 的依赖,提高了系统的灵活性和可维护性。

1.3 什么是注册中心

在最初的架构体系中,集群的概念并不流行,且机器数量相对较少,此时通过 DNS 和 Nginx 即可满足大部分服务的发现需求,相关的注册信息直接配置在 Nginx 中。但是随着微服务的兴起和流量的激增,机器规模逐渐扩大,频繁的上下线行为使得运维人员需要手动维护这些配置信息,这变得非常繁琐。因此开发者们开始希望能有一个工具,能够维护一个自动更新的服务列表,记录哪些机器已上线,哪些机器已宕机。客户端只需获取这个服务列表,就可以直接对那些已经上线的服务进行调用。这就是注册中心的作用,注册中心主要有三种角色:

角色描述
服务提供者 (Server)在一次业务中,被其他微服务调用的服务,提供接口给其他微服务使用。
服务消费者 (Client)在一次业务中,调用其他微服务的服务,使用其他微服务提供的接口。
服务注册中心 (Registry)用于保存服务提供者的注册信息,当服务节点发生变更时,注册中心会同步这些变更。 服务与注册中心通过一定机制进行通信,如果注册中心长时间无法与某服务通信,该实例将被注销。
  • 服务注册:服务提供者在启动时会向注册中心注册自身服务,并定期向注册中心发送心跳信号,以汇报存活状态。
  • 服务发现:服务消费者从注册中心查询服务提供者的地址,接着可以通过该地址调用服务提供者的接口。服务发现的重要功能之一是为服务消费者提供一个可用的服务列表。

在这里插入图片描述

1.4 CAP 理论

谈到注册中心,就避不开 CAP 理论。CAP 理论是分布式系统设计中最基础且关键的理论,它包含以下三项内容:

  • 一致性 (Consistency):指的是强一致性,即所有节点在同一时间拥有相同的数据。
  • 可用性 (Availability):确保每个请求都有响应,尽管响应结果可能不正确。
  • 分区容错性 (Partition Tolerance):在出现网络分区的情况下,系统仍然能够对外提供服务。

CAP 理论表明,分布式系统不可能同时满足数据一致性、服务可用性和分区容错性这三个基本需求,最多只能同时满足其中的两个。在分布式系统中,由于网络无法保证 100% 的健康,而服务又必须对外提供可用性,因此分区容错性是不可避免的。这意味着在一致性和可用性之间必须做出选择,系统架构因此可以分为 CP 架构和 AP 架构。

在这里插入图片描述
正常情况:
在这里插入图片描述
网络异常:
在这里插入图片描述
在 CP 架构中,为了确保分布式系统对外的数据一致性,系统通常选择不返回任何数据,直到数据的一致性得到确认。而在 AP 架构中,为了保证分布式系统的可用性,节点可能会返回版本 V0 的数据,即使这个数据可能并不准确。

注册中心描述
Zookeeper虽然官方没有将 Zookeeper 定义为注册中心,但在国内 Java 生态中,大多数集群环境依赖 Zookeeper 来实现服务注册中心的功能。
EurekaEureka 是 Netflix 开发的基于REST的服务发现框架,主要用于服务注册、管理、负载均衡和故障转移。官方声明 Eureka 2.0 版本已停止维护,不建议使用,但由于它是 Spring Cloud 的默认实现,仍有许多公司在使用。
NacosNacos 是 Spring Cloud Alibaba 架构中的重要组件,除了提供服务注册和发现功能外,还支持配置管理、流量管理、DNS 和动态 DNS 等多种特性。

二:Eureka 简介

Eureka 是 Netflix OSS 套件中专注于服务注册和发现的解决方案。Spring Cloud 对 Eureka 进行了集成,并作为优先推荐的方案进行推广。尽管 Eureka 2.0 目前已停止维护,并且新微服务架构设计中不再建议使用它,但仍然有大量公司的微服务系统在使用 Eureka 作为注册中心,Eureka 主要分为两个部分:

  • Eureka Server:作为注册中心的 Server 端,Eureka Server 为微服务应用程序提供服务注册、发现和健康检查等功能。
  • Eureka Client:服务提供者在服务启动时会作为 Eureka Client 注册到 Eureka Server。

2.1 搭建 Eureka Server

Eureka-server 是⼀个独立的微服务

2.1.1 创建 Eureka-server 子模块

在这里插入图片描述

2.1.2 引入 eureka-server 依赖和项目构建插件

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

2.1.3 完善启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}
}

2.1.4 编写配置文件

server:port: 10010 # 设置Eureka Server监听的端口spring:application:name: eureka-server # 应用名称eureka:instance:hostname: localhost # Eureka Server的主机名client:fetch-registry: false # 是否从其他Eureka Server获取注册信息,默认为true。# 因为这是一个单点的Eureka Server,不需要同步其他节点的数据,这里设为false。register-with-eureka: false # 是否将自己注册到Eureka Server,默认为true。# 由于当前应用就是Eureka Server,因此设为false。sevice-url:# 设置与Eureka Server的地址,查询服务和注册服务都需要依赖这个地址。defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

2.1.5 启动服务

启动服务并访问注册中心:http://127.0.0.1:10010/

在这里插入图片描述

2.2 服务注册

接下来我们把 product-service 注册到 eureka-server 中

2.2.1 引入 eureka-client 依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2.2.2 完善配置文件

spring:application:name: product-service # 应用名称eureka:client:service-url:defaultZone: http://127.0.0.1:10010/eureka # Eureka Server地址

2.2.3 启动服务

通过访问注册中心的地址 http://127.0.0.1:10010/,可以查看到 product-service 已成功注册到 Eureka 上。

在这里插入图片描述

2.3 服务发现

接下来我们对 order-service 进行修改,在远程调用时,从 Eureka Server 获取 product-service 的服务信息,实现服务发现。

2.3.1 引入依赖

服务注册和服务发现都封装在 eureka-client 依赖中, 所以服务发现时也是引入 eureka-client 依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2.3.2 完善配置文件

spring:application:name: product-serviceeureka:client:service-url:defaultZone: http://127.0.0.1:10010/eureka

2.3.3 远程调用

在进行远程调用时,我们需要从 Eureka Server 获取 product-service 的服务列表,这个列表可能会有多个服务,并从中选择一个进行调用。

import com.bite.order.mapper.OrderMapper;
import com.bite.order.model.OrderInfo;
import com.bite.order.model.ProductInfo;
import org.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.eureka.EurekaServiceInstance;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.util.List;@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;  @Resourceprivate DiscoveryClient discoveryClient;  // 注入 DiscoveryClient,用于服务发现@Autowiredprivate RestTemplate restTemplate;  // 注入 RestTemplate,用于进行 HTTP 请求// 根据订单 ID 查询订单信息public OrderInfo selectOrderById(Integer orderId) {// 从数据库中获取订单信息OrderInfo orderInfo = orderMapper.selectOrderById(orderId);// 根据服务名称获取 product-service 实例列表List<ServiceInstance> instances = discoveryClient.getInstances("product-service");// 从实例列表中获取第一个服务实例EurekaServiceInstance instance = (EurekaServiceInstance) instances.get(0);// 记录服务实例 ID,便于调试log.info(instance.getInstanceId());// 拼接调用 product-service 的 URLString url = instance.getUri() + "/product/" + orderInfo.getProductId();// 通过 RestTemplate 发起 GET 请求,获取产品信息ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);// 将获取到的产品信息设置到订单信息中orderInfo.setProductInfo(productInfo);// 返回更新后的订单信息return orderInfo;}
}

2.3.4 启动服务

通过访问注册中心 http://127.0.0.1:10010/,可以看到 order-service 已成功注册到 Eureka 上。此外,访问接口 http://127.0.0.1:8080/order/1 也表明远程调用已经顺利完成。

在这里插入图片描述

在这里插入图片描述

三:负载均衡 - LoadBalance

List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
//服务可能有多个, 获取第⼀个
EurekaServiceInstance instance = (EurekaServiceInstance) instances.get(0);

这段代码是我们在介绍 Eureka 时编写的,它根据应用名称获取服务实例列表,并从中选择了一个服务实例。但是我们此时思考一个问题:如果我们启动了两个 product-service 实例,此时实例列表中就会包含两个 product-service 实例。那么,如何确保流量能够合理地分配到这多个实例上呢?

我们再启动两个 product-service 实例,选中要启动的服务,右键点击并选择 Copy Configuration…。接着,在弹出的窗口中,选择 Modify options -> Add VM options,然后添加以下 JVM 选项:-Dserver.port=9091。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

现在 IDEA 的 Service 窗口中会多出一个启动配置。右键点击该配置即可启动服务。通过相同的操作,再启动一个实例,这样就可以总共启动三个 product-service 实例。

在这里插入图片描述

在这里插入图片描述
观察 Eureka, 可以看到 product-service下有三个实例:

在这里插入图片描述

注意:此时如果发起多次请求的话指向的都是同一台机器,因为我们之前的代码是有问题的,这显然不是我们想要的结果。我们启动多个实例的目的是希望能够分担其他机器的负载。那么,如何实现这一点呢?解决方案是对上述代码进行简单修改。

// 用于生成服务实例的轮询索引
private static AtomicInteger atomicInteger = new AtomicInteger(1);
// 存储获取到的服务实例列表
private static List<ServiceInstance> instances;// 初始化方法,获取“product-service”的所有服务实例
@PostConstruct
public void init() {instances = discoveryClient.getInstances("product-service");
}// 根据订单ID查询订单信息,并获取对应产品信息
public OrderInfo selectOrderById(Integer orderId) {// 查询订单信息OrderInfo orderInfo = orderMapper.selectOrderById(orderId);// 轮询获取服务实例的索引int index = atomicInteger.getAndIncrement() % instances.size();// 获取相应的服务实例ServiceInstance instance = instances.get(index);// 记录日志,输出当前使用的实例IDlog.info(instance.getInstanceId());// 拼接请求URLString url = instance.getUri() + "/product/" + orderInfo.getProductId();// 通过RestTemplate发送请求,获取产品信息ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);// 将产品信息设置到订单信息中orderInfo.setProductInfo(productInfo);return orderInfo; // 返回订单信息
}

3.1 什么是负载均衡

通过上述代码可以初步了解负载均衡的概念:负载均衡是将请求平均分配到不同实例上的过程。负载均衡是高并发、高可用系统中不可或缺的关键组件。当服务流量增大时,通常采用增加机器的方式进行扩容,而负载均衡则旨在根据一定规则,在多个机器或其他资源之间合理地分配负载。

在上述例子中,我们只是简单地实现了对实例的轮询,但实际业务场景往往更加复杂。例如,可以根据机器的配置进行负载分配,将流量更多地分配给配置较高的机器,而流量较少分配给配置较低的机器。这就类似于企业中强能力的员工可以承担更多工作。在多机部署的服务中,开发人员需要考虑负载均衡的实现,因此出现了一些负载均衡器来帮助我们实现这一目标。负载均衡主要分为服务端负载均衡和客户端负载均衡。

3.1.1 服务端负载均衡

服务端负载均衡通过特定的算法对请求进行分配,而 Nginx 是一个比较知名的服务端负载均衡器。当请求到达 Nginx 后,它会根据负载均衡算法在多个服务器之间选择一个进行访问,从而实现有效的流量管理和资源利用。

在这里插入图片描述

3.1.2 客户端负载均衡

客户端负载均衡是在客户端通过算法实现负载均衡功能,而不再依赖于单个指定的负载均衡设备集中提供此功能。例如,Spring Cloud 的 Ribbon 允许请求在客户端进行负载均衡处理。简单点说,请求首先发送到客户端,客户端从注册中心获取服务列表,然后通过负载均衡算法选择一个服务器进行访问。客户端负载均衡和服务端负载均衡最大的区别在于服务清单所存储的位置

在这里插入图片描述

3.2 Spring Cloud LoadBalancer 快速上手

自 2020.0.1 版本以来,Spring Cloud 移除了 Ribbon 组件,并采用 Spring Cloud LoadBalancer 组件来替代 Ribbon 实现客户端负载均衡。

3.2.1 使用 Spring Cloud LoadBalancer 实现负载均衡

  1. 只需给 RestTemplate 这个 Bean 添加 @LoadBalanced 注解即可实现负载均衡功能。
@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}
}
  1. 接着修改 IP 和端口号为服务名称
public OrderInfo selectOrderById(Integer orderId) {// 查询订单信息OrderInfo orderInfo = orderMapper.selectOrderById(orderId);// 构造产品信息的URLString url = "http://product-service/product/" + orderInfo.getProductId();// 调用外部服务获取产品信息ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);// 将产品信息设置到订单信息中orderInfo.setProductInfo(productInfo);return orderInfo;
}

启动多个 product-service 实例后,连续多次发送请求 http://127.0.0.1:8080/order/1,接着可以在 product-service 的日志中观察到负载均衡成功地将请求分配到了这三个实例上。

在这里插入图片描述

3.2.2 负载均衡策略

负载均衡策略是一种核心思想,无论使用何种负载均衡器,其基本策略都是相似的。Spring Cloud LoadBalancer 支持两种主要的负载均衡策略:轮询和随机选择。轮询策略通过轮流处理用户请求来分配负载,这是一种实现简单且常用的策略,类似于学校的值日生或轮流打扫卫生的场景。而随机选择策略则是随机选取一个后端服务器来处理新请求。

Spring Cloud LoadBalancer 的默认负载均衡策略是轮询策略,其实现为 RoundRobinLoadBalancer。如果服务消费者希望使用随机负载均衡策略,操作起来也非常简单。

3.2.2.1 定义随机算法对象

定义一个随机算法对象,并通过 @Bean 注解将其加载到 Spring 容器中,这里使用的是 Spring Cloud LoadBalancer 提供的 RandomLoadBalancer,注意:该类需要满足以下要求:首先不使用 @Configuration 注解;其次它必须位于组件扫描的范围内。

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;public class LoadBalancerConfig {// 定义一个随机负载均衡器的 Bean@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {// 获取当前负载均衡器的服务名称String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);System.out.println("=============="+name);// 创建并返回 RandomLoadBalancer 实例return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,ServiceInstanceListSupplier.class), name);}
}
3.2.2.2 @LoadBalancerClient 或者 @LoadBalancerClients 注解

在 RestTemplate 配置类上使用 @LoadBalancerClient 或 @LoadBalancerClients 注解,可以为不同的服务提供者配置不同的客户端负载均衡算法策略。由于我们的项目中只有一个服务提供者,因此使用 @LoadBalancerClient 注解,其中 name 属性指定该负载均衡策略适用于哪个服务提供者,而 configuration 属性则指定使用哪个负载均衡策略实现。

import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.web.client.RestTemplate;// 使用 @LoadBalancerClient 注解为 product-service 配置负载均衡策略
@LoadBalancerClient(name = "product-service", configuration = LoadBalancerConfig.class)
// 标记该类为 Spring 配置类
@Configuration
public class BeanConfig {// 创建一个带负载均衡支持的 RestTemplate Bean@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate(); // 返回 RestTemplate 的实例}
}

3.2.3 服务部署

首先需要使用 Maven 对三个服务进行打包:eureka-server、order-service 和 product-service。打包方式与 Spring Boot 项目一致,依次对这三个项目进行打包即可。

在这里插入图片描述

接着将 Jar 包传输到云服务器,可以直接将文件拖动到 Xshell 窗口以完成上传。上传成功后,启动服务,并记得启动两台实例。

# 后台启动 eureka-server, 并设置输出日志到 logs/eureka.log
nohup java -jar eureka-server.jar > logs/eureka.log &# 后台启动 order-service, 并设置输出日志到 logs/order.log
nohup java -jar order-service.jar > logs/order.log &# 后台启动 product-service, 并设置输出日志到 logs/product-9090.log
nohup java -jar product-service.jar > logs/product-9090.log &# 启动 product-service 实例,指定端口号为 9091
nohup java -jar product-service.jar --server.port=9091 > logs/product-9091.log &# 启动 product-service 实例,指定端口号为 9092
nohup java -jar product-service.jar --server.port=9092 > logs/product-9092.log &

启动之前请确保云服务器的相关端口已经开放。根据自己项目的设置情况,在云服务器上开放所需的端口号。

在这里插入图片描述

最后分别访问 Eureka Server 和订单服务接口:http://110.41.51.65:8080/order/1

在这里插入图片描述
在这里插入图片描述

相关文章:

Spring Cloud - 2( 12000 字详解 Spring Cloud)

一&#xff1a;服务注册和服务发现 - Eureka 1.1 背景 在上一章节的例子中&#xff0c;我们可以看到远程调用时 URL 被硬编码&#xff0c;这导致在更换机器或新增机器时&#xff0c;相关的 URL 需要进行相应的变更。这就需要让所有相关服务去修改 URL&#xff0c;随之而来的就…...

解决Win11下MySQL服务无法开机自启动问题

问题描述 在win11系统中&#xff0c;明明将MySQL服务设置成了自动启动&#xff0c;但在重启电脑后MySQL服务还是无法自动启动&#xff0c;每次都要重新到计算机管理的服务中找到服务再手动启动。 解决方式 首先确保mysql服务的启动类型为自动。 设置方法&#xff1a;找到此电…...

RGB矩阵照明系统详解及WS2812配置指南

RGB矩阵照明系统详解及WS2812配置指南 一、RGB矩阵照明简介 RGB矩阵照明是一种强大的功能&#xff0c;允许使用外部驱动器驱动的RGB LED矩阵为键盘增添绚丽的灯光效果。该系统与RGBLIGHT功能无缝集成&#xff0c;因此您可以使用与RGBLIGHT相同的键码来控制它&#xff0c;操作…...

全球首款无限时长电影生成模型SkyReels-V2本地部署教程:视频时长无限制!

一、简介 SkyReels-V2 模型集成了多模态大语言模型&#xff08;MLLM&#xff09;、多阶段预训练、强化学习以及创新的扩散强迫&#xff08;Diffusion-forcing&#xff09;框架&#xff0c;实现了在提示词遵循、视觉质量、运动动态以及视频时长等方面的全面突破。通过扩散强迫框…...

代理ARP与传统ARP在网络通信中的应用及区别研究

一些问题 路由器隔离广播域&#xff0c;每个接口/网段都是独立的广播域ARP请求是二层广播包&#xff0c;广播包没法通过路由器ARP请求没法穿越互联网到达目标主服务器 一些思考 电脑访问互联网服务器的时候&#xff0c;ARP询问的内容&#xff0c;真的是访问服务器么&#xf…...

理解 Envoy 的架构

理解 Envoy 的架构对于深入理解 Istio 至关重要&#xff0c;因为 Envoy 是 Istio 数据平面的核心。Envoy 是一个高性能的 C 分布式代理&#xff0c;设计为云原生应用和大规模微服务架构的网络基础。 以下是 Envoy 架构的关键组成部分和核心理念&#xff1a; 核心设计理念&…...

使用Kotlin Flow实现Android应用的响应式编程

在Android应用中使用Kotlin Flow实现响应式编程可以分为以下步骤&#xff0c;结合最佳实践和生命周期管理&#xff1a; 1. 添加依赖 在build.gradle中确保包含协程和生命周期相关依赖&#xff1a; dependencies {implementation("org.jetbrains.kotlinx:kotlinx-corouti…...

【AI提示词】蝴蝶效应专家

提示说明 一位专注于分析和优化蝴蝶效应现象的专业人士&#xff0c;擅长将微小变化转化为系统级影响的研究者。 提示词 # Role: 蝴蝶效应专家## Profile - language: 中文 - description: 一位专注于分析和优化蝴蝶效应现象的专业人士&#xff0c;擅长将微小变化转化为系统级…...

StreamRL:弹性、可扩展、异构的RLHF架构

StreamRL&#xff1a;弹性、可扩展、异构的RLHF架构 大语言模型&#xff08;LLMs&#xff09;的强化学习&#xff08;RL&#xff09;训练正处于快速发展阶段&#xff0c;但现有架构存在诸多问题。本文介绍的StreamRL框架为解决这些难题而来&#xff0c;它通过独特设计提升了训…...

架构进阶:大型制造业企业数据架构顶层设计总体规划方案【附全文阅读】

本文概述了一个大型企业数据架构设计的总体规划方案,针对当前数据架构与管理中存在的诸多问题,如缺乏统一数据模型、数据分析应用体系不健全、主数据管理体系不完善、数据治理体系缺失等,提出了明确的改进目标与实施路径。 数据架构设计思路聚焦于明确数据分布和流向…...

前端指南——项目代码结构解析(React为例)

文件结构 文件项目 ├── doc │ ├── technology.md ├── node_modules ├── public ├── shell ├── src │ ├── auto-generated │ │ ├── apis │ │ ├── models │ ├── components │ │ ├── 组件A │ │ ├── 组件B …...

Redis-数据一致性问题与解决方案

Redis-数据一致性问题与解决方案 引言 Redis 是一个高性能的内存数据库&#xff0c;广泛应用于缓存、会话存储、实时分析等场景。作为一个 NoSQL 数据库&#xff0c;它的高性能和丰富的数据结构使其成为现代微服务架构中不可或缺的组件。然而&#xff0c;在高并发的环境下&am…...

【数据结构】算法的复杂度

前言&#xff1a;经过了C语言的学习&#xff0c;紧接着就步入到数据结构的学习了。在C语言阶段我们在写大多数的oj题的时候会遇到一些问题&#xff0c;就是算法的效率低使用的时间较多&#xff0c;占用的空间也多&#xff0c;数据结构就是来优化算法的。 文章目录 一&#xff…...

Leetcode刷题 由浅入深之字符串——541. 反转字符串Ⅱ

目录 &#xff08;一&#xff09;反转字符串Ⅱ的C实现 写法一&#xff08;s.begin&#xff08;&#xff09;遍历字符&#xff09; &#xff08;二&#xff09;复杂度分析 时间复杂度 空间复杂度 &#xff08;三&#xff09;总结 【题目链接】541. 反转字符串Ⅱ - 力扣&am…...

制造单元智能化改造与集成技术平台成套实训设备

制造单元智能化改造与集成技术平台成套实训设备 一、概述&#xff1a; 本设备以汽车行业的轮毂为产品对象&#xff0c;实现了仓库取料、制造加工、打磨抛光、检测识别、分拣入位等生产工艺环节&#xff0c;以未来智能制造工厂的定位和需求为参考&#xff0c;通过工业以太网完成…...

Vscode 顶部Menu(菜单)栏消失如何恢复

Vscode 顶部Menu(菜单)栏消失如何恢复 https://blog.csdn.net/m0_62964247/article/details/135759655 Vscode 顶部Menu(菜单)栏消失如何恢复&#xff1f; 首先按一下 Alt按键&#xff0c;看一下是否恢复了菜单栏 如果恢复了想了解更进一步的设置&#xff0c;或是没能恢复菜单…...

苍穹外卖--公共字段自动填充

1.问题分析 业务表中的公共字段&#xff1a; 问题&#xff1a;代码冗余、不便于后期维护 2.实现思路 自定义注解AutoFill&#xff0c;用于标识需要进行公共字段填充的方法 自定义切面类AutoFillAspect&#xff0c;统一拦截加入了AutoFill注解的方法&#xff0c;通过反射为公…...

行业 |四大痛点待破:“拆解”DeepSeek一体机

繁荣DeepSeek一体机市场。 2025年开年&#xff0c;DeepSeek大模型掀起的一体机热潮席卷中国AI市场。这款一体机凭借其“开箱即用”的便利性和极低的门槛&#xff0c;吸引了大量企业关注&#xff0c;尤其是在中小企业和行业创新者中&#xff0c;更是成为了新晋“顶流”。 无论…...

革新锅炉厂智能控制——Ethernet IP转CANopen协议网关的工业互联新方案

锅炉厂智能化转型的必经之路 在工业4.0时代&#xff0c;锅炉厂作为能源供应的核心环节&#xff0c;正面临智能化升级的迫切需求。传统锅炉控制系统往往因协议不兼容、数据孤岛问题导致效率低下、维护成本高昂。如何实现设备间高效协同&#xff1f;如何让老旧设备融入智能网络&…...

基于卷积神经网络和Pyqt5的猫狗识别小程序

任务描述 猫狗分类任务&#xff08;Dogs vs Cats&#xff09;是Kaggle平台在2013年举办的一个经典计算机视觉竞赛。官方给出的Kaggle Dogs vs Cats 数据集中包括由12500张猫咪图片和12500张狗狗图片组成的训练集&#xff0c;12500张未标记照片组成的测试集。选手需要在规定时间…...

Baklib知识中台引领服务智能跃迁

智能架构重构服务范式 Baklib 知识中台通过全量数据融合与多模态处理能力&#xff0c;重塑企业服务底层逻辑。基于分布式架构设计&#xff0c;平台将分散在业务系统、文档库及外部渠道的非结构化数据进行智能清洗与语义解析&#xff0c;形成标准化的知识元数据池。通过四库体系…...

【Python】超全常用 conda 命令整理

Conda命令整理文档&#xff0c;结合官方指南与高频使用场景分类说明&#xff0c;每个命令都有对应的解释 一、环境管理 1. 创建环境 基本创建conda create --name my_env # 创建名为my_env的空环境 conda create -n my_env python3.11 # 指定Python版本 conda creat…...

FreeRTOS菜鸟入门(十四)·事件

目录 1. 基本概念 2. 应用场景 3. 运作机制 4. 控制块 5. 事件函数接口 5.1 事件创建函数 xEventGroupCreate() 5.2 事件删除函数 vEventGroupDelete() 5.3 事件组置位函数 xEventGroupSetBits()&#xff08;非中断&#xff09; 5.4 事件组置位函数 xEventGr…...

setData执行后操作方法-微信小程序

在微信小程序中&#xff0c;setData 是异步执行的&#xff0c;如果你需要在 setData 执行完毕后执行某些操作&#xff0c;可以通过以下几种方式实现&#xff1a; 1. 使用 setData 的回调函数 从基础库 2.2.3 开始&#xff0c;setData 支持传入回调函数&#xff0c;回调会在数据…...

SpringAI特性

一、SpringAI 顾问&#xff08;Advisors&#xff09; Spring AI 使用 Advisors机制来增强 AI 的能力&#xff0c;可以理解为一系列可插拔的拦截器&#xff0c;在调用 AI 前和调用 AI 后可以执行一些额外的操作&#xff0c;比如&#xff1a; 前置增强&#xff1a;调用 AI 前改…...

捌拾叁- 量子傅里叶变换

1. 前言 最近公司地震&#xff0c;现在稍微有点时间继续学习。 看了几个算法&#xff0c;都说是基于 量子傅里叶变换 &#xff0c;好&#xff0c;就是他了 Quantum Fourier。 2. 傅里叶变换 大学是学通信的&#xff0c;对于傅里叶变换还是有所理解的。其实就是基于一个 时域…...

SSTI模版注入

1、概念 SSTI是一种常见的Web安全漏洞&#xff0c;它允许攻击者通过注入恶意模板代码&#xff0c;使服务器在渲染模板时执行非预期的操作。 &#xff08;1&#xff09;渲染模版 至于什么是渲染模版&#xff1a;服务器端渲染模板是一种Web开发技术&#xff0c;它允许在服务器端…...

33、前台搜索功能怎么实现?

输入搜索的东西&#xff0c;如果为空 如果有 前端是提交表单&#xff0c;方式是 post 后端接受 调用 mybatisplus的categoryService.getById 用户在搜索框内输入关键字之后&#xff0c;执行 js 中的 load方法&#xff0c;前端提交表单&#xff0c; 后端 controller 中的loa…...

量化解析美英协议的非对称冲击:多因子模型与波动率曲面重构

摘要&#xff1a;基于机器学习算法对市场微观结构的实时监测&#xff0c;黄金价格在3300美元/盎司附近展开技术性反弹。本文通过多因子分析框架&#xff0c;解析美元指数上行、贸易政策突变及资产配置迁移对贵金属市场的复合影响&#xff0c;并构建基于LSTM神经网络的动态支撑位…...

对PyTorch模块进行性能分析

以下是针对PyTorch模块进行性能分析的完整方法与工具指南&#xff0c;结合了多种优化策略和实际应用场景&#xff1a; 一、PyTorch性能分析工具 PyTorch Profiler • 功能&#xff1a;内置的性能分析工具&#xff0c;支持捕获CPU/GPU操作、内存分配、数据形状及硬件利用率。 …...

lvm详细笔记

LVM简介 逻辑卷管理器&#xff0c;是Linux 系统中用于管理磁盘储存的关键技术。 LVM 则打破了磁盘分区一旦确定&#xff0c;其大小调整往往较为复杂&#xff0c;且难以灵活应对业务变化这种限制&#xff0c;它允许用户将多个物理分区组合卷组。例如&#xff0c;系统中的多个物…...

OpenHarmony 以太网卡热插拔事件接口无效

目录 1.背景 2.解决方案 1.背景 在OpenHarmony中调用以太网热插拔时间&#xff0c;发现热插拔没有任何回调&#xff0c;如下接口 import { ethernet } from kit.NetworkKit;ethernet.on(interfaceStateChange, (data: object) > {console.log(on interfaceSharingStateCha…...

SPDK NVMe of RDMA 部署

使用SPDK NVMe of RDMA 实现多NVMe设备共享 一、编译、安装spdk 1.1、下载 1.1.1 下载spdk源码 首先&#xff0c;我们需要从GitHub上克隆SPDK的源码仓库。打开终端&#xff0c;输入以下命令&#xff1a; git clone -b v22.01 https://github.com/spdk/spdk.git cd spdk1.1.2…...

Go语言的逃逸分析是怎么进行的

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…...

纯净IP,跨境账号稳定的底层逻辑

在跨境业务快速扩张的背景下&#xff0c;越来越多的卖家、营销人、数据团队都开始使用代理IP来实现全球网络触达。然而&#xff0c;账号封禁问题始终如影随形&#xff0c;而背后的一个“隐性元凶”常常被忽视——纯净IP的缺失。本文将从实战角度出发&#xff0c;带你深入了解什…...

编译日志:关于编译opencv带有ffmpeg视频解码支持的若干办法

编译日志&#xff1a;关于编译opencv带有ffmpeg视频解码支持的若干办法 前言 ​ 笔者这里是封装了简单的OpenCV视频播放抽象&#xff0c;然后却发现移植到Ubuntu和开发板上都罢工的事情&#xff0c;原来是Windows平台下我们是默认下载了ffmpeg的库的&#xff0c;但是在泛Linu…...

djinn: 3靶场渗透

djinn: 3 来自 <https://www.vulnhub.com/entry/djinn-3,492/> 1&#xff0c;将两台虚拟机网络连接都改为NAT模式 2&#xff0c;攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.182&#xff0c;靶场IP192.168.23.243 3&#xff0…...

WHAT - 简单服务发现

文章目录 简单理解举个例子简单服务发现方式1. 静态配置&#xff08;最简单&#xff0c;但不灵活&#xff09;2. DNS 发现3. 使用服务注册中心&#xff08;稍高级&#xff09; 总结 “简单服务发现”&#xff08;Simple Service Discovery&#xff09;通常指的是一种让系统中的…...

auto推导类型原则

auto 是 C11 引入的类型自动推导关键字&#xff0c;它允许编译器根据表达式的类型来推导变量的确切类型。虽然使用 auto 可以让代码更简洁&#xff0c;但理解它的类型推导规则非常关键&#xff0c;尤其是在涉及指针、引用、const、模板等场景时。 ✅ 一、基本推导原则 auto x …...

44.辐射发射整改简易摸底测试方法

辐射发射整改简易摸底测试方法 1. 正式摸底预测试2. 简易方法预测试3. 分析频谱4. 探查传播路径5. 施加措施6. 与简易方法预测试效果对比 1. 正式摸底预测试 去正式实验室做一次预测试&#xff0c;取得频谱图&#xff1b;确定超标频点和超标量&#xff08;备用&#xff09;。 …...

初识C++:入门基础(二)

概述&#xff1a;该篇博客主要介绍C的缺省函数、函数重载、和引用等知识。 目录 1. 缺省参数 2. 函数重载 3. 引用 3.1 引用的概念和定义 3.2 引用的特性 3.3 引用的使用 3.4 const引用 3.5 指针和引用的关系 4. nullptr 5. 小结 1. 缺省参数 缺省参数是声明或定义函…...

我国脑机接口市场规模将破38亿元,医疗领域成关键突破口

当人类仅凭"意念"就能操控无人机编队飞行&#xff0c;当瘫痪患者通过"脑控"重新站立行走&#xff0c;这些曾只存在于科幻电影的场景&#xff0c;如今正通过脑机接口技术变为现实。作为"十四五"规划中重点发展的前沿科技&#xff0c;我国脑机接口…...

笔记,麦克风的灵敏度

麦克风的“灵敏度&#xff08;Sensitivity&#xff09;”决定了它捕捉声音细节的能力。想象麦克风是一只有耳朵的生物。高灵敏度麦克风像长着“超级顺风耳”的精灵&#xff0c;能听见花瓣飘落的声音、远处树叶的沙沙声&#xff0c;甚至你心跳的微弱震动。适合录音棚里捕捉歌手的…...

国产linux系统(银河麒麟,统信uos)使用 PageOffice 在线打开Word文件,并用前端对话框实现填空填表

不管是政府机关、公司企业&#xff0c;还是金融行业、教育行业等单位&#xff0c;在办公过程中都经常需要填写各种文书和表格&#xff0c;比如通知、报告、登记表、计划表、申请表等。这些文书和表格往往是用Word文件制作的模板&#xff0c;比方说一个通知模板中经常会有“关于…...

AKS 支持 Kata Container容器沙盒 -预览阶段

您准备好提升您的云和 DevOps 技能了吗&#xff1f; &#x1f425;《云原生devops》专门为您打造&#xff0c;我们精心打造的数十篇文章库&#xff0c;这些文章涵盖了 Azure、AWS 和 DevOps 方法论的众多重要主题。无论您是希望精进专业知识的资深专业人士&#xff0c;还是渴望…...

Ubuntu通过源码编译方式单独安装python3.12

1、安装依赖 sudo apt-get install zlib1g sudo apt-get install zlib1g-dev sudo apt-get install openssl sudo apt-get install libssl-dev2、编译源码并安装 wget https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tar.xz tar -xvf Python-3.12.0.tar.xz cd Pyth…...

【某OTA网站】phantom-token 1004

新版1004 phantom-token 请求头中包含phantom-token 定位到 window.signature 熟悉的vmp 和xhs一样 最新环境检测点 最新检测 canvas 下的 toDataURL方法较严 过程中 会用setAttribute给canvas 设置width height 从而使toDataURL返回不同的值 如果写死toDataURL的返回值…...

游戏引擎学习第266天:添加顶部时钟概览视图。

简要讨论使用第三方调试工具或在多个项目中复用自己的调试工具 今天的工作主要是在提升调试界面的可用性和美观性。昨天已经整理了布局代码&#xff0c;今天的目标是继续优化调试界面&#xff0c;使其更易用。我们已经为调试工具添加了许多新功能&#xff0c;并且在实现过程中…...

霸王茶姬微信小程序自动化签到系统完整实现解析

霸王茶姬微信小程序自动化签到系统完整实现解析 技术栈&#xff1a;Node.js 微信小程序API MD5动态签名 一、脚本全景架构 功能模块图 #mermaid-svg-0vx5W2xo0IZWn6mH {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-s…...

AI与自然语言处理(NLP):从BERT到GPT的演进

AI与自然语言处理&#xff08;NLP&#xff09;&#xff1a;从BERT到GPT的演进 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 AI与自然语言处理&#xff08;NLP&#xff09;&#xff1a;从BERT到GPT的演进摘要引言…...