微服务系列--Ribbon负载均衡

1、前言

这篇文章接上一篇文章进行开发,上一篇整合完了Nacos,这篇来整合Ribbon。Ribbon不属于SpringCloud Alibaba的东西,而是基于Netflix Ribbon实现的。可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。

2、核心注解

Rabbin的依赖不需要进行重复导入,因为我们上一篇在导入nacos的时候,其实就已经导入进来了,nacos引入的相关依赖里面,包含了ribbon的jar包。 

ribbon使用起来极其简单,用一个@LoadBalanced 注解就能实现基本的功能。在我们的RestTemplate Bean上增加注解,@LoadBalanced注解是属于Spring,而不是ribbon的,Spring在初始化容器的时候,如果检测到Bean被@LoadBalanced注解,Spring会为其设置LoadBalancerInterceptor的拦截器。

package com.chen.config;

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 ConsumerConfig {

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

}

3、配置负载均衡接口 

在controller里面新增一个接口,接口指定实例名和provider的接口名

package com.chen.controller;

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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/index")
    public String index(){
        List<ServiceInstance> provider = discoveryClient.getInstances("provider");
        int index = ThreadLocalRandom.current().nextInt(provider.size());
        String url = provider.get(index).getUri()+"/provider/index";
        return this.restTemplate.getForObject(url, String.class);
    }

    @GetMapping("/index_ribbon")
    public String index_ribbon(){
        return "ribbon均衡调用:"+this.restTemplate.getForObject("http://provider/provider/index", String.class);
    }

}

OK,自此,调一下接口测试一下,浏览器输入:localhost:8080/consumer/index_ribbon

发现就是这两个接口进行轮询调用

 ribbon如果不指定规则的话,那么就是默认轮询规则,按顺序依次调用。

4、设置随机规则

spring:
  cloud:
    nacos:
      discovery:
        # 配置nacos服务地址,如果不配置,默认是localhost:8848
        server-addr: localhost:8848
  application:
    name: consumer

server:
  port: 8080

provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

我这里设置了com.netflix.loadbalancer.RandomRule随机规则,继续调接口测试可以发现,现在已经变成无规律的了。

5、设置权重规则

在nacos可视化界面,服务详情里面,可以看到每一个实例都可以单独设置权重

顾名思义,改变了这个权重值,那么在调接口的时候,就会根据这个权重去随机调取某个实例的接口,权重值越大, 调取接口的概率越大。但是,改完之后再进行测试可以发现,这个权重值没有生效,这还需要我们重写AbstractLoadBalancerRule类的choose方法进行实现,代码如下:

package com.chen.config;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
        //读取配置文件
    }

    @Override
    public Server choose(Object o) {
        ILoadBalancer loadBalancer = this.getLoadBalancer();
        BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) loadBalancer;
        //获取要请求的微服务名称
        String name = baseLoadBalancer.getName();
        //获取服务发现的相关API
        NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
        try {
            Instance instance = namingService.selectOneHealthyInstance(name);
            log.info("选择的实例是port={},instance={}",instance.getPort(),instance);
            return new NacosServer(instance);
        } catch (NacosException e) {
            e.printStackTrace();
            return null;
        }
    }
}

然后,在yml文件里面把规则指向我们继承的这个规则类

spring:
  cloud:
    nacos:
      discovery:
        # 配置nacos服务地址,如果不配置,默认是localhost:8848
        server-addr: localhost:8848
  application:
    name: consumer

server:
  port: 8080

provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.chen.config.NacosWeightedRule

再次进行测试就会发现权重值已经生效。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

西瓜不甜柠檬不酸

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

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

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

打赏作者

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

抵扣说明:

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

余额充值