Лента - это проект с открытым исходным кодом, выпущенный Netflix. Его основная функция заключается в предоставлении алгоритмов балансировки программного нагрузки на стороне клиента для соединения сервисов среднего уровня Netflix. Компонент клиента Ribbon предоставляет серию полных элементов конфигурации, таких как тайм -аут подключения, повторная попытка и т. Д. Проще говоря, он должен перечислить все машины, стоящие за балансировщиком нагрузки (LB для короткого) в файле конфигурации. Лента автоматически поможет вам подключить эти машины на основе определенных правил (таких как простой опрос, мгновенное соединение и т. Д.). У нас также есть очень простой способ реализовать пользовательские алгоритмы балансировки нагрузки с использованием ленты.
Когда дело доходит до балансировки нагрузки, вы обычно думаете о балансировке нагрузки на сервере. Обычно используемые продукты включают аппаратные или облачные сервисы LBS, NGINX и т. Д., Которые являются знакомыми продуктами.
Spring Cloud предоставляет ленту, которая позволяет вызывающему абоненту иметь возможности балансировки нагрузки. Благодаря тесной интеграции с Eureka, в сервисном кластере нет необходимости настраивать сервисы балансировки нагрузки, что значительно упрощает архитектуру в кластере обслуживания.
Я не хочу подробно писать больше виртуальных представлений, в любом случае, я вижу соответствующие представления повсюду.
Просто откройте код и посмотрите, как лента реализована через код.
Конфигурация
Подробное объяснение:
1. Конфигурация ленточной ленточной ленты генерирует экземпляр RibbonloadBalancerClient.
Расположение кода:
Spring-Cloud-Netflix-Core-1.3.5.Release.jar
org.springframework.cloud.netflix.ribbon
Ribbonautoconfiguration.class
@Configuration@condityalonclass ({iclient.class, resttemplate.class, asyncresttemplate.class, ribbon.class})@Ribbonclients@autoconfigurefferter (name = "org.springframework.cloud.netflix.eureka.eurekaclientautoconfiguration")@autoconfigurebefore ({loadbalancerautoconfiguration.class, asynclablancerautoconfiguration.class})@enableconfigurationproperties (ribboneagropguration.class})@enableconfigurationproperties (ribboneagropertropertroperts. Ribbonautoconfiguration {// опустить @bean @conditionalonmissingbean (loadbalancerclient.class) public loadbalancerclient loadbalancerclient () {return new ribbonlablancecurcerclient (springclientFactory ()); } // пропускать}Давайте сначала рассмотрим условия конфигурации. Конфигурация Ribbonautoconfiguration должна быть выполнена до конфигурации LoadBalancerautoConfiguration, поскольку в конфигурации LoadBalanCeraUtoConfiguration будет использоваться экземпляр RibbonloadBalancerClient.
RibbonLoadBalancErclient наследует от интерфейса LoadBalancerClient, является клиентом балансировки нагрузки и вызывающим абонент политики балансировки нагрузки.
2. Нагрузка BalancerInterceptorConfig Generation Generation:
1). Нагрузка балансировочного экземпляра
Включать:
Ленточный экземпляр вступления в лент.
LoadBalanCerRequestFactory: экземпляр
2) .RestTemplate Custom ResttemplateCustomizer экземпляр
Расположение кода:
Spring-Cloud-Commons-1.2.4.Release.jar
org.springframework.cloud.client.loadbalancer
LoadBalancerautoconfiguration.class
@Configuration@condentalonclass (resttemplate.class) @conditionalonbean (loadbalancerclient.class) @enableconfigurationproperties (loadbalancerretretryproperties.class) Общедоступный класс Buldbalancerautoconfiguration {// omit @bonditionalonmissingbeanbeanceconfiguration {// omit @bonditionalonmissingbeanbeancerquerquerquerque LoadBalanCerRequestFactory (LoadBalanCERCLIENT LOADBANCERCERCLIENT) {вернуть новый LoadBalanCerRequestFactory (LoadBalancerClient, Transformers); } @Configuration @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate") static class LoadBalancerInterceptorConfig { @Bean public LoadBalancerInterceptor ribbonInterceptor( LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) { return new LoadBalancerInterceptor (LoadBalancErclient, requestFactory); } @Bean @conditionalonmissingbean public resttemplatecustomizer resttemplatecustomizer (final LoadBalancerInterceptor LoadBalancerInterceptor) {return new ResttemplateCustomizer () {@Override public void customize (resttemplate restteplate) {listhttprequestinter rest -rest -letmletrate) {listhttprequestintertrecter> restteplate) {listhttprequestr resttemplate.getInterceptors ()); list.add (loadbalancerinterceptor); RESTTEMPLATE.SetInterceptors (список); }}; }} // опущенное}Давайте сначала рассмотрим условия конфигурации:
Требуется, чтобы в проектной среде был класс Resttemplate.
Требуется, чтобы существовал экземпляр класса реализации интерфейса LoadBalancerClient, то есть ленточной ленточной лент, генерируемой на предыдущем этапе.
3. Настройте все экземпляры Resttemplate через ResttemplateCustomizer, созданный на вышеуказанном шаге, который должен установить перехватчик балансировки нагрузки в экземпляр Resttemplate.
Configuration@CondentalOnClass (resttemplate.class) @conditionalonbean (loadbalancerclient.class) @enableconfigurationproperties (loadbalancerretretryproperties.class) Общедоступный класс LoadBalanceraUtoConfiguration {// Omit @bean publicInitializingLectoringLateRestTATRATERTINATIARITIRATIRATIRITIARITIARITIRATIRATIRATIARITIARITIARITIARITIARITIARITIARITIARITIARITIARITIARITIAS Список <ResttemplateCustomizer> настройки) {return new SmartInitialializingleton () {@Override public void atefsingletonSintanted () {для (Resttemplate Resttemplate: LoadBalanceraUtoConfiguration.This.Resttemplates) {для (RestTemplateCustomizer: Customizer). }}}}}}}; } // Опустить @configuration @conditionalonmissingclass ("org.springframework.retry.support.retrytemplate") Static Class LoadBalancerEmptorConfig {@Bean publicalancerInterceptor ribboninterceptor (rateverAnclient ratebalclient, ratemberquestory ribboninterceptor) LoadBalancerInterceptor (LoadBalancErclient, requestFactory); } @Bean @conditionalonmissingbean public resttemplatecustomizer resttemplatecustomizer (final LoadBalancerInterceptor LoadBalancerInterceptor) {return new ResttemplateCustomizer () {@Override public void customize (resttemplate restteplate) {listhttprequestinter rest -rest -letmletrate) {listhttprequestintertrecter> restteplate) {listhttprequestr resttemplate.getInterceptors ()); list.add (loadbalancerinterceptor); RESTTEMPLATE.SetInterceptors (список); }}; }} // опущенное}RESTTEMPLATE.SetInterceptors (Список) Это место - место, где вводится перехватчик балансировки нагрузки.
На самом деле можно догадаться из этого места, что Resttemplate может построить соответствующие запросы для достижения балансировки нагрузки с помощью инъекционных перехватчиков.
Также можно увидеть, что вы можете настроить перехватчик для достижения других целей.
4. Конфигурация RibbonClientConfiguration генерирует экземпляр Zoneawareloadlancer
Расположение кода:
Spring-Cloud-Netflix-Core-1.3.5.Release.jar
org.springframework.cloud.netflix.ribbon
RibbonClientConfiguration.class
@Suppresswarnings ("temercation")@configururation@enableconfigurationproperties // Порядок здесь важен, последний должен быть по умолчанию, сначала должно быть необязательным // См. https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653@import( <okhttpribbonconfiguration.class, restclascbonconfiguration.class, httpclientribgonfiguration. Опустить @bean @conditionalonmissingbean public iloadbalancer Ribbonloadbalancer (iClientConfig Config, Serverlist <serer> ServerList, ServerListFilter <server> ServerListFilter, Irule Rule, iping Ping, ServerListupdater. this.propertiesfactory.get (iloadbalancer.class, config, имя); } вернуть новый zoneawareloadbalancer <> (конфигурация, правило, ping, serverlist, serverlistfilter, serverlistupdater); } // опущено}Zoneawareloadbalancer наследует от интерфейса iloadbalancer, который имеет метод:
/*** Выберите сервер из балансировщика нагрузки. * * @param Ключ объект, который может использовать балансировщик нагрузки, чтобы определить, какой сервер вернуть. null, если * балансировщик нагрузки не использует этот параметр. * @return Server выбран */ public Server Pickerserver (ключ объекта);
Zoneawareloadbalancer - это конкретный класс реализации балансировки нагрузки, а также класс балансировки нагрузки по умолчанию. Определенный экземпляр службы выбирается путем реализации метода выбора.
Перехват и запрос
1. Используйте Resttemplate для выполнения различных запросов, таких как Get и Post, все из которых реализованы с помощью метода DoExecute.
Расположение кода:
Spring-Web-4.3.12.Release.jar
org.springframework.web.client
Resttemplate.class
открытый класс Resttemplate Extends перехват, реализует Restoperations {// слегка защищенный <t> t doexecute (uri url, метод httpmethod, requestcallback requestcallback, responseextractor <t> responseextractor) throws restclientException {assert.notnull (url, '' url 'не обязательно должен быть null'); Assert.notnull (метод, «метод» не должен быть нулевым »); Clienthttpresponse response = null; try {clienthttprequest request = createrequest (url, method); if (requestCallback! = null) {requestCallback.dowitHrequest (request); } response = request.execute (); HandlerSponse (URL, метод, ответ); if (responseextractor! = null) {return responseextractor.extractdata (response); } else {return null; }} catch (ioException ex) {string resource = url.toString (); String Query = url.getRawQuery (); resource = (Query! = null? resource.substring (0, resource.indexof ('?'))): resource); бросить новый ResourceCcessException ("ошибка ввода/вывода на" + method.name () + "запрос/" " + resource +"/":" + ex.getMessage (), ex); } наконец {if (response! = null) {response.close (); }}} // опущенное}Различные поддерживаемые методы запроса HTTP в конечном итоге вызывают метод DoExecute, который вызывает метод создания для создания экземпляра запроса, и выполняет запрос, чтобы получить объект ответа.
2. Сгенерировать экземпляр запроса для создания завода
В предыдущем коде метод CreaterEquest вызывается для создания экземпляра запроса, который определяется в родительском классе.
Сначала организуйте основные отношения наследования:
Метод Createrequest фактически определяется в классе Httpaccessor Abstract.
Общественный абстрактный класс httpaccessor {private clienthttprequestfactory requestFactory = new SimpleClientHttPrequestFactory (); public void setRequestFactory (clientHttprequestFactory requestFactory) {assert.notnull (requestFactory, "clientHttpRequestFactory не должен быть нулевым"); this.requestfactory = requestFactory; } public clienthttprequestfactory getRequestFactory () {return this.RequestFactory; } защищенный клиент. if (logger.isdebugenabled ()) {logger.debug («создан» + method.name () + "запрос /" " + url +" /""); } return запрос; }}Вызовите метод GetRequestFactory в методе CreaterEquest, чтобы получить экземпляр запроса для создания завода. Фактически, getRequestFactory не определяется в текущем классе httpaccessor, но определяется в перехвате подкласса.
Общедоступный абстрактный класс перехват public void setInterceptors (list <clienthttprequestinterceptor> receptors) {this.interceptors = receptors; } public List <clientHttprequestInterceptor> getInterceptors () {return Interceptors; } @Override public clienthttprequestfactory getRequestFactory () {clientHttpRequestFactory delegate = super.getRequestFactory (); if (! collectionTils.isempty (getInterceptors ())) {return new rececpityTclientHttpRequestFactory (делегат, getInterceptors ()); } else {return delegate; }}}Я сделал небольшое действие здесь. Во -первых, я создал и получил фабрику SimpleClientHttPrequestFactory через класс httpaccessor. Эта фабрика в основном создает основные экземпляры запроса, когда нет перехватчика.
Во -вторых, когда существует инъекция перехвата, создайте фабрику перехвата. Эта фабрика создает экземпляр запроса с перехватчиком. Поскольку перехватчик балансировки нагрузки вводится, он создается на заводе перехвата.
3. Создайте экземпляр запроса через завод
При создании экземпляра это зависит от метода Createrequest Factory.
public class receptingclienthttprequestfactory extrablestsclienthttprequestfactorywrapper {private final List <Clienthttprequestinterceptor> Interceptors; public receptingClientHttpRequestFactory (clientHttprequestFactory requestFactory, list <clientHttprequestInterceptor> receptors) {super (requestFactory); this.interceptors = (Interceptors! = NULL? Interceptors: Collections. } @Override защищенный клиент. }}Это означает новый экземпляр перехвата
4. Запросите экземпляр, чтобы вызвать метод перехвата перехвата на нагрузку, введенный в этап конфигурации
На шаге 1 можно увидеть, что после создания экземпляра запроса запрос выполняется путем выполнения метода выполнения экземпляра запроса.
Clienthttprequest request = createrequest (url, method); if (requestCallback! = Null) {requestCallback.dowitHrequest (request);} response = request.execute ();Фактическим экземпляром запроса перехватывает Clienthttprequest, и Execute фактически находится в своем родительском классе.
Расположение определения класса:
Spring-Web-4.3.12.Release.jar
org.springframework.http.client
RececeptingClienthttprequest.class
Взгляните на их отношения наследства.
Метод ExecuteInternal, реализованный подклассом, фактически вызывается в методе выполнения.
Public Abstract Class AbstractClientHttpRequest реализует ClientHttprequest {Private Final Httpheaders Headers = new httpheaders (); Частный логический казненный = false; @Override public final httpheaders getheaders () {return (this.exected? Httpheaders.readonlyhttpheaders (this.headers): this.headers); } @Override public final outputStream getBody () бросает ioException {assertnotexecated (); вернуть Get BodyTenternal (this.Headers); } @Override public final ClientHttpresponse execute () бросает ioException {assertnotexecated (); Clienthttpresponse result = executeInternal (this.Headers); this.Exected = true; результат возврата; } protected void assertnotexecated () {assert.state (! this.execated, "clienthttprequest уже выполнен"); } Защищенный абстрактный выходной поток Get BodyTenternal (заголовки HTTPHEADERS) бросает ioException; Защищенная абстрактная клиент.На самом деле, это метод ExecuteInternal класса перехвата. В котором называется исполнение исполнителя перехвата. Пропустите уровень и определите, что если перехватчик был введен, вызывается метод перехвата перехватчика.
Перехватчик здесь на самом деле представляет собой экземпляр перехвата перехвата, балансирующий нагрузку, вводится в экземпляр Resttemplate на этапе конфигурации. Вы можете обратиться к шагу 2 этапа конфигурации выше.
Class reterceptingClienthttprequest extends AbstractBufferingClientHttpRequest {// oMit @Override защищен окончательный клиент. return requestExecution.execute (this, bufferedOutput); } Частный класс перехватчика public urceptingRequestexecution () {this.iterator = receptors.iterator (); } @Override public clienthttpresponse execute (httprequest, byte [] body) throws ioexception {if (this.iterator.hasnext ()) {clienthttprequestinterceptor nextInterceptor = this.TeRator.next (); вернуть nextInterceptor.Intercept (запрос, тело, это); } else {clienthttprequest delegate = requestFactory.createrEquest (request.geturi (), request.getMethod ()); for (map.Entry <string, list <string >> entry: request.getheaders (). for (String value: values) {delegate.getheaders (). add (entry.getkey (), value); }} if (body.length> 0) {streamutils.copy (body, delegate.getbody ()); } return delegate.execute (); }}}}5. Перехватчик балансировки нагрузки вызывает клиента балансировки нагрузки
В методе перехвата класса перехвата перехвата нагрузки класса LoadBalancerInterceptor используется метод выполнения класса реализации клиентского балансировки нагрузки.
Общедоступный класс LoadBalanCerInterceptor реализует ClientHttprequestInterceptor {private LoadBalancerclient LoadBalancer; Private LoadBalanCerRequestFactory RequestFactory; Public LoadBalancerInterceptor (LoadBalanCerclient LoadBalancer, LoadBalanCerRequestFactory requestFactory) {this.LoadBalancer = LoadBalancer; this.requestfactory = requestFactory; } public LoadBalancerInterceptor (LoadBalancerClient LoadBalancer) {// для обратной совместимости Это (LoadBalancer, New LoadBalanCerRequestFactory (LoadBalancer)); } @Override public clienthttpresponse receptept (final httprequest, окончательный байт [] тело, окончательный клиент, который можно получить, выбросить ioexception {final uri riginaluri = request.geturi (); String serviceName = OriginalUri.gethost (); Assert.state (ServiceName! = NULL, "Запрос URI не содержит действительного имени хоста:" + Originaluri); return this.loadbalancer.execute (ServiceName, requestFactory.createrEquest (запрос, тело, выполнение)); }}На шаге 1 фазы конфигурации вы можете увидеть, что класс реализации - ribbonloadbalancerclient.
6. Клиент балансировки нагрузки вызывает политику балансировки нагрузки, чтобы выбрать целевой экземпляр службы и инициировать запрос
В первом методе Execute и методе Getserver ribbonloadbalanclient мы видим, что на самом деле выбран метод выбора класса реализации Iloadbalancer и передается следующему объекту запроса, чтобы инициировать запрос.
Класс реализации балансировки нагрузки здесь-это экземпляр балансировщика нагрузки ZoneaWareloadBalancer, который по умолчанию, и внутренне выбирает услугу через политику балансировки.
Создание Zoneawareloadbalancer можно найти на шаге 4 фазы конфигурации.
Общедоступный класс Ribbonloadlancerclient реализует LoadBalancErclient {@Override public <t> t execute (string serviceId, loadbalancerRequest <t> запрос), выбросы ioException {iloadbalancer LoadBalancer = GetLoadBalancer (ServiceId); Сервер Server = GetServer (LoadBalancer); if (server == null) {бросить новое allodalstateException («Нет экземпляров для» + serviceId); } Ribbonserver ribbonserver = new Ribbonserver (ServiceId, Server, Issecure (Server, ServiceId), ServerIntrospector (serviceId) .getMetAdata (сервер)); return execute (serviceId, ribbonserver, request); } @Override public <t> t execute (string serviceId, serviceInstance serviceInstance, loadbalancerRequest <t> запрос) throws ioException {server server = null; if (ServiceInsing EncementOf RIBBONSERVER) {SERVER = (((RIBBONSERVER) SERVICEINSTANCE) .GETSERVER (); } if (server == null) {бросить new allogalstateException ("Нет экземпляров для" + serviceId); } RibbonloadBalancerContext context = this.clientFactory .getLoadBalanCerCONTEXT (serviceId); RibbonstatsRecorder StatsRecorder = new RibbonstatsRecorder (контекст, сервер); try {t returnval = request.apply (serviceInstance); statsRecorder.recordstats (returnVal); return returnval; } // поймать ioexception и reethrow, чтобы Resttemplate ведет себя правильно, поймайте (ioexception ex) {statsrecorder.recordstats (ex); бросить бывш; } catch (Exception ex) {statsRecorder.recordstats (ex); ReflectionUtils.rethrowruntimeexception (Ex); } return null; } // Слегка защищенный сервер getServer (iloadbalancer LoadBalancer) {if (loadbalancer == null) {return null; } return LoadBalancer.chooseServer ("по умолчанию"); // todo: лучшая обработка ключа} защищенного iloadbalancer GetLoadLancer (String ServiceId) {return this.clientFactory.getLoadBalancer (serviceId); } public Static Class Ribbonserver реализует ServiceInstance {Private Final String ServiceId; частный конечный сервер сервера; Частный финальный логический защитный; частная карта <строка, строка> метаданные; public ribbonserver (String serviceId, сервер сервера) {this (serviceId, server, false, collections. <String, String> umptyMap ()); } public Ribbonserver (String ServiceId, сервер, сервер, Boolean Secure, Map <String, String> Metadata) {this.serviceid = serviceId; this.server = server; this.secure = secure; this.metadata = метаданные; } // опущено}}После окончания кода давайте обобрим его.
При использовании RestTemplate для запроса других услуг регулярный экземпляр HTTP -запроса используется внутренне для отправки запросов.
После добавления аннотации @loanbalanced в Resttemplate, на самом деле, посредством конфигурации, перехватчик балансировки нагрузки вводится в Resttemplate, что позволяет балансировщику нагрузки выбирать соответствующую службу в соответствии с соответствующей политикой перед отправкой запроса.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.