SpringCloud微服务架构第四节-使用 Robbin 解决客户端负载均衡

继续 SpringCloud 之旅,前面讲到了服务的注册于发现,每个微服务都各自注册到 Eureka 服务,看上去很不错,但实际情况我们的客户端会有多个以缓解各自的压力,或者说万一哪个微服务宕机了有辅助的微服务来替代。这个时候就需要负载均衡了。

Robbin介绍

是 Netflixfa 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。在 SpringCloud 中,Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载。


SpringCloud微服务架构第四节-使用 Robbin 解决客户端负载均衡_第1张图片

集成 Robbin

首先我们给服务消费者也就是 movie 微服务,集成 Robbin,其实在 spring-cloud-starter-eureka 依赖中已经包含了 Ribbon 的依赖,所以我们不再增加新的依赖,可以查阅 pom 的依赖,如下图


SpringCloud微服务架构第四节-使用 Robbin 解决客户端负载均衡_第2张图片

其次在 RestTemplate 构造上面增加新的注解 @LoadBalanced,网站代码如下


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
public class MsSimpleConsumerMovieApplication {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    
    public static void main(String[] args) {
        SpringApplication.run(MsSimpleConsumerMovieApplication.class, args);
    }
}

说明:在这里添加这个注解就可以整合 Ribbon 到该微服务了。
最后来到我们的 Controller 层的代码处,修改 MovieController 如下

package cn.ts.ms.movie.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import cn.ts.ms.movie.model.User;


@RestController
public class MovieController {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    
    @GetMapping("/user/{id}")
    public User findByUserId(@PathVariable Integer id){
        return restTemplate.getForObject("http://MS-SIMPLE-PROVIDER-USER/user/find?id="+id, User.class);
    }
    
    @GetMapping("/log")
    public void printLog(){
        ServiceInstance instance = loadBalancerClient.choose("MS-SIMPLE-PROVIDER-USER");
        System.out.println("Now:"+instance.getServiceId()+"---"+instance.getHost()+":"+instance.getPort());
    }
    
}

说明:
修改restTemplate.getForObject 的第一个参数为 http://MS-SIMPLE-PROVIDER-USER/user/find?id="+id 这样我们就不必关心到底是哪个 ip 提供的服务,只需要指定这个虚拟主机名,接下来我们启动服务器看看效果
启动 eureka、2个或多个 user 微服务,启动 movie 微服务

在开发的时候,启动多个微服务,只需要改变端口即可


SpringCloud微服务架构第四节-使用 Robbin 解决客户端负载均衡_第3张图片

启动后查看下 eureka 服务器


SpringCloud微服务架构第四节-使用 Robbin 解决客户端负载均衡_第4张图片

可以清楚的看到2个 use 微服务

我们接下来调用 movie 的接口看看是否和我们想象的一样,不出意外,我们也能获得和之前一样的结果,为了验证 Robbin 的分配策略,我们调用 http://localhost:8010/log 这个接口,多刷几次,可以看到我们的请求能够向不同的 user 提供发送

SpringCloud微服务架构第四节-使用 Robbin 解决客户端负载均衡_第5张图片

自定义 Robbin 策略

以上是默认行为,在实际情况下,很有可能需要不同的分配轮询策略,接下来我们构造一个我们自己的 Robbin

代码实现方式

首先我们建立一个 Robbin 配置类,这个类不能在主应用程序的@ComponentScan中,我们单独建一个包就叫 robbin

package cn.ts.ms.robbin;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;

@Configuration
public class RobbinConfig {

    @Bean
    public IRule robbinRule(){
        return new RandomRule();
    }
}

我们需要配置 user 的服务使用这个 robbin,需要在构建一个类,这个类是需要被扫描到的

package cn.ts.ms.movie;

import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;

import cn.ts.ms.robbin.RobbinConfig;

@Configuration
@RibbonClient(name="MS-SIMPLE-PROVIDER-USER",configuration=RobbinConfig.class)
public class RobbinNewConfig {

}

OK,代码开发完毕,走一遍测试下,多次请求 http://localhost:8010/log
得到的结果是

SpringCloud微服务架构第四节-使用 Robbin 解决客户端负载均衡_第6张图片

这次是随机请求的结果。

配置方式更简单

上面是使用 java 编码的方式,也可以使用 yml 配置的方式快速达到效果
我们将上面的RobbinNewConfig 注释掉,改用 yml 的方式
在 yml 里面增加

MS-SIMPLE-PROVIDER-USER: 
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

结果也是一样的。
到此,我们基本把 Ribbon 如何使用给说明清楚,下一步我们将使用 Feign实现声明式 Rest 调用。

你可能感兴趣的:(SpringCloud微服务架构第四节-使用 Robbin 解决客户端负载均衡)