Netflix Ribbon简介
Netflix Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。
具体来说,Ribbon是一个客户端负载均衡器,可以在配置文件中列出所有的服务提供方机器,然后Ribbon会自动基于某种规则(如简单轮询、随机连接等)去连接这些机器。同时,Ribbon也提供了一系列完善的配置项,如连接超时、重试等。此外,还可以很容易地使用Ribbon实现自定义的负载均衡算法。
Ribbon属于进程内负载均衡,它只是一个类库,集成于服务消费方进程,消费方通过它来获取到服务提供方的地址。在Netflix的架构中,Ribbon通常与Eureka一起使用,Eureka是一个服务治理组件,用于服务的注册与发现,而Ribbon则负责在多个服务实例之间进行负载均衡。
涉及的模块
- springcloud-eureka-server :18082 ,注册中心
- springcloud-ribbon-server:18091, 18092, provider服务提供者
- springcloud-ribbon-client:18090, consumer服务消费者
springcloud-eureka-server 注册中心
可参考 Springboot集成Eureka实现服务注册中心一节的实现
springcloud-ribbon-server Provider模块
provider没有太多需要注意的事项,只需要注册到任意一个注册中心即可。
pom.xml
依赖版本可参考 springbootSeries 模块中pom.xml文件中的版本定义
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
application.properties配置
spring.profiles.active = dev
spring.application.name=springbootEurekaRibbonServer
server.port=18091
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone = http://127.0.0.1:18082/eureka
application-server2.properties配置
再添加另一个配置,名为application-server2.properties
,主要就是个性一下端口号,配置如下:
#springboot Server
spring.application.name=springbootEurekaRibbonServer
spring.aop.auto=true
spring.aop.proxy-target-class=true
# log4j
logging.config=classpath:log4j2.xml
logging.level.root=INFO
logging.level.org.springframework.web=ERROR
#restful Server
server.port=18092
server.compression.enabled=true
server.compression.mime-types=application/json,application/octet-stream
#swagger
springdoc.api-docs.enabled=true
springdoc.api-docs.path=/api-schema
swagger-config.group = default-group
swagger-config.description= The following is a restful-api list of {} application, and you can browse or test them to determine if they are working as you expect.
swagger-config.version=V1.0
swagger-config.urlPattern=/**
swagger-config.base-package=com.korgs
swagger-config.authorization-key-name=token
swagger-config.wiki = https://korgs.blog.csdn.net/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone = http://127.0.0.1:18082/eureka
SpringbootApplication启动类
注意@GetMapping("/helloworld")
为供测试的服务接口。同时别忘记了@EnableDiscoveryClient
注解,用来注册到Enreka。
@Slf4j
@SpringBootApplication(scanBasePackages = {"com.korgs", "cn.hutool.extra.spring"})
@Configuration
@EnableConfigurationProperties
@ServletComponentScan
@RestController
@EnableDiscoveryClient
public class SpringbootEurekaServerRibbonApplication {
@Value("${server.port}")
private String serverPort;
public static void main(String[] args) {
SpringApplication.run(SpringbootEurekaServerRibbonApplication.class, args);
}
@GetMapping("/helloworld")
public BaseResponse<String> helloWorld(String uuid){
String str = LogGenerator.trackLog()
+ " uuid=" + uuid + " I am busy to handle this request."
+ " serverPort=" + serverPort;
log.info( str );
return BaseResponse.success(str);
}
}
springcloud-ribbon-client Consumer模块
除了注册到注册中心外,负载均衡一般是在consumer端实现的
pom.xml
在springboot3中引入的是spring-cloud-starter-loadbalancer
包来负责负载均衡。依赖版本可参考 springbootSeries 模块中pom.xml文件中的版本定义
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
application.properties配置
service-url.ribbon-service = http://springbootEurekaRibbonServer
,:
- service-url.ribbon-service是一个自定义的key值;
- http://springbootEurekaRibbonServer为
springcloud-ribbon-server
模块向注册中心注册的服务名,一般为spring.application.name
的值,相当于http://localhost:18091。
spring.profiles.active = dev
spring.application.name=springbootEurekaWithRibbonClient
server.port=18090
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone = http://127.0.0.1:18082/eureka
#自定义配置服务端
service-url.ribbon-service = http://springbootEurekaRibbonServer
SpringbootApplication启动类
添加@EnableDiscoveryClient
注解,用来注册到Enreka。
@Slf4j
@SpringBootApplication(scanBasePackages = {"com.korgs", "cn.hutool.extra.spring"})
@Configuration
@EnableConfigurationProperties
@ServletComponentScan
@RestController
@EnableDiscoveryClient
public class SpringbootEurekaClientRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootEurekaClientRibbonApplication.class, args);
}
@GetMapping("/helloworld/{uuid}")
public BaseResponse<String> helloWorld(String uuid){
String str = LogGenerator.trackLog()
+ " uuid=" + uuid + " I am busy to handle this request.";
log.info( str );
return BaseResponse.success(str);
}
}
实现Ribbon-RestTemplate Bean
主要就是添加一个@LoadBalanced
注解
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Controller测试类
@RestController
@RequestMapping("/api/load")
public class LoadBalanceController {
@Autowired
private RestTemplate restTemplate;
@Value("${service-url.ribbon-service}")
private String ribbonServiceUrl;
@GetMapping("/v1/hello-content")
public BaseResponse<String> loadHelloContent(String uuid){
String result = restTemplate.getForObject(ribbonServiceUrl + "/helloworld?uuid={1}", String.class, uuid);
return BaseResponse.success(result);
}
}
源码下载
涉及模块:
- springcloud-eureka-server :18082 ,注册中心
- springcloud-ribbon-server:18091,18092 provider服务提供者
- springcloud-ribbon-client:18090, consumer服务消费者
源码下载:
- 基础框架源码下载
- Springboot集成Netflix-ribbon、Enreka实现负载均衡
源码运行方法:
- 模块详细功能说明和运行测试方法
按上述方法启动后,可以在-
- 注册中心中看到如下界面
- 打开 http://localhost:18090/swagger-ui
依次调用springcloud-ribbon-client
模块的http://localhost:18090/api/load/v1/hello-content?uuid=2222
,观察返回结果中端口号的变化。
Ribbon插件功能详解
全局负载均衡配置
ribbon:
ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
OkToRetryOnAllOperations: true #对超时请求启用重试机制
MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
MaxAutoRetries: 1 # 切换实例后重试最大次数
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法
单个服务负载均衡配置
springbootEurekaRibbonServer:
ribbon:
ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
OkToRetryOnAllOperations: true #对超时请求启用重试机制
MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
MaxAutoRetries: 1 # 切换实例后重试最大次数
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法
如果不需要注册中心,可以这样来写
springbootEurekaRibbonServer.ribbon.eureka.enabled=false
springbootEurekaRibbonServer.ribbon.listOfServers=http://springbootEurekaRibbonServer:18091,http://springbootEurekaRibbonServer:18092
Ribbon的负载均衡策略
- com.netflix.loadbalancer.RandomRule:从提供服务的实例中以随机的方式;
- com.netflix.loadbalancer.RoundRobinRule:以线性轮询的方式,就是维护一个计数器,从提供服务的实例中按顺序选取,第一次选第一个,第二次选第二个,以此类推,到最后一个以后再从头来过;
- com.netflix.loadbalancer.RetryRule:在RoundRobinRule的基础上添加重试机制,即在指定的重试时间内,反复使用线性轮询策略来选择可用实例;
- com.netflix.loadbalancer.WeightedResponseTimeRule:对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择;
- com.netflix.loadbalancer.BestAvailableRule:选择并发较小的实例;
- com.netflix.loadbalancer.AvailabilityFilteringRule:先过滤掉故障实例,再选择并发较小的实例;
- com.netflix.loadbalancer.ZoneAwareLoadBalancer:采用双重过滤,同时过滤不是同一区域的实例和故障实例,选择并发较小的实例。
注解实现负载均衡策略配置
//配置启动类注解
@RestController
@RibbonClient(name = "springbootEurekaRibbonServer")
public class LoadBalanceController {
@GetMapping("/v1/hello-content")
public BaseResponse<String> loadHelloContent(String uuid){
String result = restTemplate.getForObject(ribbonServiceUrl + "http://springbootEurekaRibbonServer/helloworld/{1}", String.class, uuid);
return BaseResponse.success(result);
}
}
编程实现负载均衡策略配置
/*自定义ribbon的IRule负载规则
* ResponseTimeWeightedRule根据每个节点的相应时间负载
* RandomRule随机负载
* ZoneAvoidanceRule以根据AWS区域和可用性发送流量
* */
@Configuration
public class RibbonTimeConfig {
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
/*自定义ribbon的IPing负载规则
*DummyPing不检查活动性或者可用性,将流量发送到所有实例
*PingUrl通过HTTP访问获取与其响应并检查结果
*NIWSDiscoveryPing,Eureka发现服务的自动配置检测
*/
@Configuration
public class RibbonTimeConfig {
@Bean
public PingUrl ribbonPing(){
PingUrl pingUrl = new PingUrl();
pingUrl.setExpectedContent("true");//这个内容需要与服务器接口返回的内容一致才认为服务是正常的
return pingUrl;
}
}