Spring Cloud Alibaba Ribbon组件的使用

Ribbon组件在Spring Cloud的作用是实现负载均衡,这里简单的说一下负载均衡的概念,负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。如下图:

 Nacos为我们提供了注册中心和配置中心,在集群模式下,Ribbon可以将请求通过一些策略分摊到各个Nacos,在讲具体实现之前,先来简单的自定义模拟一下负载均衡的实现:

自定义模拟负载均衡:

创建两个服务提供者工程:

ribbon_provider_1

pom依赖:导入nacos启动器和springboot的web启动器,同时注入common公共属性工程(这里不展示,common工程只声明了一个User实体类)

         <!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

配置文件:application.yaml

server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.40.141:8848
  application:
    name: ribbon-provider

controller:

@RestController
@RequestMapping("/provider")
public class ProviderController {
    @Autowired
    private UserService userService;

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id){
        return userService.getUserById(id);
    }
}

service:

public interface UserService {
    User getUserById(Integer id);
}
@Service
public class UserServiceImpl implements UserService {

    @Override
    public User getUserById(Integer id) {
        return new User(id,"张三-1",18);
    }
}

启动类:

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApp {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApp.class,args);
    }
}

ribbon_provider_2:

配置文件:application.yaml

server:
  port: 9091
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.40.141:8848
  application:
    name: ribbon-provider

Controller、Service与启动类和ribbon_provider_1保持一致(Service稍作区分,打印的User对象name属性为"张三-2")

创建服务消费者ribbon_consumer:

pom依赖(与ribbon_provider一样):

         <!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

application.yaml配置文件

server:
  port: 80
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.40.141:8848
  application:
    name: ribbon-consumer

controller:

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

    //访问Rest服务的客户端
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    private int currentIndex;

    @RequestMapping(value = "/getUserById/{id}")
    public User getUserById(@PathVariable  Integer id){
        //获取nacos中注册的指定服务信息
        List<ServiceInstance> serviceList = discoveryClient.getInstances("ribbon-provider");
        //通过Random工具类获取随机数
        currentIndex = new Random().nextInt(serviceList.size());
        //随机获取服务
        ServiceInstance serviceInstance = serviceList.get(currentIndex);
        //拼接访问服务的url
        String serviceUrl = serviceInstance.getHost() + ":" + serviceInstance.getPort();
        String url = "http://"+serviceUrl+"/provider/getUserById/"+id;
        //调用服务
        return restTemplate.getForObject(url,User.class);
    }
}

配置类(注册RestTemplate到ioc容器):

@Configuration
public class ConfigBean {

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

启动类:

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class,args);
    }
}

启动消费者跟提供者工程,然后启动nacos服务,浏览器进入nacos后台(关于nacos上篇文章已详细记载)查看注册的服务

 看到服务提供者实例数为2,服务消费者实例数为1,注册成功!

访问localhost/consumer/getUserById/1测试

查看响应结果是访问了ribbon_provider_2

继续刷新(这里模拟的策略为随机,可能连续几次访问的都是ribbon_provider_2)

 负载均衡的随机分配模拟成功!

Ribbon入门使用:

首先,nacos里面已经集成了ribbon,所以不用额外的再去引入依赖。

Ribbon实现负载均衡的核心在于IRule接口,这个接口给出了负载均衡的规范,并且官方提供了多个实现类,每个实现类可以近似的看做是负载均衡的一个实现策略。

如上图中的RandomRule就是随机分配策略,RoundRobinRule是轮询策略

简单的看下RandomRule源码如何实现:

    //该注解的作用是告诉JVM,忽略掉一些警告信息
    @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        } else {
            Server server = null;

            while(server == null) {
                if (Thread.interrupted()) {
                    return null;
                }
                //获取所有服务的列表
                List<Server> upList = lb.getReachableServers();
                List<Server> allList = lb.getAllServers();
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }
                //调用自身的chooseRandomInt方法获取一个随机数
                int index = this.chooseRandomInt(serverCount);
                //通过随机索引获取服务
                server = (Server)upList.get(index);
                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }

                    server = null;
                    Thread.yield();
                }
            }

            return server;
        }
    }
    
    //生成随机数的方法
    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

 源码中的核心业务逻辑跟模拟随机分配的实现很相似,都是获得所有服务的列表再通过随机索引去获取服务并调用。

 了解这些原理后,改造一下上面的模拟实现案例,通过Ribbon来实操一波。

1.修改ribbon_consumer的ConfigBean配置类:

在RestTemplate的注册方法上加上@LoadBalanced注解,这样在通过ioc容器获取restTemplate对象时,Ribbon会通过拦截器将请求拦截并处理,拿到注册中心的所有可用服务,通过获取到的服务信息(ip,port)替换掉serviceId,同时在ioc容器中查找IRule是否已注册,如果已注册则根据IRule的类型来实施负载策略,否则通过实施默认策略。

    @Bean
	/**
	 * 添加了@LoadBalanced注解之后,Ribbon会给restTemplate请求添加一个拦截器,在拦截器中获取
	 * 注册中心的所有可用服务,通过获取到的服务信息(ip,port)替换 serviceId 实现负载请求。
	 */
	@LoadBalanced //开启负载均衡
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}

	//随机策略
	@Bean
	public IRule iRule() {
		return new RandomRule();
	}

修改ribbon_consumer的controller:

@RequestMapping(value = "/getUserById/{id}")
    public User getUserById(@PathVariable("id")  Integer id){
        //在ribbon中不再使用host + ":" + port的方式获取url,而是通过serviceId(nacos中注册服务的名称)查找
        String serviceUrl = "ribbon-provider";
        String url = "http://"+serviceUrl+"/provider/getUserById/"+id;
        //调用服务
        return restTemplate.getForObject(url,User.class);
    }

 启动测试:

浏览器的地址栏输入localhost/consumer/getUserById/2测试访问

 至此Ribbon的入门案例结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。 主要功能服务限流降级:默认支持 WebServlet、 WebFlux, OpenFeign、 RestTemplate、 Spring CloudGateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有Worker(schedulerx-client)上执行。阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值