Spring Cloud LoadBalancer 实战

70 阅读1分钟

Spring Cloud LoadBalancer 官方文档

介绍

Spring Cloud 提供了自己的客户端负载均衡器的抽象和实现. 目前已经支持的http客户端有:

已经提供的负载均衡算法有随机和轮询, 可以看到源码中 ReactorServiceInstanceLoadBalancer 接口的实现类:

实现类

实战

添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

测试

这里使用RestTemplate来测试负载均衡效果, 默认均衡算法为轮询算法.

    @GetMapping("/list")
    public String getOrders() {
        // 请求商品列表
        // 1. 通过RestTemplate调用goods-svc服务的商品列表接口
        String resp = restTemplate.getForObject("http://goods-svc/goods/list", String.class);
        log.info(resp);
        return resp;
    }

原理

通过debug可以得知, 最终的实现原理是通过restTemplate拦截器 LoadBalancerInterceptor 切入负载均衡, 最终通过RoundRobinLoadBalancer#getInstanceResponse方法选择出来一个实例作为请求目标:

private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
    if (instances.isEmpty()) {
        if (log.isWarnEnabled()) {
            log.warn("No servers available for service: " + this.serviceId);
        }

        return new EmptyResponse();
    } else if (instances.size() == 1) {
        return new DefaultResponse((ServiceInstance)instances.get(0));
    } else {
        int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;
        ServiceInstance instance = (ServiceInstance)instances.get(pos % instances.size());
        return new DefaultResponse(instance);
    }
}

这里算法也很简单: 就是请求次数 % 实例数量

修改负载均衡算法

public class LoadBalancerConfiguration {

    /**
     * 修改负载均衡策略
     * @param environment
     * @param loadBalancerClientFactory
     * @return
     */
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                                          .getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }
}
@Configuration
@LoadBalancerClient(name = "goods-svc", configuration = LoadBalancerConfiguration.class)
public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }


}

总结

综上所述,Spring Cloud LoadBalancer 提供了灵活而强大的负载均衡功能,可以满足各种场景下的需求。