Spring Cloud LoadBalancer 原理与实践
背景
当前我们的微服务架构基于Spring Cloud Alibaba体系,通过定制NacosRule实现了跨集群访问和灰度发布功能。但随着Spring Cloud与Nacos版本升级,官方已弃用Ribbon转向LoadBalancer,这要求我们完成以下技术升级:
- 负载均衡机制迁移:将原有Ribbon规则适配到LoadBalancer
- 功能继承保障:保持跨集群路由和灰度能力
- 技术风险控制:深入理解底层机制以提升问题排查效率
技术选型对比
| 特性 | Ribbon | LoadBalancer |
|---|---|---|
| 维护状态 | 停止更新 | 官方维护 |
| 响应式支持 | 不支持 | 原生支持 |
| 配置灵活性 | XML/注解 | 全Java配置 |
| 扩展性 | 中等 | 高 |
| 服务发现集成 | 需要适配 | 深度整合 |
负载均衡
什么是负载均衡?简单来说,负载均衡就是将网络流量(负载)分摊到不同的网络服务器(可以平均分配,也可以不平均),系统就可以实现服务的水平横向扩展。
服务端负载均衡
服务器端负载均衡指的是存放在服务器端的负载均衡器,例如 Nginx、HAProxy、F5 等。

客户端负载均衡
客户端负载均衡指的是嵌套在客户端的负载均衡器,例如 Ribbon、Loadbalancer。

Spring cloud loadbalancer
在介绍loadbalancer之前,如果让你来设计一个负载均衡组件,你会怎么设计?
我们可能需要考虑以下这几个问题:
- 如何获取服务器列表?
- 服务器列表发生变更如何监听同步?
- 如何将客户端请求进行拦截然后选择服务器进行转发?
- 如何将负载进行分摊?
带着这些问题,我们来深入了解Spring Cloud LoadBalancer的实现机制。
服务器列表获取
ServiceInstanceListSupplier
public interface ServiceInstanceListSupplierextends Supplier<Flux<List<ServiceInstance>>> {// 服务idString getServiceId();// 构造器static ServiceInstanceListSupplierBuilder builder() {return new ServiceInstanceListSupplierBuilder();}//用于创建一个 固定的 ServiceInstanceListSupplier(实例列表不会变)。//允许从 Spring Environment 读取配置来构造 FixedServiceInstanceListSupplier。static FixedServiceInstanceListSupplier.Builder fixed(Environment environment) {return new FixedServiceInstanceListSupplier.Builder(environment);}//直接返回 serviceId 对应的 FixedServiceInstanceListSupplier。static FixedServiceInstanceListSupplier.SimpleBuilder fixed(String serviceId) {return new FixedServiceInstanceListSupplier.SimpleBuilder(serviceId);}//实现 ServiceInstanceListSupplier,用于返回一个固定的实例列表,不会动态更新。//适用于测试环境或者静态服务发现场景。class FixedServiceInstanceListSupplier implements ServiceInstanceListSupplier {private final String serviceId;private List<ServiceInstance> instances;@Deprecatedpublic static Builder with(Environment env) {return new Builder(env);}//构造 FixedServiceInstanceListSupplier,接受服务 ID 和实例列表。private FixedServiceInstanceListSupplier(String serviceId,List<ServiceInstance> instances) {this.serviceId = serviceId;this.instances = instances;}//返回当前 FixedServiceInstanceListSupplier 所管理的 serviceId。@Overridepublic String getServiceId() {return serviceId;}//返回固定的实例列表,不会随 Nacos 或 Eureka 变化。@Overridepublic Flux<List<ServiceInstance>> get() {return Flux.just(instances);}}
该接口提供符合条件的实例列表,并提供了 builder 方法返回 ServiceInstanceListSupplierBuilder 实例用来构造 ServiceInstanceListSupplier
同时FixedServiceInstanceListSupplier,它返回固定的服务实例列表。它主要用于
- ** 测试负载均衡逻辑**(在不依赖 Nacos/Eureka 的情况下提供固定实例)。**
- 静态配置服务实例(比如在某些特殊场景下,不使用注册中心,而是固定 IP+端口)。
示例
List<ServiceInstance> instances = List.of(new DefaultServiceInstance("id1", "my-service", "127.0.0.1", 8080, false),new DefaultServiceInstance("id2", "my-service", "127.0.0.2", 8081, false)
);ServiceInstanceListSupplier supplier = ServiceInstanceListSupplier.fixed("my-service").withInstances(instances).build();// 获取实例列表
supplier.get().subscribe(list -> list.forEach(instance ->System.out.println(instance.getHost() + ":" + instance.getPort())
));
整个 ServiceInstanceListSupplier 的实现类都是 rx式 编程风格,但核心逻辑不难看懂,下面就贴出几个实现类简单了解下
DiscoveryClientServiceInstanceListSupplier
...
// 普通mvc项目获取获取实例列表
public DiscoveryClientServiceInstanceListSupplier(DiscoveryClient delegate,Environment environment) {this.serviceId = environment.getProperty(PROPERTY_NAME);resolveTimeout(environment);this.serviceInstances = Flux.defer(() -> Mono.fromCallable(() -> delegate.getInstances(serviceId))).timeout(timeout, Flux.defer(() -> {logTimeout();return Flux.just(new ArrayList<>());}), Schedulers.boundedElastic()).onErrorResume(error -> {logException(error);return Flux.just(new ArrayList<>());});}// webflux项目获取获取实例列表public DiscoveryClientServiceInstanceListSupplier(ReactiveDiscoveryClient delegate,Environment environment) {...}
...
主要逻辑在构造方法中,等价于 this.serviceInstances = discoveryClient.getInstances(serviceId),不难理解:从注册中心拉去实例列表
DelegatingServiceInstanceListSupplier
public abstract class DelegatingServiceInstanceListSupplierimplements ServiceInstanceListSupplier, InitializingBean, DisposableBean {protected final ServiceInstanceListSupplier delegate;public DelegatingServiceInstanceListSupplier(ServiceInstanceListSupplier delegate) {Assert.notNull(delegate, "delegate may not be null");this.delegate = delegate;}...
装饰层,内嵌一个代理对象,一般就是 DiscoveryClientServiceInstanceListSupplier 来获取实例列表,装饰逻辑就是过滤对应的列表
其下面有n个实现子类,暂不贴代码了
主要功能为:
- ZonePreferenceServiceInstanceListSupplier:区域优先选择,优先选择与当前客户端在相同
zone(可用区)的实例,提高访问效率,降低跨区域流量消耗。 - CachingServiceInstanceListSupplier:缓存
ServiceInstanceListSupplier的返回结果,减少注册中心查询次数,提升性能。 - SameInstancePreferenceServiceInstanceListSupplier:尽量路由到之前选中的实例,减少服务间的切换,提高请求一致性。
- HealthCheckServiceInstanceListSupplier:在负载均衡前,过滤掉不健康的服务实例,确保请求不会路由到故障实例。
选择实例以及转发
ReactorLoadBalancer
public interface ReactorLoadBalancer<T> extends ReactiveLoadBalancer<T> {/*** Choose the next server based on the load balancing algorithm.* @param request - an input request* @return - mono of response*/@SuppressWarnings("rawtypes")Mono<Response<T>> choose(Request request);default Mono<Response<T>> choose() {return choose(REQUEST);}}
该接口从 ServiceInstanceListSupplier 返回的实例中选择最终目标,其中也分为普通mvc项目和webflux项目,spring-cloud-loadbalancer 默认只提供了两个实现:
- RandomLoadBalancer:随机选择
- RoundRobinLoadBalancer:轮询
如果不明白这两区别,可以看文章最后的部分
服务装配
LoadBalancerClientConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
public class LoadBalancerClientConfiguration {private static final int REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER = 193827465;//实例选择规则:默认轮询@Bean@ConditionalOnMissingBeanpublic ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,ServiceInstanceListSupplier.class), name);}//WebFlux 环境下的默认 ServiceInstanceListSupplier 配置@Configuration(proxyBeanMethods = false)@ConditionalOnReactiveDiscoveryEnabled@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER)public static class ReactiveSupportConfiguration {@Bean@ConditionalOnBean(ReactiveDiscoveryClient.class)@ConditionalOnMissingBean@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations",havingValue = "default", matchIfMissing = true)public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().build(context);}...}//普通 web 环境下的配置@Configuration(proxyBeanMethods = false)@ConditionalOnBlockingDiscoveryEnabled@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER + 1)public static class BlockingSupportConfiguration {...@Bean@ConditionalOnBean(DiscoveryClient.class)@ConditionalOnMissingBean@ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations",havingValue = "health-check")public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withHealthChecks().build(context);}...}}
现在回过头来看每个 LoadBalancerClient 容器实例下默认注册的配置类 LoadBalancerClientConfiguration,如代码所示:
默认的实例选择规则是 轮询
对应的实例列表获取规则取决于 spring.cloud.loadbalancer.configurations 属性配置
LoadBalancerAutoConfiguration
@Configuration(proxyBeanMethods = false)
@LoadBalancerClients
@EnableConfigurationProperties(LoadBalancerProperties.class)
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,LoadBalancerBeanPostProcessorAutoConfiguration.class,ReactiveLoadBalancerAutoConfiguration.class })
public class LoadBalancerAutoConfiguration {private final ObjectProvider<List<LoadBalancerClientSpecification>> configurations;public LoadBalancerAutoConfiguration(ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {this.configurations = configurations;}@Bean@ConditionalOnMissingBeanpublic LoadBalancerZoneConfig zoneConfig(Environment environment) {return new LoadBalancerZoneConfig(environment.getProperty("spring.cloud.loadbalancer.zone"));}@ConditionalOnMissingBean@Beanpublic LoadBalancerClientFactory loadBalancerClientFactory() {LoadBalancerClientFactory clientFactory = new LoadBalancerClientFactory();clientFactory.setConfigurations(this.configurations.getIfAvailable(Collections::emptyList));return clientFactory;}}
等上述所有实例加载完,最后整体装配
执行最终实例
BlockingLoadBalancerClient
public class BlockingLoadBalancerClient implements LoadBalancerClient {...@Overridepublic <T> T execute(String serviceId, LoadBalancerRequest<T> request)throws IOException {ServiceInstance serviceInstance = choose(serviceId);if (serviceInstance == null) {throw new IllegalStateException("No instances available for " + serviceId);}return execute(serviceId, serviceInstance, request);}//执行request请求@Overridepublic <T> T execute(String serviceId, ServiceInstance serviceInstance,LoadBalancerRequest<T> request) throws IOException {try {return request.apply(serviceInstance);}catch (IOException iOException) {throw iOException;}catch (Exception exception) {ReflectionUtils.rethrowRuntimeException(exception);}return null;}@Overridepublic URI reconstructURI(ServiceInstance serviceInstance, URI original) {return LoadBalancerUriTools.reconstructURI(serviceInstance, original);}@Overridepublic ServiceInstance choose(String serviceId) {//获取 serviceId 容器中的 ReactiveLoadBalancer 实例ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory.getInstance(serviceId);if (loadBalancer == null) {return null;}Response<ServiceInstance> loadBalancerResponse = Mono.from(loadBalancer.choose()).block();if (loadBalancerResponse == null) {return null;}return loadBalancerResponse.getServer();}}
最后回到 BlockingLoadBalancerClient#execute 逻辑(容器中默认装配的 LoadBalancerClient):
逻辑无非就是选择最终的实例来执行请求
底层逻辑就是从隔离好的 容器 中获取对应的 ServiceInstanceListSupplier 和 ReactiveLoadBalancer 来选择实例
实践指南
配置类
- 注册中心维度,相当于每个client端隔离一份配置,都走自己定义的逻辑,通过@LoadBalancerClients注解整合到一份配置类中,具体配置一内部类的形式维护,缺点就是,client端规则发生变化时,需要修改对应配置类
- 通用策略配置,每种策略配置隔离一份,通过@LoadBalancerClients注解整合到一份配置类中,client端选择对应的配置即可,缺点就是,组合会很多,比较复杂,但是好处时,如果发生变更的话,只需要更改@LoadBalancerClients的属性值,拓展性也比较好
注册中心维度
@LoadBalancerClients({@LoadBalancerClient(value = "eureka-client-1", configuration = ClietConfig.EurekaClient1Config.class), @LoadBalancerClient(value = "eureka-client-2", configuration = ClietConfig.EurekaClient2Config.class)
})
public class ClietConfig {//如果这里面的规则发生变化,就得改这里面的东西static class EurekaClient1Config {// ... }//如果这里面的规则发生变化,就得改这里面的东西static class EurekaClient2Config {// ...}
}
通用策略维度
@LoadBalancerClients({@LoadBalancerClient(value = "eureka-client-1", configuration = LoadBalanceConfig.RandomLoadBalancerConfig.class), @LoadBalancerClient(value = "eureka-client-2", configuration = LoadBalanceConfig.ZonePerferServiceListConfig.class)
})
public class LoadBalanceConfig {//这些策略不用更改,一般时通用static class RandomLoadBalancerConfig {// ...}//这些策略不用更改,一般时通用static class HintServiceListConfig {// ... }// ...
}
灰度切入
目前根据loadbalancer提供的类来看,可以实现灰度切入的有两个地方,分别为:
- ReactiveLoadBalancer:选择实例
- ServiceInstanceListSupplier:过滤实例
严格意义上来说,我的理解是灰度功能是来选择示例的,并不是过滤实例的,所以我可能更倾向于通过ReactiveLoadBalancer来实现,实现他的choose方法;
但是这里有个坑是啥?
如果你想在ReactiveLoadBalancer层面实现基于请求头的路由决策,你需要在调用choose方法时传递一些上下文信息。Spring Cloud LoadBalancer中的Request接口可以携带这些信息。然而,Request对象需要在调用choose之前构建,并且Spring Cloud LoadBalancer并没有提供一个内置的方式来根据传入的HTTP请求构建这个Request对象。
不过这个可以通过上下文来传递下来,需要自己来做一些封装
本文暂时不细讲灰度的实现,后续有时间的话,我专门出一篇文章来说
自定义负载策略
通过"选择实例以及转发"章节的介绍,我们可以发现,loadbalancer主要提供了两个默认策略:
- RandomLoadBalancer:随机选择
- RoundRobinLoadBalancer:轮询
同时,他们又是被 @ConditionalOnMissingBean修饰,所以,如果我们想自定义自己的策略规则,我们直接通过 @Configuration和@Bean,注入自己的策略就行,以下是一个简单示例
@Configuration
@LoadBalancerClients(defaultConfiguration = MyBalancerConfiguration.class)
public class MyBalancerConfiguration {/*** 自定义负载均衡器*/@Beanpublic ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new MyLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}
}
其中MyLoadBalancer是我们自定义的规则
@Slf4j
public class MyLoadBalancer implements ReactorServiceInstanceLoadBalancer {private final String serviceId;//服务列表private final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;public MyLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> supplier, String serviceId) {this.serviceId = serviceId;this.serviceInstanceListSupplierProvider = supplier;}@Overridepublic Mono<Response<ServiceInstance>> choose(Request request) {/*** 进行路由选择*/...}
}
拓展
ReactiveLoadBalancer 和ServiceInstanceListSupplier 区别
概念区分
| 组件名称 | 作用 |
|---|---|
ServiceInstanceListSupplier | 负责提供某个服务的所有可用实例列表(获取并缓存服务实例列表)。 |
ReactiveLoadBalancer | 负责基于负载均衡策略,从 ServiceInstanceListSupplier 提供的实例列表中选择一个合适的实例。 |
简单来说:
ServiceInstanceListSupplier负责提供候选实例列表。ReactiveLoadBalancer负责从这些候选实例中挑选一个最终的实例。
核心职责
ServiceInstanceListSupplier
-
主要作用:提供目标服务的可用
ServiceInstance列表。 -
底层实现:它会通过
DiscoveryClient(如 Nacos、Eureka 等)获取服务实例列表,并可能会对实例进行缓存、筛选、排序等操作。 -
接口定义:
public interface ServiceInstanceListSupplier {Flux<List<ServiceInstance>> get(); }- 该接口返回一个
Flux<List<ServiceInstance>>,代表着它是响应式的,能够动态推送服务实例列表更新(比如当 Nacos 服务实例变更时)。 - 其默认实现
DiscoveryClientServiceInstanceListSupplier会基于DiscoveryClient获取实例信息。
- 该接口返回一个
-
可以自定义过滤、排序规则:
-
例如,你可以扩展
ServiceInstanceListSupplier,让它优先返回健康检查通过的实例,或者特定版本的实例。 -
代码示例:
@Component public class MyCustomInstanceSupplier implements ServiceInstanceListSupplier {private final DiscoveryClient discoveryClient;public MyCustomInstanceSupplier(DiscoveryClient discoveryClient) {this.discoveryClient = discoveryClient;}@Overridepublic Flux<List<ServiceInstance>> get() {return Flux.defer(() -> {List<ServiceInstance> instances = discoveryClient.getInstances("my-service");// 自定义筛选逻辑,比如过滤掉某些状态的实例List<ServiceInstance> filteredInstances = instances.stream().filter(instance -> instance.getMetadata().get("status").equals("UP")).collect(Collectors.toList());return Flux.just(filteredInstances);});} }
-
ReactiveLoadBalancer
-
主要作用:根据某种负载均衡算法,从
ServiceInstanceListSupplier提供的实例中挑选一个。 -
底层实现:它的核心方法是:
public interface ReactiveLoadBalancer<T> {Mono<Response<T>> choose(Request request); }choose(Request request): 选择一个具体的ServiceInstance。- 其中
T通常是ServiceInstance,也可以是Response<ServiceInstance>(包含 metadata)。
-
默认实现
RoundRobinLoadBalancer:基于轮询算法选择实例。RandomLoadBalancer:随机选择一个实例。CachingServiceInstanceListSupplier:基于缓存提高性能,避免频繁查询服务列表。
-
示例:自定义
ReactiveLoadBalancer-
例如,你可以自定义负载均衡算法,优先选择 CPU 负载最低的实例:
@Component public class MyCustomLoadBalancer implements ReactiveLoadBalancer<ServiceInstance> {private final ServiceInstanceListSupplier supplier;public MyCustomLoadBalancer(ServiceInstanceListSupplier supplier) {this.supplier = supplier;}@Overridepublic Mono<Response<ServiceInstance>> choose(Request request) {return supplier.get().map(instances -> {// 选择 CPU 负载最低的实例ServiceInstance selectedInstance = instances.stream().min(Comparator.comparing(instance -> getCpuLoad(instance))).orElse(null);return new DefaultResponse(selectedInstance);});}private double getCpuLoad(ServiceInstance instance) {// 这里假设实例 metadata 里包含 cpu_loadreturn Double.parseDouble(instance.getMetadata().getOrDefault("cpu_load", "100"));} }
-
完整负载均衡流程
- 客户端发起请求
- 例如,Spring Cloud Gateway 或 RestTemplate 发起对
my-service的调用。
- 例如,Spring Cloud Gateway 或 RestTemplate 发起对
- 获取可用实例列表
ServiceInstanceListSupplier.get()从注册中心(Nacos、Eureka)获取my-service的所有实例。
- 选择负载均衡策略
ReactiveLoadBalancer.choose(request)使用RoundRobinLoadBalancer或自定义策略,选择一个实例。
- 最终返回一个实例
ReactiveLoadBalancer选出具体的ServiceInstance,并返回给WebClient或RestTemplate进行请求。
示意图:
请求 -> ServiceInstanceListSupplier 获取实例列表 -> ReactiveLoadBalancer 选择实例 -> 返回实例给调用方
总结
| 组件 | 主要作用 | 关键方法 | 关系 |
|---|---|---|---|
ServiceInstanceListSupplier | 提供某个服务的可用实例列表 | Flux<List<ServiceInstance>> get() | 负责获取候选服务实例 |
ReactiveLoadBalancer | 依据负载均衡策略选择具体实例 | Mono<Response<ServiceInstance>> choose(Request request) | 负责选择最终的服务实例 |
ServiceInstanceListSupplier负责从服务发现组件(如 Nacos)获取所有可用实例,可能还会做缓存、排序、过滤。ReactiveLoadBalancer负责根据负载均衡策略(轮询、随机、自定义策略)从ServiceInstanceListSupplier获取的实例中挑选一个最终的实例。ReactiveLoadBalancer依赖ServiceInstanceListSupplier,它无法直接从 Nacos 之类的服务注册中心获取实例,而是必须由ServiceInstanceListSupplier提供候选实例。
相关文章:
Spring Cloud LoadBalancer 原理与实践
背景 当前我们的微服务架构基于Spring Cloud Alibaba体系,通过定制NacosRule实现了跨集群访问和灰度发布功能。但随着Spring Cloud与Nacos版本升级,官方已弃用Ribbon转向LoadBalancer,这要求我们完成以下技术升级: 负载均衡机制…...
Vmware下的openEuler
1.下载openEuler操作系统镜像 https://repo.openeuler.org/openEuler-20.03-LTS/ISO/ 2.在VM新建虚拟机 3.虚拟机联网 我是出现了没有网络,ping不通的问题 参考:https://blog.csdn.net/FHY26828/article/details/140941234 修改文件: 在…...
spring security学习入门指引
学习 Spring Security 可以从以下几个方面逐步深入,结合理论与实践,以下是具体的学习路径建议: 1. 基础准备 • 熟悉 Spring 框架: 先掌握 Spring Core、Spring MVC 和 Spring Boot 的基础,理解依赖注入(D…...
【瞎折腾/Dify】使用docker离线部署Dify
文章目录 说在前面安装Docker(外网)获取Dify源码(外网)拉取docker镜像(外网)导出镜像(内网)导入镜像(内网)运行问题 说在前面 外网操作系统:windows内网操作系统:ubuntu外网docker desktop版本:4.29.0外网docker版本:version 26.0…...
Java EE Web环境安装
Java EE Web环境安装 一、JDK安装与测试(Windows环境) 1. 安装JDK 官网下载:Oracle JDK(选择Windows x64 Installer)双击安装包,按向导完成安装 2. 环境变量配置 右键【此电脑】→【属性】→【高级…...
Node.js中HTTPS模块应用详解
1. HTTPS 模块的概念 HTTPS(Hypertext Transfer Protocol Secure)是 HTTP 的安全版本,通过 SSL/TLS 协议对数据进行加密,确保数据在传输过程中不被窃取或篡改。在 Node.js 中,https 模块提供了创建 HTTPS 服务器和客户…...
我测试了AI搜索:试图替代谷歌搜索
随着人工智能工具的不断进步,探讨它们是否能够取代传统搜索引擎如谷歌,已成为一个引人入胜的话题。 有一点是确定的:并非所有的人工智能都可用。它们需要的主要特性是能够访问互联网以获取最新信息,这就排除了Anthropic的Claude。 人工智能在某些方面可以增强或改进谷歌搜…...
大语言模型基础之‘显存优化‘
上一篇可扩展的训练技术(二)中,我们介绍了零冗余优化器(Zero Redundancy Optimizer, Zero),该技术由DeepSpeed代码库提出,主要用于解决数据并行中的模型冗余技术,即在数据并行训练中,每个GPU上都…...
【Nexus】Maven 私服搭建以及上传自己的Jar包
Nexus 安装 docker run -d -uroot --name nexus3 --restartalways -p 8081:8081 -v /data/nexus-data/blobs:/nexus-data/blobs -v /etc/localtime:/etc/localtime sonatype/nexus3这里也提供一下docker-composer的方法 .env 文件 VERSIONlatest CONTAINER_NAMECONTAINER_N…...
css模拟雷达扫描动画
<div class"radar-scan"><div class"radar-container" /></div> 样式: .radar-scan {background-image: linear-gradient(0deg,transparent 24%,rgba(32, 255, 77, 0.15) 25%,rgba(32, 255, 77, 0.15) 26%,transparent 27%,…...
冠珠瓷砖×郭培“惟质致美”品质主题片上映,讲述高定艺术背后的致美品质故事
168年前,一位英国服装设计师,开创了「高级定制」的先河。时至今日,从服装到各行各业「高级定制」始终代表着对完美的极致追求,成为了行业至高境界的象征。 被誉为“中国高定第一人”,高级定制服装设计师郭培࿰…...
【Java 基础(人话版)】进制转换
进制的简单介绍 整数可以使用四种不同的进制表示方式: 二进制 (Binary):由 0 和 1 组成,满 2 进 1,以 0b 或 0B 开头表示。十进制 (Decimal):由 0-9 组成,满 10 进 1,是最常用的数值表示方式。…...
3DS模拟器使用(pc+安卓)+金手指+存档互传
1、引言 3ds模拟器已经能够在手机端近乎完美模拟了,那么多的3ds游戏,比玩手机游戏舒服多了。 本人是精灵宝可梦的老玩家,从第一世代就一直在玩,刚耍完NDS的第五世代,黑白系列。现在到宝可梦XY了,需要在3d…...
SpaceClaim二次开发(4)
目录 第五章 Storing Custom Data (存储自定义数据) 5.1 文档属性 5.2 自定义属性 5.3 属性传播 第六章 Identifying Objects in ACIS and Parasolid Files(识别ACIS和Parasolid文件中的对象) 6.1 导出期间的标识符 6.2 导入和…...
Leetcode3340:检查平衡字符串
题目描述: 给你一个仅由数字 0 - 9 组成的字符串 num。如果偶数下标处的数字之和等于奇数下标处的数字之和,则认为该数字字符串是一个 平衡字符串。 如果 num 是一个 平衡字符串,则返回 true;否则,返回 false。 代码…...
Java多线程基石—内存模型
Java Memory Model Java内存模型(JMM),定义了线程如何与内存交互及线程间的可见性、有序性和原子性。 JMM屏蔽了各种硬件和操作系统的访问差异,保证Java程序在各种平台下对内存的访问都能保证一致效果。 1 JMM 可见性 一个线程…...
ArcGIS助力水文分析:数据处理、地图制作与流域特征提取
在水文水环境保护中,对于信息的采集、处理和分析是关键步骤。水文水环境及其相关数据均具有空间分布特征,传统的方法难以发挥作用。地理信息系统(GIS)强大的空间数据管理和分析功能,在空间信息处理上有独到的优势&…...
从以太网 II 到 VLAN 和 Jumbo Frame:数据帧格式解读
以太网数据帧是计算机网络通信的基本单位,在不同的应用场景中,它的格式有所不同。根据协议标准和用途,以太网数据帧主要包括以太网 II 帧、IEEE 802.3 帧、IEEE 802.1Q VLAN 帧等七种主要类型。为了更好地理解以太网的通信机制,我…...
X86 RouterOS 7.18 设置笔记六:端口映射(IPv4、IPv6)及回流问题
X86 j4125 4网口小主机折腾笔记五:PVE安装ROS RouterOS X86 RouterOS 7.18 设置笔记一:基础设置 X86 RouterOS 7.18 设置笔记二:网络基础设置(IPV4) X86 RouterOS 7.18 设置笔记三:防火墙设置(IPV4) X86 RouterOS 7.18 设置笔记四…...
将 IPoIB 驱动修改为仅使用 RC 模式
摘要 本文档详细介绍了将 Linux 内核中的 IPoIB(IP over InfiniBand)驱动修改为仅使用 RC(Reliable Connection,可靠连接)模式,并移除所有与 TCP/IP 和以太网相关部分的方法。通过这些修改,可以优化 IPoIB 驱动以适应特定的高性能计算场景,提高数据传输的可靠性和效率…...
热修复框架Tinker与Robust原理剖析
热修复框架Tinker与Robust原理剖析 一、热修复技术概述 1.1 什么是热修复 热修复(Hot Fix)是Android平台上的一种动态修复机制,它允许应用在不重新发布版本的情况下,动态修复线上bug。这种技术对于快速修复线上问题、降低用户流…...
69.Harmonyos NEXT图片预览组件应用实践(二):电商、内容与办公场景
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! Harmonyos NEXT图片预览组件应用实践(二):电商、内容与办公场景 文章目录 Harmonyos NEXT图片预览组件应用实践…...
C题库-判断水仙花数
【数据判断】 问题1:判断水仙花数,水仙花数是指一个三位数,其各位数字的立方和等于该数本身。 方法一: #include<stdio.h>int main(void){int num,Bit,Ten,Hundred;printf("Input a number:");scanf("%d&q…...
31.Harmonyos Next仿uv-ui 组件NumberBox 步进器组件异步操作处理
Harmonyos Next仿uv-ui 组件NumberBox 步进器组件异步操作处理 文章目录 Harmonyos Next仿uv-ui 组件NumberBox 步进器组件异步操作处理1. 组件介绍2. 效果展示3. 异步操作处理3.1 异步初始化3.2 异步值更新 4. 完整示例代码5. 知识点讲解5.1 异步操作基础5.2 异步操作中的状态…...
MIPI电平标准详解
一、MIPI电平的定义与核心特性 MIPI(Mobile Industry Processor Interface) 是由 MIPI联盟 制定的移动设备接口标准,涵盖摄像头(CSI)、显示屏(DSI)、射频(RFFE)等多个领…...
使用位运算实现加法、减法、乘法和除法
使用位运算实现加法、减法、乘法和除法是一个经典的计算机科学问题。位运算通常用于低级程序设计和性能优化中,以下是如何用位运算实现这些基本数学运算。 加法 加法可以通过以下步骤实现: def add(a, b):while b ! 0:# 使用异或得到不考虑进位的加法…...
深入解析Go语言Channel:源码剖析与并发读写机制
文章目录 Channel的内部结构Channel的创建过程有缓冲Channel的并发读写机制同时读写的可能性发送操作的实现接收操作的实现 并发读写的核心机制解析互斥锁保护环形缓冲区等待队列直接传递优化Goroutine调度 实例分析:有缓冲Channel的并发读写性能优化与最佳实践缓冲…...
mac安装python没有环境变量怎么办?zsh: command not found: python
在mac电脑上,下载Python安装包进行安装之后,在终端中,输入python提示: zsh: command not found: python 一、原因分析 首先,这个问题不是因为python没有安装成功的原因,是因为python安装的时候,没有为我们添加环境变量导致的,所以我们只需要,在.zshrc配置文件中加上环…...
使用DeepSeek制作可视化图表和流程图
用DeepSeek来制作可视化图表,搭配python、mermaid、html来实现可视化,我已经测试过好几种场景,都能实现自动化的代码生成,效果还是不错的,流程如下。 统计图表 (搭配Matplotlib来做) Python中的…...
jmeter-sample
jmeter-sample http request:接口测试常用请求参数ParametersBody DataFiles Upload jdbc request配置JDBC Connection Configuration创建JDBC Requst请求 http request:接口测试常用 请求参数 Parameters 常见于get请求,与拼在接口后面是一样的效果:如…...
