4. SpringCloud组件之Ribbn

Ribbon

  • 我们启动了一个justweb-service-provider,然后通过DiscoveryClient来获取服务实例信息,然后获取ip和端口来访问。

  • 但是实际环境中,我们往往会开启很多个justweb-service-provider的集群。此时我们获取的服务列表中就会有多个,到底该访问哪一个呢?

  • 一般这种情况下我们就需要编写负载均衡算法,在多个实例列表中进行选择。

  • Eureka中已经帮我们集成了负载均衡组件:Ribbon,简单修改代码即可使用。

1. Ribbn简介

在这里插入图片描述

  • 轮询
  • 随机

2. 启动两个服务实例

首先参照justweb-eureka启动两个justwebServiceProviderApplication实例,一个8081,一个8082。

Eureka监控面板:

在这里插入图片描述

3. 开启负载均衡

因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖,直接修改代码。修改justweb-service-consumer的引导类,在RestTemplate的配置方法上添加@LoadBalanced注解

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

修改调用方式,不再手动获取ip和端口,而是直接通过服务名称调用

@Controller
@RequestMapping("/consumer/user")
public class UserController {


    @Autowired
    private RestTemplate restTemplate;

    // eureka的客户端可以获取到eureka中的服务
    @Autowired
    private DiscoveryClient discoveryClient;


    @GetMapping
    @ResponseBody
    public User queryUserById(@RequestParam("id") Long id){
        // User user = this.restTemplate.getForObject("http://localhost/user/queryById/" + id, User.class);
        
        // 根据服务名称,获取实例,有可能是集群,所以service实例是个集合,从中取出第一个实例
        // ServiceInstance instance = discoveryClient.getInstances("SERVICE-PROVIDER").get(0);
        //String url = "http://"+instance.getHost()+":"+instance.getPort()+"/user/queryById/"+id;
        
        //service-provider
        String url = "http://service-provider/user/queryById/"+id;
        User user = this.restTemplate.getForObject(url, User.class);
        return user;
    }

}

4. 负载均衡策略

Ribbon默认的负载均衡策略是简单的轮询,我们可以测试一下:

编写测试类,在刚才的源码中我们看到拦截中是使用RibbonLoadBalanceClient来进行负载均衡的,其中有一个choose方法,找到choose方法的接口方法,是这样介绍的:

在这里插入图片描述

现在这个就是负载均衡获取实例的方法。

4.1 修改负载均衡的策略

接口IRule:定义负载均衡的规则接口。这里的IRule默值是一个RoundRobinRule,看类的介绍:

在这里插入图片描述

SpringBoot也帮我们提供了修改负载均衡规则的配置入口,在justweb-service-consumer的application.yml中添加如下配置:

  • 格式是:{服务名称}.ribbon.NFLoadBalancerRuleClassName,值就是IRule的实现类(properties格式)
service-provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

5. 源码跟踪

为什么我们只输入了service名称就可以访问了呢?之前还要获取ip和端口。显然有人帮我们根据service名称,获取到了服务实例的ip和端口。它就是LoadBalancerInterceptor

在如下代码打断点:
在这里插入图片描述

在这里插入图片描述

一路源码跟踪:RestTemplate.getForObject --> RestTemplate.execute --> RestTemplate.doExecute:

在这里插入图片描述

点击进入AbstractClientHttpRequest.execute --> AbstractBufferingClientHttpRequest.executeInternal --> InterceptingClientHttpRequest.executeInternal --> InterceptingClientHttpRequest.execute:
在这里插入图片描述

继续跟入:LoadBalancerInterceptor.intercept方法

在这里插入图片描述

继续跟入execute方法:发现获取了8082端口的服务

在这里插入图片描述

再跟下一次,发现获取的是8081:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值