一. Ribbon 负载均衡策略介绍

看图,不解释
在这里插入图片描述
默认 轮询

二. Feign 更改负载均衡策略

项目用 eureka-feign-hystrix-client,参考文章

feign 更改负载就均衡策略 只要在配置文件 application.yml 配置就行,代码如下:

server:
  port: 8767

spring:
  #配置程序名为eureka-feign-hystrix-client
  application:
    name: eureka-feign-hystrix-client

eureka:
  client:
    #服务注册地址
    serviceUrl:
      #注意: Eureka Server 的注册地址
      #将服务提供者注册到三个Eureka Server中去
      #defaultZone: http://peer1:8001/eureka/,http://peer2:8002/eureka/,http://peer3:8003/eureka/
      #defaultZone: http://peer1:8001/eureka/
      defaultZone: http://localhost:8761/eureka/

feign:
  hystrix:
    enabled: true  #开启 Hystrix 功能

logging:
  level:
    #feign 接口类的路径(这个配置表示的意思是,在调用 FeignHystrixInter 接口时做debug日志的输出。)
    com:
      example:
        eurekafeignhystrixclient:
          inter:
            FeignHystrixInter: debug
            # 如何配置多个 Feign 接口类 的 调用日志
            # FeignHystrixInter2: debug
            # FeignHystrixInter3: debug
            # FeignHystrixInter4: debug

# Feign 如何结合 Ribbon 切换负载均衡策略算法
eureka-client: # eureka-client 表示作用到哪个微服务
  ribbon:
    # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机
    # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
    # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置规则 重试
    # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置规则 响应时间权重
    # 我们也可以指定为其他策略,包括我们自己定义的,只要把相应的包路径写到这即可。
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

    # ConnectTimeout: 500 #请求连接超时时间
    # ReadTimeout: 1000 #请求处理的超时时间
    # OkToRetryOnAllOperations: true #对所有请求都进行重试
    # MaxAutoRetriesNextServer: 2 #切换实例的重试次数
    # MaxAutoRetries: 1 #对当前实例的重试次数

三. RestTemplate 中更改负载均衡策略算法

项目用 eureka-ribbon-hystrix-client,参考文章

RestTemplate 更改负载就均衡策略 只要在Ribbon配置类 RibbonConfig 添加代码即可,代码如下:

package com.example.eurekaribbonhystrixclient.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * 如何将RestTemplate 和 Ribbon 相结合进行负载均衡?
 * 只需要在程序的IOC容器中注入一个 RestTemplate 的 Bean,并在这个 Bean 上加上 @LoadBalanced 注解(负载均衡注解)
 * 此时 RestTemplate 就结合 Ribbon 开启了负载均衡功能
 *
 */

@Configuration
public class RibbonConfig {

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

    /**
     * 更改 负载均衡策略算法
     * RandomRule #配置规则 随机
     * RoundRobinRule #配置规则 轮询
     * RetryRule #配置规则 重试
     * WeightedResponseTimeRule #配置规则 响应时间权重
     * 也可以自定义负载均衡策略的类
     * @return
     */
    @Bean
    public IRule myRule(){
        return new RandomRule();
    }
}

四.自定义负载均衡策略的类

定义 MyCustomRule 类 继承 AbstractLoadBalancerRule 类,重写父类方法。
例如:要求每台服务器被调用5次才能轮询下一个,也就是说以前每台机器一次,现在每台机器5次。代码如下:

package com.example.eurekaribbonhystrixclient.rule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 要求每台服务器被调用5次才能轮询下一个,也就是说以前每台机器一次,现在每台机器5次。
 */
public class MyCustomRule extends AbstractLoadBalancerRule {
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }

    /**
     * Randomly choose from all living servers
     */
    //@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
    //从服务清单中随机选择一个服务实例
    @SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        int total = 0; // 总共被调用的次数,目前要求每台被调用5次
        int currentIndex = 0; // 当前提供服务的机器号

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            //负载均衡来获得可用实例列表upList和allList
            List<Server> upList = lb.getReachableServers();
            List<Server> allList = lb.getAllServers();
            int serverCount = allList.size();
            if (serverCount == 0) {
                /*
                 * No servers. End regardless of pass, because subsequent passes
                 * only get more restrictive.
                 */
                return null;
            }
            if (total < 5) {
                server = upList.get(currentIndex);
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= upList.size()) {
                    currentIndex = 0;
                }
            }
            if (server == null) {
                /*
                 * The only time this should happen is if the server list were
                 * somehow trimmed. This is a transient condition. Retry after
                 * yielding.
                 */
                Thread.yield();
                continue;
            }
            if (server.isAlive()) {
                return (server);
            }
            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }
        //正常情况下,每次都应该可以选择一个服务实例
        return server;
    }


    //随机获取一个随机数
    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

}

在Feign中 ,在配置文件application.yml 配置自定义的策略,如图所示:

在这里插入图片描述

在RestTemplate,配置自定义的策略,代码如下:

package com.example.eurekaribbonhystrixclient.config;


import com.example.eurekaribbonhystrixclient.rule.MyCustomRule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * 如何将RestTemplate 和 Ribbon 相结合进行负载均衡?
 * 只需要在程序的IOC容器中注入一个 RestTemplate 的 Bean,并在这个 Bean 上加上 @LoadBalanced 注解(负载均衡注解)
 * 此时 RestTemplate 就结合 Ribbon 开启了负载均衡功能
 *
 */

@Configuration
public class RibbonConfig {

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

    /**
     * 更改 负载均衡策略算法
     * RandomRule #配置规则 随机
     * RoundRobinRule #配置规则 轮询
     * RetryRule #配置规则 重试
     * WeightedResponseTimeRule #配置规则 响应时间权重
     * 也可以自定义负载均衡策略的类
     * @return
     */
    @Bean
    public IRule myRule(){
        return new MyCustomRule();//自定义的Rule
        //return new RandomRule();
    }
}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐