Ribbon 实战 & 理论

整体概念

Ribbon是Netflix开发的客户端负载均衡器,为Ribbon配置服务提供者地址列表后,Ribbon就可以基于某种负载均衡策略算法,自动地帮助服务消费者去请求 提供者。Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。我们也可以实现自定义负载均衡算法。

实现负载均衡

  1. 准备一个 client 服务,两个 order 服务,全部注册到同一个注册中心中,通过 client 服务调用order服务达到负载均衡
  2. 注册中心 application.properties
#是否将自己注册到其他Eureka Server,默认为true
eureka.client.register-with-eureka=false
#是否从eureka server获取注册信息
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://eureka-service1.com:7901/eureka/
  1. client 服务 application.properties
#是否将自己注册到其他Eureka Server,默认为true
eureka.client.register-with-eureka=true
#是否从eureka server获取注册信息
eureka.client.fetch-registry=true
#设置服务注册中心的URL
eureka.client.serviceUrl.defaultZone=http://eureka-service1.com:7901/eureka/
eureka.instance.appname=client
#web端口,服务是由这个端口处理rest请求的
server.port=8080
  1. order1 application.properties
#是否将自己注册到其他Eureka Server
eureka.client.register-with-eureka=true
#是否从eureka server获取注册信息
eureka.client.fetch-registry=true
#设置服务注册中心的URL
eureka.client.serviceUrl.defaultZone=http://eureka-service1.com:7901/eureka/
#实例名
eureka.instance.appname=order
#主机名
eureka.instance.hostname=eureka-order1.com
#应用名(loadBalancerClient.choose 方法的参数)
spring.application.name=order
#web端口,服务是由这个端口处理rest请求的
server.port=8081
  1. order2 application.properties
#是否将自己注册到其他Eureka Server,默认为true 需要
eureka.client.register-with-eureka=true
#是否从eureka server获取注册信息, 需要
eureka.client.fetch-registry=true
#设置服务注册中心的URL,用于client和server端交流
eureka.client.serviceUrl.defaultZone=http://eureka-service1.com:7901/eureka/
#实例名
eureka.instance.appname=order
#主机名
eureka.instance.hostname=eureka-order2.com
#应用名(loadBalancerClient.choose 方法的参数)
spring.application.name=order
#web端口,服务是由这个端口处理rest请求的
server.port=8082
  1. 配置中心界面
    在这里插入图片描述
  2. client 代码
package com.example.eurekaclient;

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.RestController;


@RestController
public class BalancerController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @GetMapping("/choseOrder")
    public String choseOrder() {
        // spring.application.name 的值
        String serviceName = "order";
        for (int i = 0; i < 10; i++) {
            ServiceInstance si = loadBalancerClient.choose(serviceName);
            System.out.println("order节点信息:url:" + si.getHost() + ",port:" + si.getPort());
        }
        return "SUCCESS";
    }
}
  1. 访问 http://localhost:8080/choseOrder
    在这里插入图片描述

@LoadBalanced 实现

  1. 两个 order 服务代码
package com.example.eurekaorder;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BalancerController {

    @Value("${eureka.instance.hostname}")
    private String hostName;
    @Value("${server.port}")
    private Integer port;

    @GetMapping("/getHostAndPort")
    public String getHostAndPort() {
        return "host:" + hostName + ",port:" + port;
    }
}

  1. client 代码
package com.example.eurekaclient;

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class Config {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(RestTemplateBuilder builder){
        return builder.build();
    }
}

package com.example.eurekaclient;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class LoadBalancedController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/loadBalanced")
    public String loadBalanced() {
        String url = "http://order/getHostAndPort";
        for (int i = 0; i < 10; i++) {
            System.out.println(restTemplate.getForObject(url, String.class));
        }
        return "SUCCESS";
    }

}

  1. 访问 http://localhost:8080/loadBalanced
    在这里插入图片描述

自定义负载均衡策略

java代码定义

@Configuration
@RibbonClient(name = "service-order",configuration = RibbonConfiguration.class)

属性定义

针对服务定ribbon策略:
service-order: 
  ribbon: 
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
给所有服务定ribbon策略:
ribbon: 
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

脱离Eureka使用

service-order:
  ribbon:
    eureka:
    # 将Eureka关闭,则Ribbon无法从Eureka中获取服务端列表信息
    enabled: false
    # listOfServers可以设置服务端列表
    listOfServers:localhost:8081,localhost:8082

负载均衡算法

ZoneAvoidanceRule(区域权衡策略):复合判断Server所在区域的性能和Server的可用性,轮询选择服务器。

BestAvailableRule(最低并发策略):会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。逐个找服务,如果断路器打开,则忽略。

RoundRobinRule(轮询策略):以简单轮询选择一个服务器。按顺序循环选择一个server。

RandomRule(随机策略):随机选择一个服务器。

AvailabilityFilteringRule(可用过滤策略):会先过滤掉多次访问故障而处于断路器跳闸状态的服务和过滤并发的连接数量超过阀值得服务,然后对剩余的服务列表安装轮询策略进行访问。

WeightedResponseTimeRule(响应时间加权策略):据平均响应时间计算所有的服务的权重,响应时间越快服务权重越大,容易被选中的概率就越高。刚启动时,如果统计信息不中,则使用RoundRobinRule(轮询)策略,等统计的信息足够了会自动的切换到WeightedResponseTimeRule。响应时间长,权重低,被选择的概率低。反之,同样道理。此策略综合了各种因素(网络,磁盘,IO等),这些因素直接影响响应时间。

RetryRule(重试策略):先按照RoundRobinRule(轮询)的策略获取服务,如果获取的服务失败则在指定的时间会进行重试,进行获取可用的服务。如多次获取某个服务失败,就不会再次获取该服务。主要是在一个时间段内,如果选择一个服务不成功,就继续找可用的服务,直到超时。

原理

  1. 拦截请求。
  2. 获取url。
  3. 通过url中 serviceName 获取 List。
  4. 通过负载均衡算法选取一个ServiceInstance。
  5. 替换请求,将原来url中的 serviceName换成ip+port。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小刘说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值