Nacos+LoadBalancer实现服务注册与发现

目录

一、相关文章

二、兼容说明

三、服务注册到Nacos

四、服务发现

五、服务分级存储模型

六、查看集群服务

七、LoadBalancer负载均衡 


一、相关文章
二、兼容说明
三、服务注册到Nacos

1、父工程cloud-demo3.0引入依赖

  • SpringCloud及SpringCloudAlibaba需根据SpringBoot参照[版本对照表]:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明

  • dependencyManagement引入依赖版本管理包,其管理的依赖引入不需要再指定版本

  • 查看管理依赖版本[spring-cloud-dependencies]:https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies/2023.0.1

  • 查看管理依赖版本[spring-cloud-alibaba-dependencies]:https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-alibaba-dependencies/2023.0.0.0-RC1

dependencyManagement {  
	imports { mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:2023.0.0.0-RC1" }  
	imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:2023.0.1" }  
}  
  
dependencies {  
	//nacos  
	implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery'  
	  
	//springcloud2021开始,使用loadbalancer处理客户端负载均衡  
	implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer'
}

 2、子工程application.yml配置

spring:  
	application:  
		name: order-service  
	cloud:  
		nacos:  
			# nacos 服务端地址  
			server-addr: 192.168.10.104:10001  
			discovery:  
				# 命名空间ID,需在注册中心创建再指定
				namespace: 44480e91-8290-43e4-9129-2d2d42ecd30a  
				# 配置集群名称,也就是机房位置,如:HZ,杭州  
				cluster-name: HZ  
				# nacos登录  
				username: nacos  
				password: nacos
				# 是否是临时实例,临时实例心跳不正常会被剔除,非临时实例则不会被剔除
				ephemeral: false

3、临时实例与非临时实例区别:参考[[Nacos和Eureka对比]]中Nacos与Eureka的区别 

4、 非临时实例必须调api才能删除,否则对应工程改为临时实例启动不了

### user-删除nacos注册中心user-service服务  
DELETE http://127.0.0.1:10001/nacos/v2/ns/instance?serviceName=user-service&ip=192.168.10.104&port=8083&namespaceId=44480e91-8290-43e4-9129-2d2d42ecd30a&clusterName=HZ&ephemeral=false&groupName=DEFAULT_GROUP  
Content-Type: application/x-www-form-urlencoded

5、在Nacos服务端创建namespace命名空间

  • namespace用来做环境隔离,如生产环境(prod)、开发环境(dev)

  • 每个namespace都有唯一id

  • 不同namespace下的服务不可见,prod的服务不能请求到dev去

6、启动多个user-service,参考idea中同服务启动多个-优快云博客

四、服务发现

1、在OrderApplication类创建RestTemplate

@Bean  
@LoadBalanced  //添加使用负载均衡注解
RestTemplate restTemplate() {  
	return new RestTemplate();  
}

2、服务远程调用

//示例:在order服根据用户ID拉取user服用户信息
@Override  
public Order getOrderById(Long orderId) {  
	//获取订单信息  
	Order order = orderMapper.getOrderById(orderId);  
	  
	//根据订单用户ID获取用户信息,通过host:port拼接请求路径
	//String url = "http://localhost:8083/user/" + order.getUserId();  
	
	//eureka方式:通过user-service服务名拼接请求路径
	String url = "http://user-service/user/" + order.getUserId();  
	
	//执行远程调用
	User user = restTemplate.getForObject(url, User.class);  
	order.setUser(user);  
	  
	return order;  
}
五、服务分级存储模型
# 服务分级存储模型
一级是服务,例如user-service
二级是集群,例如杭州,上海
三级是实例,例如杭州机房的某台部署了user-service的服务器

# 配置集群
spring.cloud.nacos.discovery.cluster-name: HZ

 

六、查看集群服务

七、LoadBalancer负载均衡 

1、默认规则,详细分析可参考:https://blog.youkuaiyun.com/BASK2312/article/details/129025006

默认提供了三种不同的负载均衡器:

  • RandomLoadBalancer(随机负载均衡器)、

  • RoundRobinLoadBalancer(轮询负载均衡器)、

  • NacosLoadBalancer(同集群优先调用均衡器)

2、指定使用同集群优先调用策略

  • 创建一个类CustomLoadBalancerConfiguration

  • OrderApplication加注解@LoadBalanced、@LoadBalancerClients

/**  
* Spring Cloud LoadBalancer替代Ribbon实现 随机/轮询/同集群优先调用 方式负载均衡策略配置  
*/  
public class CustomLoadBalancerConfiguration {  
	// Nacos配置属性  
	@Resource  
	private NacosDiscoveryProperties nacosDiscoveryProperties;  
	  
	/**  
	* 自定义负载均衡策略(随机/轮训/同集群优先调用)  
	*  
	* @return ReactorLoadBalancer  
	*/  
	@Bean  
	ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment, LoadBalancerClientFactory factory) {  
		String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); //return new NacosSameClusterWeightedRule(factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);  
		//同集群优先调用,只有Nacos有,Eureka没有  
		return new NacosLoadBalancer(factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name, nacosDiscoveryProperties);  
		  
		//随机  
		//return new RandomLoadBalancer(factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);  
		  
		//轮询  
		//return new RoundRobinLoadBalancer(factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);  
	}  
}
@LoadBalancerClients(defaultConfiguration= CustomLoadBalancerConfiguration.class)  
@SpringBootApplication  
public class OrderApplication {  
	public static void main(String[] args) {  
		SpringApplication.run(OrderApplication.class, args);  
	}  
	  
	@Bean  
	@LoadBalanced  //该注解表示使用负载均衡
	RestTemplate restTemplate() {  
		return new RestTemplate();  
	}  
}

 3、根据权重负载均衡(权重值在0-1之间)

实际部署中会出现这样的场景:
服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。

设为0表示后续不会调用,已发生的调用正常执行
设为0.1表示10个请求只有1个请求到8081

同集群两个都为0.1,另一集群为1,设置了同集群优先调用规则,也只调用0.1集群里的服务

<think>我们正在处理用户的问题:在Spring Cloud Gateway 2021Nacos的环境中,如何动态刷新负载均衡配置或实现服务实例的动态更新。 首先,我们需要明确几个关键点: 1. Spring Cloud Gateway 2021版本对应的是Spring Cloud 2021.0.x(例如2021.0.3)。 2. Nacos作为服务发现和配置中心。 3. 动态刷新的目标:负载均衡配置(例如负载均衡策略)和服务实例列表(即服务发现)。 在Spring Cloud Gateway中,负载均衡通常由Spring Cloud LoadBalancer(SC LoadBalancer)处理,它是Netflix Ribbon的替代品。在2021.0.x版本中,默认使用SC LoadBalancer。 要实现动态更新,我们需要考虑两个方面: - 服务实例列表的动态更新:当Nacos中的服务实例发生变化(上线、下线)时,Gateway如何及时感知并更新路由时的可用实例。 - 负载均衡配置的动态更新:例如更改负载均衡策略(如从轮询改为随机)而不重启网关。 ### 一、服务实例列表的动态更新 Spring Cloud Gateway通过Nacos服务发现客户端(spring-cloud-starter-alibaba-nacos-discovery)获取服务实例。Nacos客户端会定期从Nacos服务器拉取服务列表(默认间隔约10秒),同时Nacos服务器也会在服务变化时主动推送更新(通过UDP,但可能存在丢包,所以客户端也有定时拉取作为保障)。 在Spring Cloud Gateway中,我们使用`ReactiveLoadBalancer`来获取服务实例。默认情况下,`ReactiveLoadBalancer`会缓存服务实例列表,并定期更新(默认缓存时间约为35秒)。因此,从服务实例变化到Gateway感知到变化可能会有延迟。 我们可以通过调整缓存刷新时间来提高更新频率。在`application.yml`中配置: ```yaml spring: cloud: loadbalancer: cache: ttl: 5s # 设置缓存过期时间为5秒,默认是35秒 ``` 这样,负载均衡器会每5秒重新加载一次服务实例列表。 ### 二、负载均衡配置的动态更新 负载均衡配置(如策略选择)通常是在配置文件中定义的,例如: ```yaml spring: cloud: gateway: routes: - id: my_route uri: lb://my-service predicates: - Path=/my-service/** filters: - StripPrefix=1 loadbalancer: configurations: default # 可以指定负载均衡策略,例如轮询、随机等 ``` 但是,如果我们想要在运行时动态更改负载均衡策略,我们需要利用Spring Cloud的配置刷新机制。Nacos Config可以实现配置的动态刷新。 步骤: 1. 将负载均衡配置放在Nacos配置中心(例如一个Data Id为`gateway-loadbalancer.yml`的配置)。 2. 在Gateway应用中添加Nacos Config依赖和配置。 3. 使用`@RefreshScope`或配置刷新机制。 然而,需要注意的是,Spring Cloud LoadBalancer的配置(如`spring.cloud.loadbalancer.configurations`)在启动时就被加载到上下文中,目前(2021.0.x)并不支持动态刷新这些配置。也就是说,即使我们通过Nacos Config动态更改了配置,也不会立即生效。 ### 替代方案:自定义LoadBalancer配置 我们可以通过自定义`ReactiveLoadBalancer`来实现动态策略切换。基本思路: 1. 定义一个自定义的`LoadBalancer`配置类,它可以根据外部配置(例如从Nacos Config获取的配置)来创建不同的负载均衡策略。 2. 使用`@RefreshScope`结合`@Bean`来重新创建负载均衡器实例,当配置刷新时。 具体步骤: #### 1. 添加依赖 确保Gateway项目中包含以下依赖: ```xml <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> ``` #### 2. 创建自定义LoadBalancer配置 创建一个自定义的负载均衡配置类,例如: ```java import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients; 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.context.annotation.Configuration; import org.springframework.core.env.Environment; @Configuration @LoadBalancerClients(defaultConfiguration = CustomLoadBalancerConfiguration.class) public class CustomLoadBalancerConfiguration { @Bean @RefreshScope // 使这个bean可以刷新 public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) { String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); // 从配置中获取负载均衡策略,例如:spring.cloud.loadbalancer.[servicename].strategy,如果没有则使用默认策略 String strategy = environment.getProperty("spring.cloud.loadbalancer." + name + ".strategy", "round_robin"); ServiceInstanceListSupplier supplier = loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class); if ("random".equals(strategy)) { return new RandomLoadBalancer(supplier, name); } else if ("round_robin".equals(strategy)) { return new RoundRobinLoadBalancer(supplier, name); } else { // 默认使用轮询 return new RoundRobinLoadBalancer(supplier, name); } } } ``` 注意:上面的`RandomLoadBalancer`和`RoundRobinLoadBalancer`需要自己实现(或者使用Spring Cloud LoadBalancer提供的,但注意Spring Cloud LoadBalancer默认提供了`RoundRobinLoadBalancer`,随机策略需要自己实现)。 #### 3. 实现随机负载均衡器 Spring Cloud LoadBalancer没有提供随机的实现,我们可以自己写一个: ```java import reactor.core.publisher.Mono; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer; import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; import java.util.List; import java.util.Random; public class RandomLoadBalancer implements ReactorLoadBalancer<ServiceInstance> { private final String serviceId; private final ServiceInstanceListSupplier supplier; private final Random random; public RandomLoadBalancer(ServiceInstanceListSupplier supplier, String serviceId) { this.serviceId = serviceId; this.supplier = supplier; this.random = new Random(); } @Override public Mono<Response<ServiceInstance>> choose(Request request) { return supplier.get().next().map(instances -> { List<ServiceInstance> instanceList = instances.getInstances(); if (instanceList.isEmpty()) { return new EmptyResponse(); } int index = random.nextInt(instanceList.size()); ServiceInstance instance = instanceList.get(index); return new DefaultResponse(instance); }); } } ``` #### 4. 配置Nacos Config动态刷新 在`bootstrap.yml`(或`application.yml`)中配置Nacos Config: ```yaml spring: application: name: gateway-service cloud: nacos: discovery: server-addr: ${NACOS_HOST:127.0.0.1}:${NACOS_PORT:8848} config: server-addr: ${NACOS_HOST:127.0.0.1}:${NACOS_PORT:8848} file-extension: yaml # 配置动态刷新 refresh-enabled: true # 指定要加载的配置 extension-configs: - data-id: gateway-loadbalancer.yml group: DEFAULT_GROUP refresh: true ``` 在Nacos配置中心创建`gateway-loadbalancer.yml`,内容可以是: ```yaml spring: cloud: loadbalancer: my-service: # 服务名 strategy: random # 或者 round_robin ``` #### 5. 测试 当我们更改Nacos中`gateway-loadbalancer.yml`的配置(例如将`my-service`的策略从`round_robin`改为`random`)时,由于我们在`ReactorLoadBalancer`的Bean上加了`@RefreshScope`,Spring Cloud会销毁这个Bean并重新创建,从而加载新的策略。 ### 注意事项 1. 动态刷新负载均衡策略可能会带来一些性能开销,因为每次刷新都会重新创建负载均衡器。 2. 服务实例列表的动态更新通过调整`spring.cloud.loadbalancer.cache.ttl`来控制,但要注意不要设置得太小,以免增加Nacos服务器的压力。 3. 确保Nacos配置的刷新能够正确触发。可以通过`/actuator/refresh`端点(需要actuator依赖)手动刷新,或者等待Nacos Config的自动刷新(默认间隔5秒)。 ### 总结 在Spring Cloud Gateway 2021Nacos的环境中,实现负载均衡配置和服务实例的动态更新需要: - 通过调整`spring.cloud.loadbalancer.cache.ttl`来加快服务实例列表的更新。 - 通过自定义`ReactiveLoadBalancer`并结合Nacos Config的动态刷新机制,实现负载均衡策略的动态更新。 这样,我们就可以在不重启网关的情况下,动态调整负载均衡策略,并快速获取最新的服务实例列表。 ### 相关问题 1. 如何监控Spring Cloud Gateway中负载均衡器的状态? 2. 在Spring Cloud Gateway中,如何实现自定义的负载均衡算法? 3. Nacos配置动态刷新的原理是什么?</think>### Spring Cloud Gateway 2021 动态刷新负载均衡配置(Nacos环境) 在 Spring Cloud Gateway 2021.x(对应 Spring Cloud 2021.0.x)中,结合 Nacos 实现负载均衡配置和服务实例的动态更新,需要配置以下关键组件: #### 一、核心配置步骤 1. **添加必要依赖** (`pom.xml`) ```xml <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> <!-- 替换Ribbon --> </dependency> ``` 2. **启用动态刷新** (`bootstrap.yml`) ```yaml spring: application: name: api-gateway cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: public # 可选命名空间 config: server-addr: 127.0.0.1:8848 refresh-enabled: true # 开启配置自动刷新 extension-configs: # 动态配置源 - data-id: gateway-routes.yml group: DEFAULT_GROUP refresh: true # 关键:允许动态刷新 - data-id: loadbalancer-config.yml group: DEFAULT_GROUP refresh: true ``` 3. **Nacos 负载均衡配置** (`loadbalancer-config.yml`) ```yaml spring: cloud: loadbalancer: cache: ttl: 5s # 缩短实例缓存时间(默认35s) configurations: round-robin # 负载均衡策略 ``` 4. **动态路由配置** (`gateway-routes.yml`) ```yaml spring: cloud: gateway: routes: - id: user-service uri: lb://user-service # lb://启用负载均衡 predicates: - Path=/api/users/** ``` #### 二、实现动态更新机制 1. **服务实例自动更新** Nacos 客户端默认每 10 秒主动拉取服务列表,服务变更时通过 UDP 推送更新。Gateway 通过 `CacheManager` 控制刷新频率: ```yaml spring: cloud: loadbalancer: cache: ttl: 3s # 建议3-5秒(生产环境平衡性能实时性) ``` 2. **负载均衡策略热更新** 创建自定义 `LoadBalancer` 配置类: ```java @Configuration @RefreshScope // 启用配置刷新 public class LoadBalancerConfig { @Bean @RefreshScope public ReactorLoadBalancer<ServiceInstance> customLoadBalancer( Environment env, LoadBalancerClientFactory factory) { String serviceId = env.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); return new RoundRobinLoadBalancer( // 可从Nacos配置动态读取策略 factory.getLazyProvider(serviceId, ServiceInstanceListSupplier.class), serviceId ); } } ``` 3. **监听配置变更事件** 在需要即时响应的场景,添加事件监听器: ```java @Component public class NacosRefreshListener { @EventListener public void handleRefresh(RefreshScopeRefreshedEvent event) { // 重新初始化负载均衡器 LoadBalancerCacheManager.evictAll(); } } ``` #### 三、验证动态更新 1. **测试服务实例更新** - 在 Nacos 控制台下线某个服务实例 - 观察 Gateway 日志:`Refreshing ServiceInstance list for service: user-service` - 请求网关验证流量是否转移到健康实例 2. **测试配置更新** - 在 Nacos 修改 `loadbalancer-config.yml`: ```yaml spring: cloud: loadbalancer: configurations: random # 切换为随机策略 ``` - 查看网关日志:`Refreshing LoadBalancer configuration` #### 四、注意事项 1. **性能权衡** 缓存时间 `ttl` 过短会增加 Nacos 压力,建议: - 测试环境:1-3 秒 - 生产环境:5-10 秒 2. **版本兼容性** | 组件 | 推荐版本 | |------|----------| | Spring Cloud | 2021.0.3+ | | Nacos Client | 2.1.0+ | | Spring Cloud Alibaba | 2021.0.4.0+ | 3. **健康检查强化** 在 `application.yml` 添加: ```yaml spring: cloud: nacos: discovery: health-check-enabled: true # 启用健康检查 heart-beat-interval: 5s # 心跳间隔 ``` > **实现原理**:Nacos 配置变更时,通过 `RefreshEvent` 触发 `LoadBalancerCacheManager` 缓存清除,下次请求重新加载最新配置和服务实例[^1]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值