天天看点

Ribbon一、Ribbon 介绍Ribbon搭建(不含Eureka)二、@LoadBalance 分析三、restTemplate其他的注意点四、 总结

01深度解析Spring Cloud [email protected]如何生效

  • 一、Ribbon 介绍
  • Ribbon搭建(不含Eureka)
    • 1.先创建两个服务,用于负载均衡
    • 2. 创建一个 调用方来请求这个接口
    • 3.验证
  • 二、@LoadBalance 分析
    • 1. @LoadBalance 只是一个 标注
    • 2. RestTemplate 的结构
    • 3. 推测
  • 三、restTemplate其他的注意点
    • 1. 拦截器循环执行
  • 四、 总结

一、Ribbon 介绍

Ribbon 是客户端负责负载均衡,和 Nginx 不同,Nginx 是 服务端负载均衡,Ribbon 一般都是从Eureka获取服务实例列表,然后根据配置的负载均衡算法,选择一个 服务器来执行请求。
           

Ribbon搭建(不含Eureka)

1.先创建两个服务,用于负载均衡

Server 1 和Server2 的端口号要不同,不然起不来

Server 1接口如下:

@RestController
public class TestController {

    @GetMapping("/user/{id}")
    public String Info(@PathVariable Long id) {
        return "this is client1 ,id=" + id;
    }
}
           

Server 2接口如下:

@RestController
public class TestController {

    @GetMapping("/user/{id}")
    public String Info(@PathVariable Long id) {
        return "this is Client2,id=" + id;
    }
}
           

启动类都是一样的,如下:

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

2. 创建一个 调用方来请求这个接口

配置启动类,并注入 RestTemplate

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;

@EnableScheduling
@SpringBootApplication
public class Application {

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

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

配置一下 application.properties,如下:

ribbon-test.ribbon.listOfServers=127.0.0.1:2223,127.0.0.1:2222
# ribbon连接超时
default-test.ribbon.ConnectTimeout=500
# ribbon读超时
default-test.ribbon.ReadTimeout=8000

######## management ########
management.security.enabled=false
endpoints.health.sensitive=false
           

3.验证

再创建一个 测试方法来验证是否生效,放在test 目录下面,代码如下:

import com.test.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class RibbonBalanceClientTest {
    @Autowired
    private RestTemplate restTemplate;
    @Test
    public void contextLoads() {
        for (int i = 0; i < 10; i++) {
            String forObject = restTemplate.getForObject("http://ribbon-test/user/1000", String.class);
            System.out.println("============================");
            System.out.println(forObject);
        }
    }
}
           

先启动 两个server ,然后在 测试 测试类 ,结果如下:

Ribbon一、Ribbon 介绍Ribbon搭建(不含Eureka)二、@LoadBalance 分析三、restTemplate其他的注意点四、 总结

从结果可以看出实现了负载均衡,默认是 轮询策略,Client1和 clien2 依次调用.

二、@LoadBalance 分析

1. @LoadBalance 只是一个 标注

从上面的代码看,我们只是在 RestTemplate上面加了一个 @LoadBalance,就可以实现 负载均衡了,可是我们 点击进入 @LoadBalance看了一下,空的,就是一个 标记注解,突然就懵了,怎么实现的呢,从哪里 开始入手源码的分析呢…

Ribbon一、Ribbon 介绍Ribbon搭建(不含Eureka)二、@LoadBalance 分析三、restTemplate其他的注意点四、 总结

2. RestTemplate 的结构

我们继续点击 RestTemplate 类,查看其结构,如下:

Ribbon一、Ribbon 介绍Ribbon搭建(不含Eureka)二、@LoadBalance 分析三、restTemplate其他的注意点四、 总结

从 结构图上 可以看出,RestTemplate 实现了 InterceptinghHttpAccessor,划重点 ,进入 InterceptinghHttpAccessor 里面,可以看到:

  1. 里面有一个 拦截器List
  2. 重写了getRequestFactory ,里面加了一个 判断,如果有 拦截器,那么 就 new InterceptingClientHttpRequestFactory 对象
    Ribbon一、Ribbon 介绍Ribbon搭建(不含Eureka)二、@LoadBalance 分析三、restTemplate其他的注意点四、 总结

3. 推测

看到这里 ,其实 结果已经开始浮出水面,如果我们对 RestTemplate 的interceptors 加一个拦截器,不就可以实现负载均衡了嘛,我们可以看一下 InterceptingHttpAccessor 的 setInterceptors 这个方法在哪里被调用了. 果然我们看到了 在LoadBalancerAutoConfiguration的Bean配置类 里面被调用了,

Ribbon一、Ribbon 介绍Ribbon搭建(不含Eureka)二、@LoadBalance 分析三、restTemplate其他的注意点四、 总结

这样就 进一步证明了我们的猜测,原理也是这样的.下一章 就开始分析 LoadBalancerAutoConfiguration这个配置类,和 具体的拦截内容.

三、restTemplate其他的注意点

1. 拦截器循环执行

在 InterceptingClientHttpRequest 里面里面的 InterceptingRequestExecution 里面的 execute 执行时 ,代码如下:

Ribbon一、Ribbon 介绍Ribbon搭建(不含Eureka)二、@LoadBalance 分析三、restTemplate其他的注意点四、 总结

在这里 ,很多人会认为 这里获取 iterator.next(),然后执行一遍就退出了,其实不止,这里是把所有的拦截器都 运行了. 关键在于 :第三个参数 是把本身传入进去了。

Ribbon一、Ribbon 介绍Ribbon搭建(不含Eureka)二、@LoadBalance 分析三、restTemplate其他的注意点四、 总结

执行了 intercept 方法之后,里面 又调用了 execution.execute() 方法,这个有点 像 隐式 的 递归 ,注意一下.

四、 总结

本文主要是 介绍如何搭建简单Ribbon,以及怎样入手源码的分析,另外介绍了RestTemplate 的一个注意点,接下来继续分析其流程原理,此外,所有的配置 可以查看 CommonClientConfigKey.class 里面的属性,详细介绍 在下一章02深度解析Spring Cloud Ribbon—LoadBalancerAutoConfiguration拦截器注入

继续阅读