负载均衡Bibbon

2022-03-24 15:49:44 浏览数 (1)

负载均衡

结合上篇文章 点击查看Eureka注册中心

什么是Ribbon

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。

在刚才的案例中,我们启动了一个user-service,然后通过consumer来获取服务实例信息,然后获取ip和端口来访问。

但是实际环境中,我们往往会开启很多个user-service的集群。此时我们获取的服务列表中就会有多个,到底该访问哪一个呢?

一般这种情况下我们就需要编写负载均衡算法,在多个实例列表中进行选择。

使用负载均衡

导入负载均衡依赖

代码语言:javascript复制
 <!--使用负载均衡 引入 ribbon依赖-->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
       </dependency>

启动两个服务实例

设置另一个服务端口号

开启负载均衡

因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖。直接修改代码。

在消费者的启动类和RestTemplate上加入注解

代码语言:javascript复制
@EnableDiscoveryClient//开启负载均衡
@SpringBootApplication
public class UserConsumerDemoApplication {

    @Bean
    @LoadBalanced//负载均衡的另一种使用方法  内置一个拦截器 拦截所有restTemplate请求
    public RestTemplate restTemplate() {
        // 这次我们使用了OkHttp客户端,只需要注入工厂即可
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(UserConsumerDemoApplication.class, args);
    }
}

在控制层中修改代码

代码语言:javascript复制
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;


 public User queryUserById(@PathVariable("id") Long id){
  
      String url="http://user-service/user/" id;//中间写服务id    内置一个拦截器 把restTemplate请求拦截 负载均衡替换地址
       User user = restTemplate.getForObject(url, User.class);
       return user;
}

测试即可

负载均衡策略

Ribbon默认的负载均衡策略是简单的轮询

SpringBoot也帮我们提供了修改负载均衡规则的配置入口:

代码语言:javascript复制
server:
  port: 8888
spring:
  application:
    name: consumer-service
eureka:  #配置eureka集群之间的相互注册
  client:
    service-url:    # 配置两个Eureka地址  高可用
     defaultZone: http://127.0.0.1:10088/eureka,http://127.0.0.1:10089/eureka  #覆盖默认配置  key value结构
  instance:
    prefer-ip-address: true  #表示我希望使用IP地址
    ip-addres: 127.0.0.1 #指定IP地址      服务的适用方要去eureka拉取服务
user-service:  #对哪个服务进行负载均衡
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  #负载均衡算法策略 默认是轮询

修改为了随机 格式是:{服务名称}.ribbon.NFLoadBalancerRuleClassName,值就是IRule的实现类。

重试机制

Eureka的服务治理强调了CAP原则中的AP,即可用性和可靠性。它与Zookeeper这一类强调CP(一致性,可靠性)的服务治理框架最大的区别在于:Eureka为了实现更高的服务可用性,牺牲了一定的一致性,极端情况下它宁愿接收故障实例也不愿丢掉健康实例,正如我们上面所说的自我保护机制。

但是,此时如果我们调用了这些不正常的服务,调用就会失败,从而导致其它服务不能正常工作。

我们现在关闭一个user-service

因为服务剔除的延迟,consumer并不会立即得到最新的服务列表,此时再次访问你会得到错误提示。 但是此时,8081服务其实是正常的。

因此Spring Cloud 整合了Spring Retry 来增强RestTemplate的重试能力,当一次服务调用失败后,不会立即抛出一次,而是再次重试另一个服务。

只需要简单配置即可实现Ribbon的重试:

代码语言:javascript复制
# 在消费者中配置
spring:
  cloud:
    loadbalancer:
      retry:
        enabled: true # 开启Spring Cloud的重试功能
user-service:
  ribbon:
    ConnectTimeout: 250 # Ribbon的连接超时时间
    ReadTimeout: 1000 # Ribbon的数据读取超时时间
    OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
    MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
    MaxAutoRetries: 1 # 对当前实例的重试次数

根据如上配置,当访问到某个服务超时后,它会再次尝试访问下一个服务实例,如果不行就再换一个实例,如果不行,则返回失败。切换次数取决于MaxAutoRetriesNextServer参数的值。 当然需要引入依赖

代码语言:javascript复制
<!--在消费者中配置-->
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

0 人点赞