[TOC]java
以前咱們介紹了管理分佈式組件註冊的服務;eureka、consul、zookeeper、nacos他們均可以實現咱們服務的註冊於獲取。
可是實際咱們仍是須要咱們本身調用最終的客戶端獲取數據的。
localhost/order/payment/123
這個接看看響應是不是負載均衡的。
ClientHttpRequestInterceptor
攔截器。@Bean public LoadBalancerInterceptor ribbonInterceptor( LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) { return new LoadBalancerInterceptor(loadBalancerClient, requestFactory); }
LoadBalanced
標準的RestTemplate。遍歷全部RestTemplate誒個注入咱們LoadBalancerInterceptor攔截器。在這個攔截器內部會實現服務列表獲取。而後負載均衡。LoadBalancerAutoConfiguration
配置類。經過名稱咱們大概也能瞭解到這個類是配置負載均衡的自動配置類。
Allows applications to transform the load-balanced {@link HttpRequest} given the chosen
org.springframework.beans.factory.annotation
包下。瞭解Spring的讀者應該知道這是spring注入類的一種方式。關於spring注入方式解析咱們單獨開篇分析下。這裏咱們只用記住@Qualifier會注入相同屬性的bean.
SmartinitializingSingleton
和LoadBalancerRequestFactory
。關於LoadbalancerRequestFactory
這實際就是個工廠。在構造LoadBalancerIntercrptor
攔截器的時候須要用到。SmartInitializingSingleton
這個類。裏面傳了一個參數經過ObjectProvider封裝的。ObjectProvider
的做用能夠簡單理解爲@Autowired
。而內部的RestTemplateCustomer
就是咱們上文提到的做用是爲了封裝RestTemplate
。customizer.customize
就是調用添加攔截器了。
RetryLoadBalancerInterceptor
攔截內部實現裏實際上就是RetryTemplate和RestTemplate的區別。
LoadBalancedRetryPolicy
設置的。public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor
spring
LoadBalancerInterceptor
這個攔截器不難發現。他就是實現了ClientHttpRequestIntrceptor
。這裏咱們記住這個接口。在RestTemplate調用的時候確定會設計到ClientHttpRequestInterceptor
這個類。http://localhost/order/getpayment/123
。springboot
@Override @Nullable public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException { RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); }
InterceptingClientHttpRequestFactory
這個類中的createRequest方法上。
InterceptingClientHttpRequest
對象會在攔截器部分阻塞。因此這裏咱們不難看出上面Ribbon實現的LoadBalancerInterceptor。這個攔截器內部確定須要實現接口的調度。
public interface LoadBalancerClient extends ServiceInstanceChooser { <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException; <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException; URI reconstructURI(ServiceInstance instance, URI original); }
ILoadBalancer
來實現負載均衡的。說實話筆者這裏爲了省事並無落實ILoadBalancer
和LoadBalancerClient
之間是如何綁定的。BaseLoadBalancer
對ILoadBalancer
的實現。裏面重要的是chooseServer
這個方法。public Server chooseServer(Object key) { if (counter == null) { counter = createCounter(); } counter.increment(); if (rule == null) { return null; } else { try { return rule.choose(key); } catch (Exception e) { logger.warn("LoadBalancer [{}]: Error choosing server for key {}", name, key, e); return null; } } }
RoundRobbinRule
中就是經過AtomicInteger原子類操做請求次數在於容器數量取模決定獲取哪一個容器進行調用的。public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { log.warn("no load balancer"); return null; } Server server = null; int count = 0; while (server == null && count++ < 10) { List<Server> reachableServers = lb.getReachableServers(); List<Server> allServers = lb.getAllServers(); int upCount = reachableServers.size(); int serverCount = allServers.size(); if ((upCount == 0) || (serverCount == 0)) { log.warn("No up servers available from load balancer: " + lb); return null; } int nextServerIndex = incrementAndGetModulo(serverCount); server = allServers.get(nextServerIndex); if (server == null) { /* Transient. */ Thread.yield(); continue; } if (server.isAlive() && (server.isReadyToServe())) { return (server); } // Next. server = null; } if (count >= 10) { log.warn("No available alive servers after 10 tries from load balancer: " + lb); } return server; }
-Ribbon爲咱們提供了不少中內置的負載均衡策略。經常使用的就是輪詢。若是上述的不知足咱們也能夠經過實現Irule來自定義策略規則。網絡
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
來指定咱們的服務下負載策略。