Ribbon组件主要用来进行远程调用的负载均衡,基于HTTP和TCP的客户端负载均衡工具。虽然是SpringCloud的组件,但也可以单独进行使用。
1.1 依赖
SpringCloud项目直接引用如下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
1.2 配置
# 禁用Eureka,默认为true,禁用后就需要手动配置服务的地址列表
ribbon.eureka.enabled=false
# 针对具体服务配置的服务地址,前缀就是服务名
order.service.ribbon.listOfServers=localhost:8081,localhost:8083
#单位ms ,请求连接超时时间
ribbon.ConnectTimeout=1000
#单位ms ,请求处理的超时时间
ribbon.ReadTimeout=3000
# 也可是为单独的服务配置超时时间和请求处理的时间,前面加个服务名的前缀即可
# 指定某个服务的负载均衡策略
order.service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
重试机制:
当Eureka的客户端挂掉时,无法继续发送心跳,则Eureka还会保存一段时间该服务的信息,因此此时调用一定会出现,我们可以使用重试机制避免,即当请求出错时,重新请求另外的服务。
此时指定某个服务的负载均衡策略为重试即可:
order.service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RetryRule
另外也可以使用Spring Retry实现重试:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
配置如下:
# 是否对所有请求都重试
ribbon.OkToRetryOnAllOperations=false
#切换实例的重试次数
ribbon.MaxAutoRetriesNextServer=0
#对当前实例的重试次数 当Eureka中可以找到服务,但是服务连不上时将会重试
ribbon.MaxAutoRetries=0
1.2 使用
在使用前,我们先准备一个订单服务注册到Eureka,并且提供一个接口用于测试ribbon:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/testRest")
public String testRest(HttpServletRequest request) {
logger.info("==================已经调用==========" + request.getRemotePort());
return "success";
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tf5WQmPn-1596355160850)(assets/image-20200725143257317.png)]
接着在web服务中调用订单服务:
我们结合Spring的RestTemplate进行远程调用,当然SpringCloud中可以使用另外的组件Feign进行服务接口调用。使用@LoadBalanced
添加负载均衡功能,并且该注解就可以让restTemplate和Eureka整合:
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/testribbon")
public String ribbonTest(){
String result = restTemplate.getForObject("http://ORDER-SERVICE/user/testRest", String.class);
return result;
}
}
这样就可以调用到订单服务的接口。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b5XPnPci-1596355160854)(assets/image-20200725143730901.png)]
1.3 负载均衡
Ribbon在调用服务的时候,如果有多个服务实例,内部会根据一些负载均衡算法进行调用。
其默认的策略是轮询。
配置负载均衡算法:(常见的)
@Configuration
public class RibbonLoadBalanceMicroOrderConfig {
private String name = "micro-order";
@Bean
public IRule ribbonRule() {
//轮询
new RoundRobinRule();
//可以重试的轮询
new RetryRule();
//根据运行情况来计算权重
new WeightedResponseTimeRule();
//过滤掉故障实例,选择并发请求数最小的实例
new BestAvailableRule();
//随机轮询
return new RandomRule();
}
}
1.4饥饿加载
在进行服务调用时,如果网络不好,则第一次调用会出现超时的情况,因为Ribbon客户端是在第一次请求时初始化的。针对该问题,我们可以禁用超时或者让超时时间变长。
同时也可以开启Ribbon的饥饿加载模式,让其提前初始化:
ribbon.eager-load.enabled=true
ribbon.eager-load.clients=order-service
第二个就是指定需要提前加载的服务名,多个服务用英文逗号分隔就好