SpringCloud------Ribbon特性脱离Eureka做负载均衡

本文探讨了在微服务架构中不使用Eureka服务发现的情况,介绍了如何通过直接配置服务实例列表和自定义负载均衡策略来实现服务间的调用。文中详细展示了在Spring Cloud Ribbon中关闭Eureka功能的具体配置,以及如何使用RestTemplate和LoadBalancerClient进行服务调用。

1、什么情况不需要Eureka服务端,脱离它,直接访问微服务端集群?

???

2、application.yml中关闭Eureka功能

配置文件中没有eureka的zoneDefaultUrl,关闭eureka功能

server:
  port: 80

ribbon:
  eureka:
    enabled: false
  
dept-8001:
  ribbon:
    listOfServers: http://dept-8001.com:8001,http://dept-8002.com:8002,http://dept-8003.com:8003

3、RestConfig中的注解@LoadBalanced去掉

package com.zemel.consumer.config;

import java.nio.charset.Charset;
import java.util.Base64;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestConfig {
	
	@Bean
	public HttpHeaders getHeaders(){
		// 进行一个Http头信息配置
		HttpHeaders headers = new HttpHeaders();
		String auth = "wendy:wendy";
		byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII")));
		// 加密字符串要有空格
		String authHeader = "Basic " + new String(encodedAuth);
		
		headers.set("Authorization", authHeader);
		return headers;
	}

	@Bean
//	@LoadBalanced
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}

}

4、MyBalanceConfig.java

package com.zemel.common;

import org.springframework.context.annotation.Bean;

import com.netflix.loadbalancer.IRule;

// 该类无法被主main扫描到
public class MyLoadBalanceConfig {

	@Bean
	public IRule ribbonRule(){
		
		return new com.netflix.loadbalancer.RandomRule();
	}
}

5、Main启动类

package com.zemel.consumer;

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

/**
 * Hello world!
 *
 */
@SpringBootApplication
public class ConsumerRibbonApp {
	public static void main(String[] args) {
		SpringApplication.run(ConsumerRibbonApp.class, args);
	}
	
	
}

6、控制器

通过LoadBalancerClient类获取到服务的主机名和端口信息

package com.zemel.consumer.controller;

import java.net.URI;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.zemel.common.MyLoadBalanceConfig;
import com.zemel.vo.Dept;

@RestController
@RequestMapping("/consumer/dept")
@RibbonClient(name="dept-8001", configuration=MyLoadBalanceConfig.class)
public class DeptController {
	
	static final String DEPT_REST_TOPIC = "dept-8001";
	
	@Resource
	private RestTemplate restTemplate;
	
	@Autowired
	private LoadBalancerClient client;
	
	@Resource
	private HttpHeaders headers;

	@GetMapping("/get")
	public Object getDept(long id){
		
		ServiceInstance instance = client.choose(DEPT_REST_TOPIC);
		
		System.out.println("host="+instance.getHost()+"--port:"+instance.getPort() + "--serviceId:"+instance.getServiceId()
		+ "  --uri:" + instance.getUri());
		
		Dept dept = null;
		
		URI deptUri = URI.create(String.format("http://%s:%s/dept/get/"+id, instance.getHost(),instance.getPort()));
		
//		return dept; 
		return this.restTemplate.exchange(deptUri, HttpMethod.GET, new HttpEntity(headers), Dept.class);
		
//		return this.restTemplate.exchange(DEPT_GET_URL+id, HttpMethod.GET, new HttpEntity(headers), Dept.class);
//		return this.restTemplate.getForEntity(DEPT_GET_URL+id, Dept.class);
	}
	
	/*@GetMapping("/list")
	public Object list(){
		return this.restTemplate.exchange(DEPT_LIST_URL, HttpMethod.GET, new HttpEntity(headers), List.class);
//		return this.restTemplate.getForObject(DEPT_LIST_URL, List.class);
	}
	
	@GetMapping("/add")
	public Object add(Dept dept){
		return this.restTemplate.exchange(DEPT_ADD_URL, HttpMethod.POST, new HttpEntity(dept,headers), Boolean.class);
//		return this.restTemplate.postForObject(DEPT_ADD_URL, dept, Boolean.class);
	}*/
}

 

 

 

 

 

 

 

<think> 我们正在讨论Spring Cloud Ribbon的警告信息,特别是关于RibbonLoadBalancerClient被弃用,并建议使用BlockingLoadBalancerClient的问题。根据用户提供的信息,我们可以总结以下几点: 1. 引用[1]介绍了AbstractLoadBalancer,它是Ribbon负载均衡器的抽象基类,包含选择服务器、获取服务器列表和获取负载均衡统计信息的方法。 2. 引用[2]提到了脱离Eureka使用Ribbon的方式,通过LoadBalancerClient直接选择服务实例。 3. 引用[3]指出Spring Cloud整合了Netflix的开源项目,包括Ribbon。 4. 引用[4]提到了Eureka的自我保护机制可能导致服务实例状态不准确。 用户的问题:在Spring Cloud应用中出现了警告,提示`RibbonLoadBalancerClient`已被弃用,建议使用`BlockingLoadBalancerClient`,并且需要设置`spring.cloud.loadbalancer.ribbon.enabled=false`或移除`spring-cloud-starter-netflix-ribbon`依赖。 ### 警告原因分析 自Spring Cloud 2020.0.0(也称为Ilford)版本开始,Spring Cloud移除了对Netflix Ribbon的默认支持,转而使用Spring Cloud LoadBalancer作为默认的负载均衡器。因此,当项目中还存在Ribbon依赖时,系统会发出警告,提示`RibbonLoadBalancerClient`已被弃用。 ### 解决方案 #### 方法一:移除Ribbon依赖,使用Spring Cloud LoadBalancer 1. **移除Ribbon依赖**:在项目的构建文件(如Maven的pom.xml或Gradle的build.gradle)中,移除`spring-cloud-starter-netflix-ribbon`依赖。 2. **添加Spring Cloud LoadBalancer依赖**:如果尚未包含,确保添加了Spring Cloud LoadBalancer的依赖(通常包含在`spring-cloud-starter-loadbalancer`中)。 3. **配置调整**:在`application.properties`或`application.yml`中,无需设置`spring.cloud.loadbalancer.ribbon.enabled`,因为移除了Ribbon后,自然使用Spring Cloud LoadBalancer。 4. **代码调整**:如果代码中直接使用了`RibbonLoadBalancerClient`,需要替换为`BlockingLoadBalancerClient`(同步)或`ReactiveLoadBalancer`(异步,适用于WebFlux)。 示例代码替换: ```java // 弃用的方式 @Autowired private RibbonLoadBalancerClient loadBalancerClient; public void doSomething() { ServiceInstance instance = loadBalancerClient.choose("service-name"); // ... } // 替换为BlockingLoadBalancerClient @Autowired private LoadBalancerClientFactory loadBalancerClientFactory; public void doSomething() { BlockingLoadBalancerClient loadBalancerClient = new BlockingLoadBalancerClient( loadBalancerClientFactory); ServiceInstance instance = loadBalancerClient.choose("service-name"); // ... } ``` 或者更简洁地使用`LoadBalancerClient`(接口),但注意在自动装配时,实际注入的是`BlockingLoadBalancerClient`: ```java @Autowired private LoadBalancerClient loadBalancerClient; // 现在这个接口的实现是BlockingLoadBalancerClient public void doSomething() { ServiceInstance instance = loadBalancerClient.choose("service-name"); // ... } ``` #### 方法二:暂时保留Ribbon(不推荐) 如果由于某些原因暂时无法移除Ribbon依赖,可以通过配置禁用Spring Cloud LoadBalancer而继续使用Ribbon: ```yaml spring: cloud: loadbalancer: ribbon: enabled: true ``` 但是请注意,这只是一个过渡方案,因为Ribbon已经进入维护模式,不再积极开发。 ### 相关问题 1. 如何检测项目中是否仍在使用Ribbon? 2. 使用Spring Cloud LoadBalancer时,如何自定义负载均衡策略? 3. 在微服务架构中,如何实现客户端负载均衡? 4. Spring Cloud LoadBalancer与Ribbon在性能上有哪些差异? ### 注意事项 - 在升级Spring Cloud版本时,注意查看官方迁移指南,特别是从Hoxton版本升级到2020.x及以上版本时,负载均衡机制发生了变化[^3]。 - 如果使用了Eureka,服务发现和负载均衡是紧密相关的,确保Eureka客户端配置正确[^4]。 [^1]: SpringCloud Ribbon的分析(二) [^2]: springcloud系列9——Ribbon脱离Eureka使用 [^3]: 编码实现Spring Cloud微服务负载均衡调用(eurekaribbon) [^4]: Spring Cloud Eureka自我保护机制(服务无法剔除) </think> ### Spring Cloud RibbonLoadBalancerClient 警告解读与解决方案 #### 警告原因分析 警告信息提示使用 `BlockingLoadBalancerClient` 替代 `RibbonLoadBalancerClient`,根本原因是 Spring Cloud 2020.0.0(Ilford)版本后**移除了对 Ribbon 的默认支持**: 1. **Spring Cloud 架构演进** Spring Cloud 团队逐步淘汰 Netflix 组件(如 Ribbon),转向更通用的 `Spring Cloud LoadBalancer` 作为默认负载均衡器[^3] 2. **核心差异** ```mermaid graph LR A[负载均衡客户端] --> B[RibbonLoadBalancerClient] A --> C[BlockingLoadBalancerClient] B --> D[依赖Netflix Ribbon] C --> E[基于Spring Cloud LoadBalancer] E --> F[支持响应式编程] E --> G[无第三方依赖] ``` #### 解决方法 按照推荐顺序实施: ##### 方案一:启用新负载均衡器(推荐) 1. **添加依赖** 在 `pom.xml` 中引入新组件: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> ``` 2. **禁用 Ribbon** 在 `application.yml` 配置: ```yaml spring: cloud: loadbalancer: ribbon: enabled: false # 关键配置[^1] ``` 3. **代码迁移** 替换原有的 Ribbon 调用方式: ```java // 废弃方式 @Autowired private RibbonLoadBalancerClient loadBalancerClient; // 新方式 @Autowired private LoadBalancerClient loadBalancerClient; // 自动注入Blocking实现 public void callService() { ServiceInstance instance = loadBalancerClient.choose("service-name"); URI uri = instance.getUri(); // 执行服务调用... } ``` ##### 方案二:强制启用 Ribbon(临时方案) 若需暂时保留 Ribbon: ```yaml spring: cloud: loadbalancer: ribbon: enabled: true # 强制启用(不推荐) ``` #### 架构升级建议 1. **负载均衡器选择策略** | 特性 | RibbonLoadBalancerClient | BlockingLoadBalancerClient | |-----------------------|--------------------------|----------------------------| | 响应式支持 | ❌ | ✔️ | | 健康检查机制 | 基础实现 | 集成Spring Boot Actuator | | 自定义策略扩展性 | 中等 | 高 | | 未来版本兼容性 | 逐步淘汰 | 官方维护 | 2. **服务发现注意事项** 使用新负载均衡器时需确保: - Eureka 客户端正确注册服务(检查 `@EnableDiscoveryClient`) - 关闭自我保护机制避免幽灵服务[^4]: ```yaml eureka: server: enable-self-preservation: false ``` #### 验证步骤 1. 启动时检查日志: ``` LoadBalancerClient implementation: BlockingLoadBalancerClient ``` 2. 通过 Actuator 端点验证: ```bash curl http://localhost:8080/actuator/serviceregistry ``` ### 相关问题 1. 如何为 `BlockingLoadBalancerClient` 实现自定义负载均衡策略? 2. 在混合使用 Eureka 和 Nacos 时,负载均衡器应如何配置? 3. Spring Cloud LoadBalancer 如何实现服务健康检查? 4. 响应式编程场景下应该使用哪种负载均衡客户端? > 提示:升级后若出现服务选择异常,可通过 `@LoadBalancerClient(configuration=MyConfig.class)` 注解实现策略定制化[^2]。 [^1]: SpringCloud Ribbon的分析(二) [^2]: springcloud系列9——Ribbon脱离Eureka使用 [^3]: 编码实现Spring Cloud微服务负载均衡调用(eurekaribbon) [^4]: Spring Cloud Eureka自我保护机制(服务无法剔除)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值