Исходный код ленты второй кисти

Java

Чем больше вы говорите, чем больше делаете, тем практичнее вы будете.

1. Базовые знания2. Основные компоненты ленты Netflix2.1 Список сервисов ServerList2.2 Фильтрация службы ServerListFilter2.3 Обновление списка сервисов ServerListUpdater2.4 Проверка работоспособности службы IPing2.5 IRule выбирает сервис по алгоритму2.6 ILoadBalancer: координатор, генеральный менеджер2.7 Настроить состав компонентов3. Основные компоненты SC-ленты (от Eureka)3.1 (Конфигурация) Конфигурация по умолчанию RibbonClientConfiguration3.2 (Конфигурация) Пользовательская конфигурация3.2.1 Аннотированный класс конфигурации3.2.1 Конфигурация в конфигурационном файле:3.3 (использование) SpringClientFactory3.4 (использование) LoadBalancerClient3. Что происходит, когда SC-Ribbon используется с eureka4. Как Resttemplate имеет возможности балансировки нагрузки5. Резюме

1. Базовые знания

Прежде всего, нам нужно понять базовые знания:

  • Netflix открыл исходный код для ряда компонентов микросервисов. адрес проектаgithub.com/Netflix. иметь внутриeureka,Ribbonи т.д

  • SpringCloud интегрирует несколько наборов пакетов с открытым исходным кодом Netfix, а также формирует проект, адрес проектаGitHub.com/spring - уродливо.... Мы знакомы с эврикой, лента здесь.

  • Ribbon — это проект с открытым исходным кодом, выпущенный Netflix, его основная функция — предоставление алгоритма балансировки нагрузки программного обеспечения на стороне клиента.

  • Модуль Spring Cloud Ribbon — это封装Проект Ribbon, разработанный Netflix.

то есть

  • Spring Cloud Ribbon — это набор инструментов для балансировки клиентской нагрузки, основанный на ленте Netflix.
  • Основная функциональность находится в проекте Netflix Ribbon.

Эта статья основана на версии Brixton, исходный код которой просматривается непосредственно в среде Springboot.

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Brixton.SR4</version>
        <type>pom</type>
        <scope>import</scope>
</dependency>ml

2. Основные компоненты ленты Netflix

начать сNetflix Ribbonточка зрения проекта

2.1 Список сервисов ServerList

Список сервисов хранения, то есть объектов для балансировки нагрузки

主要实现

  • ConfigurationBasedServerList: Статический список сервисов, который мы обычно называем мертвой записью, настраивается до запуска проекта.
  • DiscoveryEnabledNIWSServerList: список динамических сервисов, начиная сEureka Clientдля списка услуг.

2.2 Фильтрация службы ServerListFilter

Отфильтруйте список служб по определенным условиям и выполните вторичную фильтрацию в списке серверов ServerList.

主要实现:

  • AbstractServerListFilter
    Класс, отвечающий за фильтрацию списка доступных в данный момент серверов из балансировщика нагрузки.
  • ZoneAffinityServerListFilter: Отфильтровать все службы, которые не находятся в той же зоне, что и клиент (примечание: если той же зоны, что и клиент, не существует, не фильтровать службы в разных зонах).
  • ZonePreferenceServerListFilter:
  • ServerListSubsetFilter

2.3 Обновление списка сервисов ServerListUpdater

Определите действие обновления, выполните операцию обновления в соответствии с политикой, обновите список ServerList, обычно используемый для динамического списка серверов.

主要实现:

  • PollingServerListUpdater
    Стратегия реализации по умолчанию. Этот объект запускает синхронизированный пул потоков и регулярно выполняет стратегию обновления.

  • EurekaNotificationServerListUpdater
    Список служб обновляется при получении уведомления об обновлении кэша.

2.4 Проверка работоспособности службы IPing

проверить, жив ли сервис,

主要实现:

  • DummyPing: всегда думай живо
  • NoOpPing:ничего не делать
  • PingConstant: Укажите статус выживания сервера, установив параметр конфигурации
  • NIWSDiscoveryPing: возвращает true, если экземпляр службы существует в локальном кэше Eureka (конфигурация по умолчанию). Когда класс, предоставленный в пакете ленты-eureka, используется в сочетании с eureka, если клиент обнаружения находится в сети, считается, что обнаружение пульса прошло успешно.
  • PingUrl: Используйте HttpClient для вызова URL-адреса службы. Если вызов успешен, пульс считается успешным, что указывает на то, что служба активна.

IPing проверяет работоспособность службы.

IPingStrategy: интерфейс политики проверки списка сервисов,
Единственная реализация:SerialPingStrategy: Используя стратегию линейного обхода, IPing используется для проверки живучести каждого сервиса.

2.5 IRule выбирает сервис по алгоритму

Выберите услугу для доступа из списка услуг в соответствии с алгоритмом

主要实现:

  • RandomRule: случайный алгоритм
  • RoundRobinRule: стратегия ротации (`политика по умолчанию`)
  • RetryRule: Опрос + повтор, основанный на RoundRobinRule, добавлена ​​функция повтора.
  • WeightedResponseTimeRule: (非常好) при запуске статистика недостаточна, первое использованиеRoundRobinRuleСтратегия. имеетDynamicServerWeightTaskЗапланированные задачи, время ответа каждого экземпляра службы по умолчанию рассчитывается каждые 30 секунд, и когда статистики будет достаточно, переключитесь наWeightedResponseTimeRule.
  • BestAvailableRule: сначала отфильтруйте службы с включенным автоматическим выключателем, а затем выберите экземпляр службы с наименьшим одновременным запросом для использования. При запуске, если статистики недостаточно, используется стратегия RoundRobinRule, а когда статистики будет достаточно, переключится на BestAvailableRule.
  • PredicateBasedRule: фильтр + поворот
  • AvailabilityFilteringRule: (1) Автоматический выключатель сработал из-за множественных сбоев доступа (2) Количество одновременных подключений превышает пороговое значение (3) Оставшийся список услуг опрашивается

Резюме: мы видим, что вышеуказанный компонент является ссылкой на список сервисов (待负载对象)из定义操作. Но пусть работают вместе. Для этого требуется ILoadBalancer

2.6 ILoadBalancer: координатор, генеральный менеджер

Балансировщик нагрузки отвечает за управление планированием балансировки нагрузки на уровне менеджера.调度其他组件,完成从服务列表里获取一个服务的目标

Предоставьте внешний метод для выбора сервера.

public Server chooseServer(Object key);

Абстрактный класс: AbstractLoadBalancer main定义了服务的分组

主要实现:

1.BaseLoadBalancer: Базовая реализация балансировщика нагрузки. Обслуживание
(1) Вести список всех сервисов + список текущих выживших сервисов
(2) По умолчанию для выбора сервиса используется ротация.
(3) Определите таймер и регулярно проверяйте активность в соответствии с политикой SerialPingStrategy.

2.DynamicServerListLoadBalancerДинамическая версия обновления
(1) DomainExtractingServerList динамически получает список служб статуса UP от EurekaClient.
(2) ZoneAffinityServerListFilter фильтрует список
(3) PollingServerListUpdater регулярно обновляет службу
3.ZoneAwareLoadBalancer: Добавлена ​​политика зоны на основе DynamicServerListLoadBalancer.
(1) Этот класс использует ZoneStats для хранения статуса и среднего количества запросов каждой зоны. Региональные показатели как факторы, влияющие на выбор услуг

2.7 Настроить состав компонентов

С компонентами, какой метод комбинирования используется? Лента обеспечивает возможность настройки для пользователей.

Настройте различные эффекты балансировки нагрузки с помощью различных комбинаций компонентов.

Какие есть способы настройки:

  • Интерфейс IClientConfig: реализация по умолчаниюDefaultClientConfigImpl. Если вы не настроите никаких свойств, определенные здесь компоненты будут использоваться по умолчанию. Конечно, здесь есть и другие конфигурации различных свойств.
默认配置的组件有:
  • Конфигурация файла: когда мы заменяем конфигурацию по умолчанию, мы можем настроить различные свойства в файле конфигурации.
    Конфигурация формата атрибута выглядит следующим образом
<clientName>.<nameSpace>.<propertyName>=<value>
api-user.ribbon.listOfServers=localhost:8099

Таким образом: приблизительные компоненты Netfix-Ribbon и принцип работы понятны с первого взгляда.
адрес проектаGitHub.com/Netflix/Япония…

3. Основные компоненты SC-ленты (от Eureka)

SpringCloud-Ribbon объединяетNetflix Ribbon, чтобы интегрировать его в систему springcloud.

Основные функцииNetflix RibbonПроект находится в разработке. Пакет SC-лентыNetflix Ribbon, в основном для выполнения некоторой работы по интеграции.

С этой целью, какие компоненты SpringCloud-Ribbon добавлены и что они сделали?

思考: Поскольку основная функцияNetflix RibbonПроект находится в разработке. То, что делает этот проект, - это не что иное, как начало со следующих аспектов

  1. уровень конфигурации: В соответствии с привычками конфигурации системы Spring.
  2. уровень использования: Как использовать балансировщик нагрузки ленты

!!!!!注意注意: 此处说的是脱离Eureka使用SpringCloud-Ribbon

Рассмотрим проделанную для этого работу:

Работа на уровне конфигурации:

3.1 (Конфигурация) Конфигурация по умолчанию RibbonClientConfiguration

Этот класс конфигурации также существует как класс конфигурации по умолчанию, то есть когда вы ничего не настраиваете.SpringCloud-RibbonКомбинация основных компонентов, загружаемых по умолчанию,
по сравнению сNetflix RibbonпроектDefaultClientConfigImplПредусмотренные компоненты по умолчанию:

在这里插入图片描述
вставьте сюда описание изображения

3.2 (Конфигурация) Пользовательская конфигурация

На основе принципа расширяемости: SpringCloudRibbon также предоставляет персонализированные функции настройки.

3.2.1 Аннотированный класс конфигурации

Здесь задействованы две аннотации:@RibbonClientи@RibbonClients(обратите внимание, что естьs)

  • Функция этих двух классов аннотаций заключается в том, что классы, аннотируемые ими, будут передавать некоторый механизмRibbonClientConfigurationзаменить конфигурацию по умолчанию
  • Разница между этими двумя аннотациями заключается в следующем: одна охватывает компонент одной службы, а другая нацелена на несколько служб.

Используется следующим образом: я ставлюuserбалансировка сервисной нагрузкиIPingкомпоненты заменены на моиMyPingUrl.

Configuration
@RibbonClient(name = "user", configuration = UserConfiguration.class)
public class UserRibbonConfiguration {
}
@Configuration
protected static class UserConfiguration{
    @Bean
    public IPing ribbonPing() {
        return new MyPingUrl();
    }
}

Обратите внимание на добавление конфигурации в UserConfiguration. UserConfiguration должен быть объявлен с помощью @Configuration и не может быть размещен в месте, которое может быть просканировано с помощью @ComponentScan или @SpringBootApplication основного контекста приложения, что предотвращает совместное использование конфигурации всеми @RibbonClients.

Если вы хотите сбалансировать нагрузку на все сервисыIPingкомпоненты заменены на моиMyPingUrl

@RibbonClient(defaultConfiguration = UserConfiguration.class)
public class UserRibbonConfiguration {
}

Принцип работы:

Принцип работы этих двух аннотаций таков: вводяRibbonClientConfigurationRegistrarРегистратор, который регистрирует класс конфигурации какRibbonClientSpecification

@Configuration
@Import(RibbonClientConfigurationRegistrar.class)//这里
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RibbonClient {
}
//注册器
public class RibbonClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
        private void registerClientConfiguration(BeanDefinitionRegistry registry,
            Object name, Object configuration) {
            //注册为一个RibbonClientSpecification
        BeanDefinitionBuilder builder = BeanDefinitionBuilder
                .genericBeanDefinition(RibbonClientSpecification.class);
        builder.addConstructorArgValue(name);
        builder.addConstructorArgValue(configuration);
        registry.registerBeanDefinition(name + ".RibbonClientSpecification",
                builder.getBeanDefinition());
    }
}

RibbonClientSpecification: Буквально переведено в спецификацию клиента, да, ваша персонализированная конфигурация анализируется в спецификации клиента.

Пример:

  • Служба A и служба B используют одну и ту же персонализированную конфигурацию, службы A и B имеют однуRibbonClientSpecificationСпецификация
  • Служба C использует персонализированную конфигурацию, а служба C имеетRibbonClientSpecificationСпецификация

Как работает эта спецификация? увидеть ниже

3.2.1 Конфигурация в конфигурационном файле:

Другой - настроить его непосредственно в файле конфигурации в системе Spring.
application.yml

api-user:
  ribbon:
    NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList

Классы, определенные в этих свойствах, имеют приоритет над bean-компонентами, определенными с помощью @RibbonClient(configuration=MyRibbonConfig.class) и значениями по умолчанию, предоставляемыми Spring Cloud Netflix.

说了配置,在讲讲使用层面的工作

Используйте работу на уровне:
Использование функции балансировки нагрузки фактически вILoadBalancerна этом координирующем компоненте. Так называемое использование, собственно, и заключается в этом.ILoadBalancerначальство.

3.3 (использование) SpringClientFactory

SpringClientFactory использует фабричный режим для предоставления внешних сервисов: согласно serviceId, он получает сервисы таких объектов, как IClient, ILoadBalance и ILoadBalanceContext.

Здесь мы сосредоточимся только наILoadBalanceприобретение.

SpringClientFactory создает отдельный контекст для каждой службы и загружает в него соответствующую конфигурацию и классы реализации интерфейса Ribbon core. создать логику в своем родительском классеNamedContextFactory

public abstract class NamedContextFactory{
    private Map<String, C> configurations = new ConcurrentHashMap<>();
    private Class<?> defaultConfigType;
    //创建上下文
    protected AnnotationConfigApplicationContext createContext(String name) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        if (this.configurations.containsKey(name)) {
            for (Class<?> configuration : this.configurations.get(name)
                    .getConfiguration()) {
                context.register(configuration);
            }
        }
        for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
            if (entry.getKey().startsWith("default.")) {
                for (Class<?> configuration : entry.getValue().getConfiguration()) {
                    context.register(configuration);
                }
            }
        }
        context.register(PropertyPlaceholderAutoConfiguration.class,
                this.defaultConfigType);
        context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
                this.propertySourceName,
                Collections.<String, Object> singletonMap(this.propertyName, name)));
        if (this.parent != null) {
            // Uses Environment from parent as well as beans
            context.setParent(this.parent);
        }
        context.refresh();
        return context;
    }
}

Здесь есть два момента:

  1. По входящей службеserverIdСоздаватьAnnotationConfigApplicationContext, загрузите свой собственный пакет балансировки нагрузки. Разные сервисы имеют разные контексты, в которых хранится комбинация принадлежащих ему комплектов балансировки нагрузки.

  2. Способ составления набора услуг балансировки нагрузки. Это определяется двумя упомянутыми выше способами настройки. этоconfigurationsиdefaultConfigTypeСпецификация, представленная двумя свойствами.

    private Map<String, C> configurations = new ConcurrentHashMap<>();
    private Class<?> defaultConfigType;//代表默认的组件组合
  • конфигурации : представляет спецификацию комплекта для персонализированных конфигураций. упомянутый вышеRibbonClientSpecification
  • defaultConfigType : представляет класс конфигурации по умолчанию для sc-ленты.RibbonClientConfiguration

когда мы звонимSpringClientFactory.getLoadBalancerКогда метод получает экземпляр балансировщика нагрузки, суть сводится к получению принадлежащего ему сервиса в контексте, соответствующем сервису.ILoadBalancerвыполнить.

public <T> T getInstance(String name, Class<T> type) {
        AnnotationConfigApplicationContext context = getContext(name);
        if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
                type).length > 0) {
            return context.getBean(type);返回bean
        }
        return null;
    }

получитьILoadBalancerреализации, мы можем назвать егоchooseServerПолучите экземпляр службы и сделайте запрос.

ILoadBalancer userLoadBalancer = clientFactory.getLoadBalancer("user");
Server server = userLoadBalancer.chooseServer("default")

3.4 (использование) LoadBalancerClient

LoadBalancerClient инкапсулирует SpringClientFactory и широко используется в качестве клиента балансировщика нагрузки. Этот класс является входом в настоящий клиент балансировки нагрузки SC-Ribbon.

Предусмотрено три метода:

  • Выберите метод экземпляра службы;
  • выполнить метод запроса
  • Рефакторинг метода uri.

Каждый метод связан с балансировкой нагрузки

    ServiceInstance choose(String serviceId);

    <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

    URI reconstructURI(ServiceInstance instance, URI original);

LoadBalancerClient действует как клиент балансировки нагрузки. Его способность полностью основана на совместных усилиях всех вышеперечисленных компонентов.

public class MyClass {
    @Autowired
    private LoadBalancerClient loadBalancer;

    public void doStuff() {
        ServiceInstance instance = loadBalancer.choose("stores");
        URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
        // ... do something with the URI
    }
}

3. Что происходит, когда SC-Ribbon используется с eureka

1. Уровень конфигурации:

когдаSpringCloudRibbonиEurekaПри совместном использовании будет использоваться@RibbonClientsЗамена некоторых компонентов по умолчанию для балансировки нагрузки всех сервисов (замена составных пакетов)

@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(DiscoveryEnabledNIWSServerList.class)
@ConditionalOnBean(SpringClientFactory.class)
@ConditionalOnProperty(value = "ribbon.eureka.enabled", matchIfMissing = true)
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = EurekaRibbonClientConfiguration.class)
public class RibbonEurekaAutoConfiguration {
}
----------------------------
@Configuration
@CommonsLog
public class EurekaRibbonClientConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public IPing ribbonPing(IClientConfig config) {
        NIWSDiscoveryPing ping = new NIWSDiscoveryPing();//
        ping.initWithNiwsConfig(config);
        return ping;
    }

    @Bean
    @ConditionalOnMissingBean
    public ServerList<?> ribbonServerList(IClientConfig config) {
        DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(
                config);
        DomainExtractingServerList serverList = new DomainExtractingServerList(
                discoveryServerList, config, this.approximateZoneFromHostname);
        return serverList;
    }
}    
  • IP-адрес: реализован с использованием NIWSDiscoveryPing.
  • Список серверов: используетсяDomainExtractingServerList.DomainExtractingServerListпроксиDiscoveryEnabledNIWSServerList.DiscoveryEnabledNIWSServerListСписок хранимых сервисов все изEurekaClientиз локального кеша. (Операция выборкиPollingServerListUpdater, исполнение по времени)
public class DiscoveryEnabledNIWSServerList extends AbstractServerList<DiscoveryEnabledServer>{
private List<DiscoveryEnabledServer> obtainServersViaDiscovery() {
    EurekaClient eurekaClient = eurekaClientProvider.get();
    List<InstanceInfo> listOfInstanceInfo = eurekaClient.getInstancesByVipAddress(vipAddress, isSecure, targetRegion);
    ....

}
}

2. Используйте уровень:
Ничего не меняется, просто используйтеLoadBalancerClientЧтобы использовать балансировку нагрузки для получения сервера.

4. Как Resttemplate имеет возможности балансировки нагрузки

Resttemplate имеет возможности балансировки нагрузки, и его суть заключается в использованииLoadBalancerClientреализовать.

Как этого достичь?

Это включает в себя два пункта знаний:

  • ResttemplateСвязанные системы:
  • @LoadBalancedаннотация.

ResttemplateЕсть понятие перехватчика. Другими словами, до того, как будет сделан фактический запрос, некоторые перехватчики будут взяты. Это выбирает балансировщик нагрузкиServerпредоставил возможность.

@LoadBalancedАннотация, чтобы изменить егоResttemplateПримеры инъекцийLoadBalancerInterceptorПерехватчик. Этот перехватчик переданLoadBalancerClientдля достижения балансировки нагрузки

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {

    private LoadBalancerClient loadBalancer;
    ...
}

Подробности читайте в других моих статьях
Отправка http-запросов (1): несколько способов отправки http-запросов.
Отправить http-запрос (2): RestTemplate отправляет http-запрос
RestTemplate с аннотацией @LoadBalanced имеет возможности балансировки нагрузки.

5. Резюме

Текст начинается с введения нескольких компонентов балансировки нагрузки и начинается с нижнего уровня.Resttemplateпринцип. открылResttemplateЧерный ящик, который инициирует запросы балансировки нагрузки. Вдоль этой линии просто внимательно изучите очки знаний каждого раздела.

Вы будете поражены тем, сколько работы по разработке было сэкономлено благодаря построению здания фреймворков с открытым исходным кодом.

Мы не должны останавливаться на этапе использования, но также должны глубоко понимать принципы лежащего в основе фреймворка, чтобы вы были на один уровень выше здания.

Ссылка на ссылку:
https://www.jianshu.com/p/73c117fbfe10
https://blog.csdn.net/hry2015/article/details/78357990


Если в этой статье есть какие-либо ошибки, пожалуйста, критикуйте и советуйте, это очень ценится!
Если вы ничего не понимаете в статье, вы можете связаться со мной, чтобы обменяться знаниями!

Публичный аккаунт WeChat:Исходное действие
Наслаждайтесь изучением исходного кода, действуйте, действуйте с исходным кодом