Netflix Ribbon 负载均衡 概述 与 基本使用

目录

netflix ribbon 负载均衡

netflix Ribbon 基本使用

Ribbon 超时时间配置


本文环境:Java jdk 8 + Spring boot 2.1.3 + spring cloud Greenwich.SR1 + spring 5.1.5。

netflix ribbon 负载均衡

1、ribbon 与 eureka 一样都是 netflix 下的子项目,spring cloud 对它们进行了集成。

2、ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,可以轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。

3、Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过 Ribbon 实现。

4、nginx 在服务端实现负载均衡,ribbon 在客户端提供负载均衡。即客户端程序使用 ribbon 后,就会自动对多个节点微服务进行负载均衡。

5、负载均衡有好几种实现策略,常见的有:随机 (Random)、轮询 (RoundRobin)、一致性哈希(ConsistentHash)、哈希 (Hash)、加权(Weighted)。默认是轮询。官网地址:

https://github.com/Netflix/ribbon

https://spring.io/projects/spring-cloud-netflix

https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.1.0.RELEASE/single/spring-cloud-netflix.html#spring-cloud-ribbon

6、使用下面的命令启动多个微服务节点,动态修改应用端口以及实例名称。

java -jar eurekaclient_food-0.0.1-SNAPSHOT.jar --server.port=9396 --eureka.instance.instance-id=changSha-food-9396
java -jar eurekaclient_food-0.0.1-SNAPSHOT.jar --server.port=9397 --eureka.instance.instance-id=changSha-food-9397

如上所示此时 Eureka 服务端可以看到微服务 EUREKA-CLIENTFOOD 下面有3个节点。

netflix Ribbon 基本使用

1、Ribbon 是客户端实现的负载均衡,也就是谁发起请求,谁自己实现负载均衡,所以 eurekaclient_cat 向 eurekaclient_food 发起请求,则应该修改 eurekaclient_cat 应用。第一步应该引入 Ribbon 组件,但是 eureka 组件默认已经依赖了 ribbon 组件,所以只要引入了 eureka 就已经引入了 ribbon。

......
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
......

2、修改 eurekaclient_cat 创建 RestTemplate 实例的代码,加上 @LoadBalanced 使 RestTemplate 具有负载均衡的能力。

    /**
     * @SpringBootApplication 注解自己依赖了 @Configuration 注解,所以可以直接在启动类上使用 @Bean 注解
     * 当然也可以新建一个配置类(@Configuration) 专门管理需要创建的实例
     * @Bean 作用就是使用 DI 往 spring 容器中传教实例,以后可以直接使用 @Resource 取值使用。
     * <p>
     * LoadBalanced:英文就是负载均衡的意思,@LoadBalanced 注解表示 RestTemplate 具有负载均衡的能力。
     * 意味着 RestTemplate 每次发送 http 请求时,都会根据 ribbon 的负载均衡机制向微服务下的某台节点服务器发送请求
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        //RestTemplate 有3个构造器,这里使用无参构造器,底层使用 jdk 原生的 java.net 下 api 进行 http 操作
        return new RestTemplate();
    }

3、然后修改 RestTemplate 发起 http 请求的代码,将原来写死的 ip与端口换成微服务的名称,本文是为了演示简单,微服务名称直接写死了,实际开发中可以从配置文件中获取:

    @Resource
    private RestTemplate restTemplate;

    //通过 id 获取猫咪信息。这里只是简单的模拟,并不是操作数据库
    //请求地址:http://localhost:9394/getCatById?id=110
    @GetMapping("getCatById")
    public String getCatById(String id) throws IOException {
        //猫咪的基本信息,这里直接设置
        JsonNodeFactory nodeFactory = JsonNodeFactory.instance;
        ObjectNode objectNode = nodeFactory.objectNode();
        objectNode.put("id", id);
        objectNode.put("color", "white");
        objectNode.put("age", 0.2);

        //猫咪的食谱/菜谱信息调用 eurekaclient_food 微服务进行获取。
        //未使用负载均衡时的地址:http://localhost:9395/getHunanCuisine。使用负载均衡后,其中的 ip:port 必须使用微服务名称代替
        //EUREKA-CLIENT-FOOD 是在注册中心注册好的微服务名称(不是节点名称),也就是微服务配置文件中使用 spring.application.name 配置的名称
        String foodMenu = restTemplate.getForObject("http://EUREKA-CLIENT-FOOD/getHunanCuisine", String.class);
        if (!StringUtils.isEmpty(foodMenu)) {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(foodMenu);//先将 json 字符串专户 json 节点对象
            objectNode.putPOJO("menu", jsonNode);//对象节点插入子节点
        }
        return objectNode.toString();
    }

5、代码很简单,修改两处就好了,接下来访问测试:

可以看出 ribbon 默认采用的轮询的策略,即对集群的服务轮流进行访问。

注意:具有负载均衡后的 RestTemplate 请求时只能使用微服务名称,无法再直接使用 ip:port 的形式,如果应用中还需要直接使用 ip 请求,则可以再提供一个非负载均衡的 RestTemplate 实例即可,使用时根据方法名注入。

    @Bean
    RestTemplate restTemplateNotBalance() {
        return new RestTemplate();
    }

带负载均衡(@LoadBalanced)的 RestTemplate 必须使用微服务名称发起请求,不能使用 ip:port
不带负载均衡(@LoadBalanced)的 RestTemplate 不能使用微服务名称发起请求,只能使用 ip:port

更多负载均衡策略可以参考《Ribbon 负载均衡策略 与 脱离 Eureka 使用、LoadBalancerClient

演示源码 github 地址:https://github.com/wangmaoxiong/ribbon_study

Ribbon 超时时间配置

官网:/spring-cloud-netflix/2.1.0.RELEASE/single/spring-cloud-netflix.html#_zuul_timeouts

ribbon:
  ConnectTimeout: 3000  #连接超时时间
  ReadTimeout: 60000    #读取超时时间
  SocketTimeout: 60000  #socket 超时时间

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章