负载均衡-ribbon

1. 能干啥?

官方说法:Spring Cloud Ribbon 是 基于 Netflix Ribbon 实现的一套客户端的负载均衡工具,Ribbon 客户端组件提供一系列的完善的配置,如超时,重试等。通过 Load Balancer(LB)获取到服务提供的所有机器实例,Ribbon 会自动基于某种规则(轮询,随机)去调用这些服务。Ribbon 也可以实现我们自己的负载均衡算法;

个人简述:用户的一个请求,多个服务可以处理,以下问题的解决;

选择哪一个服务进行处理;

如果高效使用所服务资源;

怎样保证响应速度;

2. 怎么玩?

2.1 项目搭建

spring-boot 项目初始化

2.2 引入ribbon

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
			<version>2.1.3.RELEASE</version>
		</dependency>
复制代码

2.3 配置

这里为了简单,不采用注册中心形式

server.port=18090
eat.ribbon.eureka.enabled=false
eat.ribbon.listOfServers=http://localhost:18091,http://localhost:18092
复制代码

注: http://localhost:18091http://localhost:18092 服务可以自行创建,也可以直接使用参见中的源码项目

eat 服务的负载均衡代码

核心配置:@LoadBalanced

@Configuration
public class RibbonConfig {

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
复制代码

controller 使用

@RestController
@RequestMapping("/eat")
public class EatController {

    @Autowired
    private RestTemplate restTemplate;

    @PostMapping("/fruit1")
    public String eatFruit(){
        return restTemplate.postForObject("http://eat/eat/fruit",null,String.class);
    }
}
复制代码

注:restTemplate 使用规则:http:// 服务名 / {服务名}/ {请求uri}

2.4 使用

访问: localhost:18090/eat/fruit1

I eat fruit on 18091

I eat fruit on 18092

交替出现,默认区域负载均衡策略生效;

2.5 修改默认负载均衡策略

自定义策略:一台机器执行5次后,下一台开始执行5次,依次轮询;

继承AbstractLoadBalancerRule实现自定义规则

public class YiRule extends AbstractLoadBalancerRule {

    /** 总共被调用的次数,目前要求每台被调用5次 */
    private int total = 0;
    /** 当前提供服务的机器号 */
    private int currentIndex = 0;

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            //激活可用的服务
            List<Server> upList = lb.getReachableServers();

            if (total < 5) {
                server = upList.get(currentIndex);
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= upList.size()) {
                    currentIndex = 0;
                }
            }
            if (server == null) {
                Thread.yield();
                continue;
            }

            if (server.isAlive()) {
                return (server);
            }

            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }
        return server;
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }
}
复制代码

仅对eat 服务配置此规则

@RibbonClient(name = "eat",configuration = YiRule.class)
@SpringBootApplication
public class YiyiRibbonConsumerApplication {

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

}
复制代码

可以自行debug 查看是否走自定义策略;

3. 分析原理

分析ribbon原理,铁定是要看源码的,这里我们从两个角度去看;

请求链路流转

从这个角度看,我们debug 即可;

debug 目的:

1) 找到两个服务是何时加载的;
2) 哪个地方将 eat 服务替换成了 服务示例 localhost:1808x;

ribbon配置加载

LoadBalancerAutoConfiguration

spring-cloud 中的负载均衡扩展配置 ;

RibbonAutoConfiguration

ribbon 核心配置加载;

配置+时序图

下图展示了请求时序图,结合配置我们可以看出:

ribbon 是 spring-cloud-common 提供的 LoadbalancerClient 上的实现,即LoadbalancerClient是ribbon 的入口,后续的处理就是ribbon 的个性实现;

参见

Ribbon源码分析系列(一)

Ribbon 使用及其内核原理剖析

本文示例代码-github链接

おすすめ

転載: juejin.im/post/7041390960588259342
おすすめ