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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM