springCloud 微服务学习笔记
(四)ribbon实现客户端负载均衡
- ribbon简介
- 复制项目microservice_consumer-movie为 microservice_consumer-movie-ribbon
- 添加pom依赖
- 添加注解
- 修改controller
- 启动测试
- 使用java代码自定义ribbon配置
ribbon简介
ribbon是netflix发布的负载均衡器,为ribbon提供服务提供者地址列表后,ribbon就可以基于某种负载均衡算法,自动的帮消费者去请求。ribbon默认为我们提供了许多负载均衡算法,当然我们也可以自定义负载均衡算法。
ribbon提供的负载均衡算法有:
策略名 | 策略声明 | 策略描述 | 实现说明 |
---|---|---|---|
BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server |
RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 对选定的负载均衡策略机上重试机制 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
RandomRule | public class RandomRule extends AbstractLoadBalancerRule | 随机选择一个server | 在index上随机,选择index对应位置的server |
ZoneAvoidanceRule | public class ZoneAvoidanceRule extends PredicateBasedRule | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server |
1.复制项目microservice_consumer-movie为 microservice_consumer-movie-ribbon
2. 添加pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.whu.learning</groupId>
<artifactId>microservice-consumer-movie-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>microservice-consumer-movie-ribbon</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--引入actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--引入web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!--引入ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
</dependencies>
<!--引入spring cloud依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
添加注解
为RestTemplate添加@LoadBalanced注解
@SpringBootApplication
//让本服务被eureka server发现
@EnableDiscoveryClient
public class MicroserviceConsumerMovieRibbonApplication {
@Bean
//加上这个注解就能使该服务具有负载均衡的能力,真的神奇,后面原理是啥呢?
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(MicroserviceConsumerMovieRibbonApplication.class, args);
}
}
修改controller
修改controller:
@Controller
public class MovieController {
private static Logger logger = LoggerFactory.getLogger(MovieController.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/user/{id}")
@ResponseBody
public User findUserById(@PathVariable Long id) {
return restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
}
@GetMapping("/log-user-instance")
@ResponseBody
public void logUserInstance() {
ServiceInstance serviceInstance = loadBalancerClient.choose("microservice-provider-user");
logger.info("{},{},{}", serviceInstance.getServiceId(), serviceInstance.getHost(), serviceInstance.getPort());
}
}
启动测试
- 启动microservice-discovery-eureka
- 启动多个microservice-provider-user (使用 java -jar XXX.jar --server.port=YYY)
- 启动microservice_consumer-movie-ribbon
- 访问 http://localhost:8010/log-user-instance 控制台打印如下图:
可以看到,此时请求会均匀分布到两个不同的微服务节点上,说明已经实现了负载均衡。
使用java代码自定义ribbon配置
很多场景下需要自定义ribbon配置,例如修改ribbon的负载均衡规则等。
下面实例展示如何用java代码自定义改变负载均衡算法。
- 复制项目 microservice_consumer-movie-ribbon为microservice_consumer-movie-ribbon-customizing
- 创建ribbon配置类
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
- 创建空类,添加@Configuration和@RibbonClient注解
@Configuration
@RibbonClient(name = "microservice-provider-user", configuration = RibbonConfiguration.class)
public class TestConfiguration {
}
- 修改启动类,添加注解
@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(basePackages = "com.whu.learning.microservice_consumermovieribboncustimizing",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = RibbonConfiguration.class)})
public class MicroserviceConsumerMovieRibbonCustimizingApplication {
@Bean
//加上这个注解就能使该服务具有负载均衡的能力,真的神奇,后面原理是啥呢?
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(MicroserviceConsumerMovieRibbonCustimizingApplication.class, args);
}
}
- 启动测试
- 启动microservice-discovery-eureka
- 启动多个microservice-provider-user (使用 java -jar XXX.jar --server.port=YYY)
- 启动microservice_consumer-movie-ribbon
- 访问 http://localhost:8010/log-user-instance 控制台打印如下图:
参考资料
《springCloud 与Docker微服务架构实战 》—周立
https://blog.csdn.net/rickiyeat/article/details/64918756