Наиболее полное объяснение 7️⃣ Gateway от SpringCloudAlibaba (рекомендуемая коллекция)

Микросервисы Spring Cloud
Наиболее полное объяснение 7️⃣ Gateway от SpringCloudAlibaba (рекомендуемая коллекция)

Это 29-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления

🌈 Введение в колонку

    Спасибо за чтение, я надеюсь, что это может быть полезно для вас.Если есть какие-либо недостатки в сообщении в блоге, пожалуйста, оставьте сообщение в области комментариев или добавьте меня в личное представление на главной странице, чтобы пообщаться со мной в частном порядке.Спасибо. за ваш щедрый совет. Я XiaoLin, мальчик, который может писать ошибки и петь рэп. В этой колонке в основном представлено самое распространенное решение для микросервисов, SpringCloudAlibaba, которое будет представлено в компонентах. Адрес столбца: SpringCloudAlibaba.

9. Сервисный шлюз: шлюз

image-20210507115602441

9.1 Введение в шлюз

Всем известно, что в микросервисной архитектуре система будет разбита на множество микросервисов. Так как же вызвать такое количество микросервисов в качестве клиента? Если нет шлюза, мы можем только записать адрес каждого микросервиса на стороне клиента, а потом вызывать его отдельно.

image-20210507115048632

У такой архитектуры много проблем:

  1. Клиент несколько раз запрашивает разные микросервисы, что увеличивает сложность написания клиентского кода или конфигурации.
  2. Аутентификация сложна, и каждая служба требует независимой аутентификации.
  3. Существуют междоменные запросы, которые относительно сложно обрабатывать в определенных сценариях.

Gateway был создан, чтобы решить эти проблемы. Так называемый API-шлюз относится к единому входу в систему, инкапсулирует внутреннюю структуру прикладной программы и предоставляет унифицированные сервисы для клиента, здесь может быть реализована некоторая публичная логика, не связанная с функциями самого бизнеса, например аутентификация, аутентификация, мониторинг, маршрутизация и т. д.

image-20210507115517531

9.2. Часто используемые шлюзы

9.2.1 Ngnix+lua

Использование обратного прокси-сервера nginx и балансировки нагрузки может обеспечить балансировку нагрузки и высокую доступность для серверов API.

Lua — это язык сценариев, на котором можно написать простую логику, nginx поддерживает сценарии lua.

9.2.2. Конг

На основе разработки Nginx + Lua, высокой производительности и стабильности существует несколько доступных подключаемых модулей (ограничение тока, аутентификация и т. д.), которые можно использовать «из коробки».

Его недостатки:

  1. Поддерживается только протокол Http.
  2. Вторичное развитие, трудно свободно расширяться.
  3. Предоставляет API управления, не имеет более простых в использовании методов управления и настройки.

9.2.3, Зуул

Netflix Devices Gateways, богатые функции, используйте Java Development, легко развиваться.

Его недостатки:

  1. Отсутствие контроля и отсутствие динамической настройки.
  2. Есть много зависимых компонентов.
  3. Обработка запросов Http зависит от веб-контейнера, а производительность не так хороша, как у Nginx.

9.2.4, Весенний облачный шлюз

Служба шлюза, разработанная Spring для замены Zuul, стек технологий Alibaba Spring Cloud не предоставляет собственный шлюз, мы можем использовать Spring Cloud Gateway в качестве шлюза.

9.3 Введение в шлюз

Spring Cloud Gateway — это шлюз, разработанный Spring на основе таких технологий, как Spring 5.0, Spring Boot 2.0 и Project Reactor, с целью предоставления простого и эффективного унифицированного метода управления маршрутизацией API для микросервисной архитектуры. Его цель — заменить Netflix Zuul, который не только предоставляет унифицированный метод маршрутизации, но и предоставляет базовые функции шлюза на основе цепочки Filter, такие как: безопасность, мониторинг и ограничение тока.

Его основные функции:

  1. Делайте перенаправление вперед.
  2. Вначале все классы должны выполнять операции инициализации.
  3. Сетевая изоляция.

9.4. Быстрый старт

Требование: Получите доступ к шлюзу API через браузер, а затем перенаправьте запрос в стандартную микрослужбу через шлюз.

9.4.1, базовая версия

Создайте модуль API-шлюза и импортируйте следующие зависимости.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <artifactId>Shop-parent</artifactId>
    <groupId>cn.linstudy</groupId>
    <version>1.0.0</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <artifactId>api-gateway</artifactId>

  <properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>
    <!--gateway网关-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
  </dependencies>

</project>

написать файл конфигурации

server:
  port: 9000 # 指定网关服务的端口
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: product_route # 当前路由的标识, 要求唯一
          uri: http://localhost:8081 # 请求要转发到的地址
          order: 1 # 路由的优先级,数字越小级别越高
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/product-serv/** # 当请求路径满足Path指定的规则时,才进行路由转发
          filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1 # 转发之前去掉1层路径

контрольная работа

image-20210507171142491

9.4.2, версия обновления

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

Добавить зависимость nacos

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <artifactId>Shop-parent</artifactId>
    <groupId>cn.linstudy</groupId>
    <version>1.0.0</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <artifactId>api-gateway</artifactId>

  <properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>
    <!--gateway网关-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--nacos客户端-->
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
  </dependencies>

</project>

Добавьте аннотации к основному классу

@SpringBootApplication
@EnableDiscoveryClient
public class GateWayServerApp {
  public static void main(String[] args) {
    SpringApplication.run(GateWayServerApp.class,args);
  }
}

Изменить файл конфигурации

server:
  port: 9000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的微服务
      routes:
        - id: product_route # 路由的名字
          uri: lb://product-service # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          predicates:
            - Path=/product-serv/** # 符合这个规定的才进行1转发
          filters:
            - StripPrefix=1 # 将第一层去掉

Мы также можем настроить несколько правил маршрутизации.

spring:
  application:
    gateway:
      routes:
        - id: product_route
          uri: lb://product-service 
          predicates:
            - Path=/product-serv/**
          filters:
            - StripPrefix=1
        - id: order_route
          uri: lb://order-service 
          predicates:
            - Path=/order-serv/**
          filters:
            - StripPrefix=1

9.4.3, сокращенная версия

Наш профиль не нужно писать менее сложные функции можно добиться, есть сокращенная версия.

server:
  port: 9000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的微服务

image-20210507201625163

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

9.5 Архитектура ядра шлюза

9.5.1 Основные понятия

Маршрут — один из самых основных компонентов шлюза, представляющий собой конкретный носитель маршрутной информации. В основном он определяет следующую информацию:

  1. id: идентификатор маршрута, отличный от других маршрутов.
  2. uri: URI назначения, на который указывает маршрут, то есть микрослужба, на которую в конечном итоге перенаправляется запрос клиента.
  3. Заказ: используется для сортировки нескольких маршрутов. Чем меньше значение, тем выше сортировка и тем выше соответствующий приоритет.
  4. предикат: Роль утверждения заключается в выполнении условного суждения.Только когда утверждение возвращает истину, маршрут будет фактически выполнен.
  5. фильтр: Фильтры используются для изменения информации запроса и ответа.
  6. предикат: утверждения используются для условного суждения.Только когда утверждения возвращают истину, маршрут будет фактически выполнен.

9.5.2 Принцип выполнения

image-20201030161652819

  1. Получите запрос пользователя, передайте обработчик запроса обработчику сопоставления и вернитесь в цепочку выполнения.
  2. Обработчик запроса вызывает веб-обработчик, где обрабатывается наш путь 1. Предположим 1, что наш путь 1:http://localhost:9000/product-serv/get?id=1Согласно сконфигурированным правилам маршрутизации, найдите соответствующую информацию о обслуживании локально: IP-хост, соответствующий услугу продукта, является 192.168.10.130.
  3. Выбираем ноду исходя из стратегии балансировки нагрузки 1ribbon, затем сращиваем, заменяем Product-Serv в пути на 192.168.10.130:8081, если вы настроили Filter, то он будет ходить по Filter.
  4. Если у вас нет собственного маршрута, шлюз по умолчанию удалит для вас первый уровень. Порт шлюза от этого/начать вторым/Начните считать первый уровень.

image-20210507203258953

9.6. Фильтры

Роль фильтра шлюза состоит в том, чтобы делать некоторые трюки с запросом и ответом в процессе доставки запроса.

Жизненный цикл фильтра шлюза:

  1. PRE: этот фильтр вызывается перед маршрутизацией запроса. Мы можем использовать этот фильтр для реализации аутентификации и выбора в кластере. Запросить микросервис, записать отладочную информацию и т. д.
  2. POST: этот фильтр выполняется после маршрутизации в микросервис. Этот фильтр можно использовать для добавления стандартного HTTP к ответу. Заголовок, сбор статистики и метрик, отправка ответов от микросервисов клиентам и т.д.

Фильтр шлюза можно разделить на два типа: воротфильтр и GlobalFilter:

  1. GatewayFilter: применяется к одному маршруту или пакету.
  2. GlobalFilter: применяется ко всем маршрутам.

9.6.1 Локальный фильтр

Локальные фильтры — это фильтры для одного маршрута. Он делится на встроенные фильтры и настраиваемые фильтры.

9.6.1.1, встроенный фильтр

В Spring Cloud Gateway встроено множество различных типов фильтров маршрутов шлюза.

9.6.1.1.1, локальное содержимое фильтра
завод фильтров эффект параметр
AddRequestHeader Добавить заголовок к исходному запросу Имя и значение заголовка
AddRequestParameter Добавьте параметры запроса в исходный запрос Имя параметра и значение
AddResponseHeader Добавить исходный ответ заголовка Имя и значение заголовка
DedupeResponseHeader Обрезать повторяющиеся значения в заголовках ответов Имена заголовков и стратегии дедупликации, которые необходимо дедуплицировать
Hystrix Автоматический выключатель защиты для маршрутизации введения Hystrix Имя HystrixCommand
FallbackHeaders Добавьте конкретную информацию об исключении в заголовок запроса fallbackUri. Название заголовка
PrefixPath Префикс исходного пути запроса префиксный путь
PreserveHostHeader Добавьте в запрос свойство preserveHostHeader=true, фильтр маршрута проверит это свойство, чтобы решить, следует ли отправлять исходный узел. никто
RequestRateLimiter Используется для ограничения потока запросов. Алгоритм ограничения потока — это ведро токенов. ключ Resolver,
скоростьLimiter,
код статуса,
отрицатьEmptyKey,
emptyKeyStatus
RedirectTo Перенаправить оригинальный запрос на указанный URL код состояния http и URL-адрес перенаправления
RemoveHopByHopHeadersFilter Удалить ряд заголовков, указанных организацией IETF для исходного запроса. Если будет включен по умолчанию, вы можете удалить только какой заголовок удалять только настройкой
RemoveRequestHeader Удалить заголовок исходного запроса Название заголовка
RemoveResponseHeader Удалить заголовок для исходного ответа Название заголовка
RewritePath Перепишите исходный путь запроса Исходное регулярное выражение пути и переписанное регулярное выражение пути
RewriteResponseHeader Переопределить заголовок в исходном ответе Имя заголовка, регулярное выражение для значения, перезаписанное значение
SaveSession Прежде чем пересылать запрос, включитеWebSession::saveдействовать никто
secureHeaders Добавьте серию заголовков ответа безопасности к исходному ответу. Нет, поддержка изменения значения этих заголовков ответов безопасности
SetPath Изменить исходный путь запроса Измененный путь
SetResponseHeader Изменить значение заголовка в исходном ответе Название заголовка, измененное значение
SetStatus Измените исходный код состояния ответа HTTP-код состояния, может быть номером или строкой
StripPrefix Путь, используемый для усечения исходного запроса Используйте число для количества путей для усечения
Retry Повторите попытку с другим ответом повторы, статусы, методы, серии
RequestSize Устанавливает размер максимального пакета запроса, который может быть получен. Если размер пакета запроса превышает установленное значение, вернуть 413 Payload Too Large. Размер пакета запроса, в байтах, значение по умолчанию 5M
ModifyRequestBody Измените исходное содержимое тела запроса перед пересылкой запроса. Измененное содержимое тела запроса
ModifyResponseBody Изменить содержимое исходного тела ответа Модифицированный ответ отклика
9.6.1.1.2 Использование локальных фильтров
server:
  port: 9000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的微服务
      routes:
        - id: product_route # 路由的名字
          uri: lb://product-service # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          predicates:
            - Path=/product-serv/** # 符合这个规定的才进行1转发
          filters:
            - StripPrefix=1 # 将第一层去掉
            - SetStatus=2000 # 这里使用内置的过滤器,修改返回状态

9.6.1.2, локальный настраиваемый фильтр

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

Напишите класс, который реализует логику

    Имя имеет фиксированный формат xxxGatewayFilterFactory.

@Component
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.Config> {

  private static final String BEGIN_TIME = "beginTime";

  //构造函数
  public TimeGatewayFilterFactory() {
    super(TimeGatewayFilterFactory.Config.class);
  }

  //读取配置文件中的参数 赋值到 配置类中
  @Override
  public List<String> shortcutFieldOrder() {
    return Arrays.asList("show");
  }

  @Override
  public GatewayFilter apply(Config config) {
    return new GatewayFilter() {
      @Override
      public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        if (!config.show){
          // 如果配置类中的show为false,表示放行
          return chain.filter(exchange);
        }
        exchange.getAttributes().put(BEGIN_TIME, System.currentTimeMillis());
        /**
         *  pre的逻辑
         * chain.filter().then(Mono.fromRunable(()->{
         *     post的逻辑
         * }))
         */
        return chain.filter(exchange).then(Mono.fromRunnable(()->{
          Long startTime = exchange.getAttribute(BEGIN_TIME);
          if (startTime != null) {
            System.out.println(exchange.getRequest().getURI() + "请求耗时: " + (System.currentTimeMillis() - startTime) + "ms");
          }
        }));
      }
    };
  }

  @Setter
  @Getter
  static class Config{
    private boolean show;
  }

}

написать приложение.xml

server:
  port: 9000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的微服务
      routes:
        - id: product_route # 路由的名字
          uri: lb://product-service # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          predicates:
            - Path=/product-serv/** # 符合这个规定的才进行1转发
          filters:
            - StripPrefix=1 # 将第一层去掉
        - id: order_route
          uri: lb://order-service
          predicates:
            - Path=/order-serv/**
          filters:
            - StripPrefix=1
            - Time=true

Путь доступа:http://localhost:9000/order-serv/getById?o=1&pid=1

在这里插入图片描述

9.6.2, глобальный фильтр

Глобальные фильтры применяются ко всем маршрутам, настройка не требуется. Через глобальный фильтр могут быть реализованы такие функции, как унифицированная проверка разрешений и проверка безопасности. Внутри Spring Cloud Gateway также обрабатывает переадресацию всего маршрута с помощью ряда встроенных глобальных фильтров.

网关全局过滤器

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

  • Когда клиент запрашивает услугу в первый раз, сервер выполняет информационную аутентификацию (логин) пользователя.
  • После прохождения аутентификации информация о пользователе шифруется для формирования маркера, который возвращается клиенту в качестве учетных данных для входа.
  • Для каждого последующего запроса клиент несет токен аутентификации.
  • Сервер для расшифровки токена, чтобы определить, является ли действительным.

image-20210507220009473

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

Напишите глобальный фильтр

@Component
public class AuthGlobalFilter implements GlobalFilter {

  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    String token = exchange.getRequest().getQueryParams().getFirst("token");
    if (StringUtils.isBlank(token)) {
      System.out.println("鉴权失败");
      exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
      return exchange.getResponse().setComplete();
    }
    return chain.filter(exchange);
  }
}

9.6.3 Ограничение тока шлюза

Шлюз является общим входом для всех запросов, можно ограничить поток в шлюзе, а также во многих ограничивающих вариантах, мы используем эти изученные компоненты Sentinel для достижения вышеупомянутого ограничения шлюза. Sentinel поддерживает ограничения SpringCloud Gateway, Zuul и других основных шлюзов.

image-20210507220048921

Начиная с версии 1.6.0, Sentinel предоставляет модуль адаптации для Spring Cloud Gateway, который может обеспечить текущее ограничение в двух измерениях ресурсов:

  • измерение маршрута: запись маршрута, настроенная в файле конфигурации Spring, имя ресурса соответствует идентификатору маршрута.
  • Пользовательский параметр API: пользователи могут использовать API, предоставляемый Sentinel, для настройки некоторых групп API.

9.6.3.1, интеграция со шлюзом Sentinel

добавить зависимости

<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>

Напишите классы конфигурации, чтобы ограничить

Суть класса конфигурации заключается в замене текущего лимита графического интерфейса nacos кодом.

@Configuration
public class GatewayConfiguration {
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }
    // 配置限流的异常处理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }
    // 初始化一个限流的过滤器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
    //增加对商品微服务的限流
     @PostConstruct
    private void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("product_route")
                .setCount(3) // 三次
                .setIntervalSec(1) // 一秒,表示一秒钟1超过了三次就会限流
        );
        GatewayRuleManager.loadRules(rules);
    }
}

Изменить формат возврата текущего лимита по умолчанию

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

@PostConstruct
public void initBlockHandlers() {
	BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
	public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
		Map map = new HashMap<>();
		map.put("code", 0);
		map.put("message", "接口被限流了");
			return ServerResponse.status(HttpStatus.OK).
				contentType(MediaType.APPLICATION_JSON).
				body(BodyInserters.fromValue(map));
            }
};
	GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}

контрольная работа

image-20210507221350190

9.6.3.2 Группировка пользовательских API

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

Добавьте ApiController в проект Shop-order-server.

@RestController
@RequestMapping("/api")
public class ApiController {
    @RequestMapping("/hello")
    public String api1(){
        return "api";
    }
}

Добавьте конфигурацию в GatewayConfiguration

@PostConstruct
private void initCustomizedApis() {
	Set<ApiDefinition> definitions = new HashSet<>();
	ApiDefinition api1 = new ApiDefinition("order_api")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem().setPattern("/order-serv/api/**").                 setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
	definitions.add(api1);
	GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
@PostConstruct
private void initGatewayRules() {
	Set<GatewayFlowRule> rules = new HashSet<>();
	rules.add(new GatewayFlowRule("product_route")
                .setCount(3)
                .setIntervalSec(1)
	);
	rules.add(new GatewayFlowRule("order_api").
                setCount(1).
                setIntervalSec(1));
    GatewayRuleManager.loadRules(rules);
}

контрольная работа

прямое интервьюhttp://localhost:8082/api/helloСлучится ли это, посетитеhttp://localhost:9000/order-serv/api/helloТам будет ограниченный поток.