(三 Ribbon 什么是负载均衡?spring cloud如何实现负载均衡)手摸手带你一起搭建 Spring cloud 微服务 理论+实践+解析

在上一章,我介绍了springcloud的eureka搭建。我们做了服务注册。最后我们还介绍了一些续约,失效剔除等参数配置。已经不需要再通过手动输入ip去访问服务,而是通过中心只需要通过服务名就可以获取服务。这一章我们将要学习一下Ribbon负载均衡

上一章:(二 什么是Eureka服务注册中心,如何搭建?)手摸手带你一起搭建 Spring cloud 微服务 理论+实践+解析

一、Ribbon是什么?

负载均衡顾名思义,平均每台服务器的压力。实际开发过程中,同一种服务可能有多个服务器,即服务集群。这个时候为了保证这个类型的服务每台服务负载平均分配。
Ribbon是Netfix发布的负载均衡器,他有助于控制HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后,Ribbon就可以基于某种负载均衡算法,自动帮助服务消费者去请求。

在这里插入图片描述
我们上一章的例程是通过服务名获取完服务集合,serviceInstances.get(0) 可以看到总是获取第一个,因为我们当时只有一个user-service,这样显然是不对的。

 List<ServiceInstance> serviceInstances= discoveryClient.getInstances("user-service");
 String url = "http://"+serviceInstances.get(0).getHost()+":"+serviceInstances.get(0).getPort()+"/user/"+id;

所以我们需要根据算法,每次去选取合适的服务器,进行访问。
Ribbon默认为我们提供了很多负载均衡算法,我们先了解一下ribbon负载均衡有几种策略,也就是算法。

二、ribbon负载均衡有几种策略

1、随机策略RandomRule

从名字就能看出,这是个很随性的策略,随性到什么程度呢?它会从当前可用的服务节点中,随机挑选一个节点访问。妈的真随便,比我还随便。

2、轮询策略RoundRobinRule(默认策略)

这个rule是RandomRule的亲兄弟,RandomRule是随性而为挑选节点,RobinRule却按部就班从一个节点一步一步地向后选取节点,既不会跳过一个,也不会原地踏步,每一次只向后移动一步。

3、重试策略RetryRule

RetryRule他的BUFF就是给其他负载均衡策略加上重试功能。而在RetryRule里还藏着一个subRule ,这才是隐藏在下面的真正被执行的负载均衡策略,RetryRule正是要为它添加重试功能(如果初始化时没指定subRule,将默认使用RoundRibinRule )

4、最低并发策略BestAvailableRule

这个Rule继承自RoundRibonRule ,他会根据服务节点的响应时间计算权重,响应时间越长权重就越低,响应越快则权重越高,权重的高低决定了机器被选中概率的低。也就是说,响应时间越小的机器,被选中的概率越大。

5、可用过滤策略AvailabilityFilteringRule

应该说这个Rule有点智能的味道了,在过滤掉故啤服务以后,它会基于过去30分钟的统计结果选取当前并发量最小的服务节点,也就是最%闲”"的节点作为目标地址。如果统计结果尚未生成,则采用轮询的方式选定节点。

6、响应时间加权策略WeightedResponseTimeRule

这个规则底层依赖RoundRobinRule来选取节点,但并非来者不拒,它也是有一些底线的,必须要满足它的最低要求的节点才会被选中。如果节点满足了要求,无论其响应时间或者当前并发量是什么,都会被选中。
每次AvailabilityFilteringRule(简称AFR)都会请求RobinRule挑选一个节点,然后对这个节点做以下两步检查:
是否处于熔断状态(这里大家可以把熔断当做服务不可用)
节点当前的active请求连接数超过阈值,超过了则表示节点目前太忙,不适合接客
如果被选中的server不幸挂掉了检查,那么AFR会自动重试(次数最多10次),让RobinRule重新选择一个服务节点。

7、区域权衡策略ZoneAvoidanceRule

这个过滤器包含了组合过滤条件,分别是Zone级别和可用性级别。
ZoneFilter:在Eureka注册中一个服务节点有Zone,Region和URL三个身份信息,其中Zone可以理解为机房大区(未指定则由Eureka给定默认值),而这里会对这个Zone的健康情况过滤其下面所有服务节点。
可用性过滤∶这里和AvailabilityFilteringRule的验证非常像,会过滤掉当前并发量较大,或者处于熔断状态的服务节点。

二、Ribbon测试

同样,我们的例程是用上一章的例程接着往下做
上个章节例程

2.1 copy出一个user服务

首先copy出一个新的user-service
如何复制工程
我给它命名为user-service-other
设置端口为1002
在这里插入图片描述
为了方便查看效果,我们修改一下启动类名,和响应内容
在这里插入图片描述
如果你发现启动eureka时,有报错很正常,因为上个章节我们做了eureka集群,所以我们取消集群就行,修改一下eureka配置即可

server:
  port: 11111
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:11111/eureka
    register-with-eureka: false
    fetch-registry: false
  server:
    eviction-interval-timer-in-ms: 60000
    enable-self-preservation: true

然后运行测试一下eureka和两个user-service,看看工程是否复制成功
eureka中心可以看到两个user-service注册了
在这里插入图片描述
且能够通过1002端口访问返回信息
在这里插入图片描述

2.2 修改消费服务custom-service

首先在启动类CustomService的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 CustomService {
    public static void main(String[] args) {
        SpringApplication.run(CustomService.class, args);
    }
    @Bean
    @LoadBalanced //负载均衡
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

修改UserHandler,访问的方式改为直接通过服务名的方式获取服务,原本需要获取ip处,我们直接换成服务名。


import org.antry.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @ClassName UserHandler
 * @Description TODO
 * @Autor T_Antry
 * @Date 2020/11/11 11:32
 * @Version 1.0
 */
@RestController
@RequestMapping("user")
public class UserHandler {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private UserService userService;
    @Autowired
    private DiscoveryClient discoveryClient;
    @GetMapping("/{id}")
    public String doGet(@PathVariable Long id){
//       String url = "http://127.0.0.1:1001/user/"+id;
//       return "<div><h1>custom-Service回应:</h1><div>"+restTemplate.getForObject(url, String.class);
//       return userService.doGetUser(id);
//         List<ServiceInstance> serviceInstances= discoveryClient.getInstances("user-service");
//         String url = "http://"+serviceInstances.get(0).getHost()+":"+serviceInstances.get(0).getPort()+"/user/"+id;
         String url = "http://user-service/user/"+id;
        return "<div><h1>custom-Service[通过注册中心拉取服务]回应:</h1><div>"+restTemplate.getForObject(url, String.class);
    }
}

2.3 运行

如果之前的eureka和两个user-service没关的话,直接运行custom-service就可以,如果关了,再运行起来,然后运行custom-service
在地址栏输入http://127.0.0.1:9001/user/123,因为custom的工程端口我们在之前的案例中给它设置成9001端口
一直刷新,我们可以看到,拿到是来自两个不同服务的响应,这是默认的轮询策略
在这里插入图片描述
在这里插入图片描述

2.4 如何修改策略

在消费者服务的配置文件中按下面个规则修改,
这个案例是给user-service配置策略为随机策略
配置完重新运行工程,会发现,响应不再像上面那样有规律地变化,而是无规律的响应了。

user-service: #要配置策略的服务名
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  #要配置的策略名

本章资源
原本我选择0币下载,但是会自动要求收币,所以只好改成关注免费下载。

猜你喜欢

转载自blog.csdn.net/qq_39150049/article/details/110203818
今日推荐