第七节 负载均衡策略

亮子 2021-06-08 23:56:24 18194 0 0 0

1、负载均衡

1)、负载均衡的默认配置

上一节中,article服务调用user微服务,我们发现,每次请求,都是由不同的user微服务提供的。其实这是由于SpringCloud默认指定了Ribbon组件来提供的负载均衡策略。而Ribbon默认的负载均衡策略是轮询,因此我们在连续刷新页面时,user服务依次来提供服务。

在article服务运行的时候,我们可以仔细观察一下,有下面一段输出:

You already have RibbonLoadBalancerClient on your classpath. It will be used by default. As Spring Cloud Ribbon is in maintenance mode. We recommend switching to BlockingLoadBalancerClient instead. In order to use it, set the value of spring.cloud.loadbalancer.ribbon.enabled to false or remove spring-cloud-starter-netflix-ribbon from your project.

2)、禁用RibbonLoadBalancerClient

(1)修改application.properties文件,增加内容如下:

spring.cloud.loadbalancer.ribbon.enabled=false

(2)再运行各个项目

运行顺序:

  • server-blog-eureka
  • server-blog-user(port=8001,8002,8000)
  • server-blog-article

图片alt

(3)运行效果

图片alt

从实际测试看,即使我们设置了禁用ribbon,EurekaClient仍然有自己的负载均衡策略(轮询)。

2、Ribbon负载均衡

1)、什么是负载均衡

  • 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。

  • 负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

2)、负载均衡的种类

  • 硬负载
  • 软负载
  • nginx可以使用负载均衡分配流量

  • dubbo服务调用里的负载均衡
  • ribbon为客户端提供负载均衡

3)、Ribbon是什么?

  • Spring Cloud Ribbon是一个基于HTTP和TCP的**客户端负载均衡工具**,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
  • Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。

4)、负载均衡的策略

  • 随机 (Random)
  • 轮询 (RoundRobin)
  • 一致性哈希 (ConsistentHash)
  • 哈希 (Hash)
  • 加权(Weighted)

5)、配置文件方式配置 Ribbon

(1)通过配置文件方式自定义 Ribbon 属性

#自定义配置负载均衡策略
server1.ribbon.NFLoadBalancerRuleClassName= com.netflix.loadbalancer.RandomRule
server2.ribbon.NFLoadBalancerRuleClassName= com.netflix.loadbalancer.RoundRobinRule

2)通过定义配置类方式自定义 Ribbon 属性

  • NFLoadBalancerClassName:配置ILoadBalancer 的实现类
  • NFLoadBalancerRuleClassName:配置IRule 的实现类
  • NFLoadBalancerPingClassName:配置 IPing 实现类
  • NIWSServerListClassName:配置 ServerList 的实现类
  • NIWSServerListFilterClassName:配置 ServerListFilter 的实现类

3、最简单的负载均衡

1)、创建server-blog-good工程

(1)创建工程

图片alt

(2)、修改配置文件application.properties

## application.properties
spring.application.name=server-blog-good
server.port=8900

# eureka client
eureka.client.service-url.defaultZone=http://localhost:6060/eureka/
eureka.instance.prefer-ip-address=true

(3)、创建GoodController

package com.mazong.serverbloggood.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@Controller
public class GoodController {

    @RequestMapping(value = "/getGood")
    @ResponseBody
    public Object getGood(@RequestParam("id") Integer id) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("welcome", "hello,i am good service");

        return resultMap;
    }
}

(4)、运行效果

图片alt

2)、增加负载均衡

(1)引入TbUser类依赖

        <!-- 引入TbUser类的包 -->
        <dependency>
            <groupId>com.mazong</groupId>
            <artifactId>server-blog-user</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

(2)在启动类注入RestTemplate接口

package com.mazong.serverbloggood;

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

@SpringBootApplication
@EnableEurekaClient
public class ServerBlogGoodApplication {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(ServerBlogGoodApplication.class, args);
    }

}

(3)修改GoodController类

package com.mazong.serverbloggood.controller;

import com.mazong.serverbloguser.entity.TbUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Controller
public class GoodController {

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    LoadBalancerClient loadBalancerClient;

    @RequestMapping(value = "/getGood")
    @ResponseBody
    public Object getGood(@RequestParam("id") Integer id) {
        // http://localhost:8900/getGood?id=1

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("welcome", "hello,i am good service");

        ServiceInstance serviceInstance = loadBalancerClient.choose("server-blog-user");
        String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/getUser?id=" + id;
        System.out.println(url);

        TbUser user = restTemplate.getForObject(url, TbUser.class);
        resultMap.put("user", user);

        return resultMap;
    }
}

(4)编译运行

图片alt