springcloud ribbon实现原理

一、ribbon  负载均衡原理

1.客户端负载均衡,通过LoadBalancerclient来实现,ILoadBalancer 通过配置IRule 和IPin 来实现

2.ILoadBalancer 通过每10s 获取一次Eureka 注册地址,获取到注册列表后按照IRule 注册规则进行负载均衡

二、核心原理拦截器

1.ribbon 的核心其实就是代理,通过拦截器的方式

2.拦截器实现的功能1:通过对请求的拦截,获取url ,解析hostname 通过hostname 再到Eureka 拿取真实的ip 端口,建立连接发送数据

3.拦截器实现的功能2:拿到目标服务的列表后,按照Rule规则选择具体的目标服务,从而实现负载均衡

 

三、代码的实现过程

spring启动过程

1.通过@Bean向spring中注入RestTemplete 对象

2.通过@LoadBanlance 注解,实现RestTemplete  注入拦截器,将自定义的拦截器注入RestTemplete  的拦截器链中

http调用过程

1.调用RestTemplete  调用目标服务交口(hostname+接口名称),RestTemplete 的拦截器会拦截该方法,从而对接口修改和增强,把url地址改为(ip+端口+接口名称) 

2.完成规则获取以及ip端口准备后,就开始连接目标服务发送数据,连接是通过httpclient 实现,通过工厂类获取httpclient 连接对象

 

四、源代码

MyConfig 实现启动时给RestTemplete 绑定拦截器
@Configuration
public class MyConfig {

    
    // 需要使用 Autowired 注解注入所有被 @MyLoadBalanced 定义的 RestTemplate 配置 ,因为使用了 @Configuration
    // (required=false) 非必须的, 有没有都可以注入,正常运行
    @Autowired(required=false)
    @MyLoadBalanced
    private List<RestTemplate> tpls = Collections.emptyList();

    @Bean
    public SmartInitializingSingleton lbInitializing() {

        return new SmartInitializingSingleton() {

            public void afterSingletonsInstantiated() {

//                System.out.println(tpls.size());
                
                for (RestTemplate restTemplate : tpls) {
                    
                    List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
                    interceptors.add(new MyInterceptor());
                    //interceptors.add(new MyInterceptor2());
                    restTemplate.setInterceptors(interceptors);
                }

            }
        };
    }
}
MyInterceptor 拦截器类,实现url转化及规则处理
public class MyInterceptor implements ClientHttpRequestInterceptor {


    public ClientHttpResponse intercept(HttpRequest request, byte[] body,
            ClientHttpRequestExecution execution) throws IOException {

        System.out.println("####这是自定义拦截器####");
        System.out.println("***********旧的 URI:" + request.getURI());
        
        HttpRequest newRequest = new MyRequest(request);
        System.out.println("&&&&&&&&&&&&新的 URI:" + newRequest.getURI());
        
        return execution.execute(newRequest, body);
    }
MyRequest  封装的新的httpRequest类(ip+端口)
public class MyRequest implements HttpRequest {

    HttpRequest sourceRequest;
    
    public MyRequest(HttpRequest sourceRequest){
        this.sourceRequest = sourceRequest;
    }
    
    public HttpHeaders getHeaders() {

        return sourceRequest.getHeaders();
    }

    public HttpMethod getMethod() {
        
        return sourceRequest.getMethod();
    }

    public URI getURI() {

        try {
            URI newUri = new URI("http://localhost:8086/hello");
            
            return newUri;
        } catch (URISyntaxException e) {

            e.printStackTrace();
        }
        
        return sourceRequest.getURI();
    }

}
MyController  客户端controller
@RestController
@Configuration
public class MyController {

    @Resource(name="tplA")
    RestTemplate restTemplate;

    @RequestMapping(value="/call", method=RequestMethod.GET)
    public String call(){

        return restTemplate.getForObject("http://hello-service/call4", String.class);
    }
    
    @RequestMapping(value="/hello", method=RequestMethod.GET)
    public String hello(){
        
        return "hello word";
    }
}
RestTplApp  启动类,把restemplete 注入spring容器以及配置负载均衡标记
@SpringBootApplication
public class RestTplApp {

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

    @Bean
    //@MyLoadBalanced
    RestTemplate tplA(){

        return new RestTemplate();
    }

    @Bean
    @MyLoadBalanced
    RestTemplate tplB(){

        return new RestTemplate();
    }
}

五、ribbon的负载均衡算法
1.RoundRobinRule轮询(默认的算法)
2.RandomRule 随机
3.AvailabilityFilteringRule 优先过滤一部分算法,被过滤的是多次访问故障处于断路器状态的服务,以及并发连接数量超过阈值的服务,然后执行轮询算法
4.WeightedResponseTimeRule 响应时间权重算法,响应时间越短,权重越大,被调用的机会越大
5.RetryRule 轮询算法重试,如果轮询失败,则在有限时间内重试
6.BestAvailableRule 并发量算法,优先过滤掉熔断的服务,然后再选择并发量最小的连接
7.ZoneAvoidanceRule 复合算法,计算server的可用性,从而选取最有

六、ribbon 负载算法代码配置
//配置负载均衡的策略为随机,默认算法为轮询算法
    @Bean
    public IRule myRule()
    {
        //return new RoundRobinRule();
        return new RandomRule();  
    }      

 

 

源码地址:https://github.com/197wj/Ribbon

posted @ 2021-03-06 17:14  狭路相逢智者胜  阅读(2040)  评论(0编辑  收藏  举报