1 Обзор
Spring Cloud Ribbon - это набор инструментов балансировки клиентской нагрузки на основе Netflix Ribbon.
Проще говоря, Ribbon - это проект с открытым исходным кодом, выпущенный Netflix. Его основная функция заключается в предоставлении клиентских алгоритмов балансировки нагрузки и вызовов служб. Компонент клиента ленты предоставляет ряд полных элементов конфигурации, таких как тайм-аут соединения, повторная попытка и т. Д. Проще говоря, это список всех машин, на которых выполняется балансировка нагрузки (сокращенно LB) в файле конфигурации. Лента автоматически поможет вам подключить эти машины на основе определенных правил (таких как простой опрос, случайное соединение и т. Д.). для нас легко Используйте ленту для реализации настраиваемых алгоритмов балансировки нагрузки.
Информация с официального сайта: https://github.com/Netflix/ribbon/wiki/Getting-Started
2. LB (балансировка нагрузки)
2.1 Что такое балансировка нагрузки LB
Проще говоря, запросы пользователя равномерно распределяются между несколькими серверами, чтобы обеспечить высокую доступность системы. Обычная балансировка нагрузки включает программное обеспечение nginx, LVS, аппаратное обеспечение F5 и т. Д.
2.2 Разница между локальным гостевым клиентом балансировки нагрузки ленты и балансировкой нагрузки сервера nginx
Nginx - это балансировка нагрузки на сервер.Все клиентские запросы передаются в nginx, а затем nginx реализует переадресацию запросов, то есть балансировка нагрузки осуществляется сервером.
Локальная балансировка нагрузки на ленте: при вызове интерфейса микросервиса список служб регистрационной информации будет получен из списка реестра и кэширован локально в JVM, тем самым локально реализуя технологию вызова удаленных служб RPC.
Централизованная LB
относится к использованию независимых LB-средств (оборудования, такого как F5 или программного обеспечения, такого как nginx) между потребителем и поставщиком услуги.Средство отвечает за пересылку запроса на доступ к услуге через определенную стратегию. Provider.
Внутрипроцессный LB
интегрирует логику LB в потребителя. Потребитель выбирает подходящий сервер из реестра служб или из доступных адресов. Лента принадлежит внутрипроцессному LB, который является просто библиотекой классов. Интегрирован в процесс потребителя, через него потребитель получает адрес поставщика услуг.
3. Балансировка нагрузки на ленту.
3.1 Описание архитектуры
Лента при работе делится на два этапа:
- Первый шаг - выбрать Eureka Server, он предпочитает выбирать сервер с меньшей нагрузкой в той же области.
- Вторая часть выбирает адрес из списка услуг, полученных сервером, в соответствии со стратегией, заданной пользователем.
Среди них Ribbon предоставляет различные стратегии: такие как опрос, случайный выбор и взвешивание на основе времени ответа.
Описание: Лента на самом деле является клиентским компонентом мягкой балансировки нагрузки. Ее можно использовать вместе с другими клиентами, которым требуются запросы. Комбинация с eureka - лишь один из примеров.
3.2 Использование RestTemplate
https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
метод getForObject / метод getForEntity
postForObject / postForEntity
3.3 Компонент сердечника ленты IRule
IRule: выберите службу, к которой будет осуществляться доступ, из списка служб в соответствии с определенным алгоритмом.
- com.netflix.loadbalancer.RoundRobinRule: опрос
- com.netflix.loadbalancer.RandomRule: Случайно
- com.netflix.loadbalancer.RetryRule: сначала получите услугу в соответствии со стратегией RoundRobinRule, в случае сбоя службы она повторит попытку в течение указанного времени.
- WeightedResponseTimeRule: расширение RoundRobinRule, чем выше скорость ответа, чем больше вес выбора экземпляра, тем легче его выбрать
- BestAvailableRule: сначала отфильтрует службы, которые находятся в состоянии отключения выключателя из-за множественных сбоев доступа, а затем выберет службу с наименьшим количеством параллелизма.
- AvailabilityFilteringRule: сначала отфильтруйте отказавшие экземпляры, а затем выберите экземпляр с меньшим параллелизмом.
- ZoneAvoidanceRule: правило по умолчанию, составная часть оценивает производительность области, где расположен сервер, и доступность сервера для выбора сервера.
Как заменить
modify cloud-consumer-order80
Обратите внимание на детали конфигурации:
- Новый пакет
- Создайте новый класс MyselfRule
package com.lele.myrule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: lele
* @date: 2021/3/15 7:12
* @description:
*/
@Configuration
public class MySelfRule {
@Bean
public IRule myRule() {
return new RandomRule(); // 定义为随机
}
}
- Добавьте доступ
браузера @RibbonClient к основному классу запуска потребителя 80 : http: // localhost / consumer / payment / get / 1
4. Алгоритм балансировки нагрузки ленты.
4.1 Принцип
Алгоритм балансировки нагрузки: количество запросов к остальному интерфейсу% Общее количество кластеров серверов = фактический индекс местоположения сервера вызовов (счетчик остальных интерфейсов начинается с 1 после каждого перезапуска)
List instances = discoveryClient.getInstances(“CLOUD-PAYMENT-SERVICE”);
List[0] instances = 127.0.0.1:8001
List[1] instances = 127.0.0.1:8002
8001 и 8002 объединены в кластер. Всего у них две машины, а общее количество кластеров равно 2. По принципу алгоритма опроса:
Когда общее количество запросов равно 1, 1% 2 = 1 соответствует позиции индекса 1, а полученный адрес сервера - 127.0.0.1:8002
Когда общее количество запросов равно 2, 2% 2 = 0 соответствует позиция индекса 0, и полученный адрес сервера 127.0.0.1:8001,
когда общее количество запросов равно 3, и 3% 2 = 1 соответствует позиции индекса 1, а полученный адрес сервера - 127.0.0.1 : 8002,
когда общее количество запросов равно 4, 4% 2 = 0 соответствует следующему Если позиция метки равна 0, полученный адрес сервера - 127.0.0.1:8001…
и
так далее
4.2 Алгоритм опроса рукописного ввода
-
Запуск кластера 7001/7002
-
Преобразование микросервисов 8001/8002
-
Преобразование микросервиса 80 порядка:
-
ApplicationContextBean удалить @LoadBalanced
-
LoadBalancer интерфейс
-
MyLB
package com.lele.springcloud.lb; import org.springframework.cloud.client.ServiceInstance; import org.springframework.stereotype.Component; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * @author: lele * @date: 2021/3/16 7:27 * @description: */ @Component public class MyLB implements LoadBalancer { private AtomicInteger atomicInteger = new AtomicInteger(0); public final int getAndIncrement() { int current; int next; do { current = this.atomicInteger.get(); next = current >= 2147483647 ? 0 : current + 1; } while (!this.atomicInteger.compareAndSet(current, next)); System.out.println("*****第几次访问,次数next:"+next); return next; } @Override public ServiceInstance instances(List<ServiceInstance> serviceInstances) { int index = getAndIncrement() % serviceInstances.size(); return serviceInstances.get(index); } }
-
-
80 OrderController
package com.lele.springcloud.controller;
import com.lele.springcloud.entities.CommonResult;
import com.lele.springcloud.entities.Payment;
import com.lele.springcloud.lb.LoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.net.URI;
import java.util.List;
/**
* @author: lele
* @date: 2021/3/1 21:33
* @description:
*/
@RestController
@Slf4j
public class OrderController {
// public static final String PAYMENT_URL = "http://localhost:8001";
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
@Resource
private LoadBalancer loadBalancer;
@Resource
private DiscoveryClient discoveryClient;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment) {
return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
}
@GetMapping("/consumer/payment/getForEntity/{id}")
public CommonResult<Payment> getPayment2(@PathVariable("id") Long id) {
ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
if (entity.getStatusCode().is2xxSuccessful()) {
return entity.getBody();
} else {
return new CommonResult<>(444, "操作失败");
}
}
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB() {
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if (instances == null || instances.size() <= 0) {
return null;
}
ServiceInstance serviceInstance = loadBalancer.instances(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri+"/payment/lb", String.class);
}
}
- 测试
http: // localhost / consumer / payment / lb