一光年

[SpringCloud-极简示例] 4. 加入LoadBalancer,实现负载平衡

2019.06.20

上一篇中我们加入了服务注册与发现组件Eureka,它会自动发现所有注册的微服务,微服务之间也可以通过注册的服务名相互调用服务接口。

当请求压力过大时,我们考虑将一个服务扩展为N个运行实例,这样访问压力就会被分拆给这N个服务。做负载平衡的目的,就是将大量的访问请求相对平衡的分配给各个服务实例。

demo3-1

在本例中我们会运行两个Provider实例,当向Consumer发出请求时,Consumer会平均的将请求转发到两个Provider实例上。

添加LoadBalancer

加入Feign组件,包中已经自动附带了LoadBalancer包。

  ...
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>LATEST</version>
  </dependency>

在Controller中,自动绑定LoadBalancer的实例,它会根据配置自动选定一个对应服务名的接口服务。

package com.example.springcloud.comsumer.web;
...

@RestController
@RequestMapping("")
public class DemoController {
	
    @Autowired
    private RestTemplate restTemplate;
//  @Autowired
//  private DiscoveryClient discoveryClient;
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @GetMapping("/product/{id}")
    public Object getProvider(@PathVariable Integer id) throws MalformedURLException {
		
//      List<ServiceInstance> services = discoveryClient.getInstances("ms-provider");
//      if (services.size() > 0) {
//          String URL = services.get(0).getUri().toURL().toString();
//          return restTemplate.getForObject(URL + "/" + id, Object.class);
//      }
		
        // 根据负载平衡的设置,自动选择一个Provider服务
        ServiceInstance serviceInstance = loadBalancerClient.choose("ms-provider");
        if (serviceInstance == null) {
            return "找不到服务";
        }
		
        String URL = serviceInstance.getUri().toURL().toString();
        return restTemplate.getForObject(URL + "/" + id, Object.class);	
    }
}

新加一个Provider实例

作为测试,可以简单操作如下:

  1. 运行Provider主程序
  2. 修改application.yml,将端口改为8082
  3. 运行Provider主程序

启动完成后刷新Eureka管理界面(http://localhost:8765),可以看到MS-PROVIDER行运行了两个实例。

demo3-two-provider

测试一下

打开浏览器,多次请求网址 http://localhost:8080/product/1,可以看到两个PROVIDER分别相应了CONSUMER的请求。