Skip to content

idefav/spring-boot-starter-rest-lb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

50 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status Coverity Scan Build Status GitHub release Maven Central Repo License

RestTemplate 的负载均衡实现

优点

  1. 基于 Spring BootStarter 启动器, 开箱即用
  2. 依赖包较少
  3. 配置简单, 增强 RestTemplate 实现负载均衡
  4. 扩展简单, 默认实现有 轮询 和 随机 负载规则算法, 支持自定义负载规则
  5. 使用 Spring Boot 原生配置, 支持 Spring Cloud Config/Apollo/Nacos 等配置中心

适用场景

  1. 不想使用 Spring CloudDubbo 等, 大型微服务框架
  2. 不想自己维护 Nginx (或者没有维护 Nginx 的运营人员)
  3. 不想引入大量依赖, 导致项目依赖复杂

使用说明

1.引入依赖

        <dependency>
            <groupId>com.idefav</groupId>
            <artifactId>spring-boot-starter-rest-lb</artifactId>
            <version>1.0.1</version>
        </dependency>
  1. 配置 RestTemplate
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate;
    }
  1. 使用
    public String accessBaidu() {
        String result = restTemplate.getForObject("https://baidu/", String.class);
        log.info(result);
        return result;
    }

注意: baidu 是服务名称, 需要和配置文件里面的服务名称保持一致

  1. 配置服务
idefav.service-list.baidu.load-balancor=com.idefav.rest.lb.loadbalancers.RoundRobinLoadBalancer
idefav.service-list.baidu.server-list[0].url=www.baidu.com
idefav.service-list.baidu.server-list[1].url=www.jd.com
  1. 启动项目

扩展

使用字段 properties 新增 weight 权重字段

idefav.service-list.baidu.load-balancor=com.idefav.springbootdemo.loadbalancers.RandomWithWeightLoadBalancer
idefav.service-list.baidu.server-list[0].url=www.baidu.com
idefav.service-list.baidu.server-list[0].properties.weight=20
idefav.service-list.baidu.server-list[1].url=www.jd.com
idefav.service-list.baidu.server-list[1].properties.weight=80

实现权重随机算法

public class RandomWithWeightLoadBalancer extends AbstractLoadBalancer {

    private TreeMap<Double, LbServer> weightMap = new TreeMap<>();

    public RandomWithWeightLoadBalancer(List<LbServer> serverList) {
        super(serverList);
        checkServerList();
        serverList.forEach(k -> {
            double lastWeight = this.weightMap.size() == 0 ? 0 : this.weightMap.lastKey();
            if (k.getProperties() == null) {
                return;
            }
            String weight = k.getProperties().get("weight");
            if (StringUtils.isEmpty(weight)) {
                return;
            }
            if (!StringUtils.isNumeric(weight)) {
                return;
            }
            weightMap.put(Double.parseDouble(weight) + lastWeight, k);
        });
    }

    @Override
    public LbServer getServer() {
        double randomWeight = weightMap.lastKey() * Math.random();
        NavigableMap<Double, LbServer> doubleLbServerNavigableMap = weightMap.tailMap(randomWeight, false);
        return weightMap.get(doubleLbServerNavigableMap.firstKey());
    }
}

重试

  1. 固定次数重试
idefav.service-list.httpbin.retry-property.enable=true
idefav.service-list.httpbin.retry-property.retry.max-attempts=3

遇到调用接口失败, 会自动重试3次 2. 设定重试最大超时时间

idefav.service-list.httpbin.retry-property.retry.timeout=20000

在最大重试时间之内, 会一直重试 如果设置了固定次数重试, 即使最大重试次数未达到, 如果达到最大重试时间, 也终止重试 3. 熔断降级

idefav.service-list.httpbin.retry-property.retry.open-timeout=5000
idefav.service-list.httpbin.retry-property.retry.reset-timeout=20000