Конфигурации Spring Cloud Gateway+Consul

Мы используем Spring Cloud Gateway перед несколькими микросервисами с консулом в качестве службы обнаружения. Существует несколько микросервисов, разработанных на разных языках.

Пожалуйста, найдите build.gradle для приложения

buildscript {
    ext {
        springBootVersion = '2.1.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.demo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
}

ext {
    set('springCloudVersion', 'Greenwich.RELEASE')
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.cloud:spring-cloud-starter-consul-config'
    implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery'
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    // https://mvnrepository.com/artifact/io.netty/netty-tcnative-boringssl-static
    compile group: 'io.netty', name: 'netty-tcnative-boringssl-static', version: '2.0.20.Final'
    runtimeOnly 'org.springframework.boot:spring-boot-devtools'
    compileOnly 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

Ниже приведен пример конфигурации шлюза API
. приложение.yaml

server:
  port: 10000
  http:
    port: 9000
  # enable HTTP2
  http2:
    enabled: true
  # enable compression
  compression:
    enabled: true
    mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json
  ssl:
    enabled: true
    key-store: /var/.conf/self-signed.p12
    key-store-type: PKCS12
    key-store-password: "something"
    key-alias: athenasowl
    trust-store: /var/.conf/self-signe.p12
    trust-store-password: "something"
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          predicates:
          - Path = "'/api/' + serviceId + '/**'"
          filters:
          - RewritePath = "'/api/' + serviceId + '/(?<remaining>.*)'", "serviceId + '/${remaining}'"
management:
  security:
    enabled: false
  server:
    port: 10001
    ssl:
      enabled: false
  endpoint:
    gateway:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
    health:
      sensitive: false
logging:
  level:
    root: DEBUG
    org:
      springframework:
        web: INFO
  pattern:
    console: "%-5level %d{dd-MM-yyyy HH:mm:ss,SSS} [%F:%L] VTC : %msg%n"
    file: "%-5level %d{dd-MM-yyyy HH:mm:ss,SSS} [%F:%L] VTC : %msg%n"
  file: /tmp/log_files/apigateway.log
security:
  basic:
    enabled: false

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

  • Перепишите URL-адрес с префиксом /api/ в соответствующий идентификатор службы, зарегистрированный в консуле.: мы пытались настроить предикат для получения пути с префиксом API, чтобы переписать путь и удалить API, но все равно это не работает. Итак, есть еще одна служба /привет-сервис/, зарегистрированная на сервере консула, но мы хотим сделать вызов API с помощью /API/привет-сервис/.
  • Перенаправить несопоставленный запрос на путь по умолчанию: Мы хотим перенаправить все несовпадающие запросы в пользовательский интерфейс.
  • Перенаправление HTTP на HTTPS на весеннем облачном шлюзе: мы хотим, чтобы все запросы, поступающие на шлюз spring, были https
  • Перенаправление HTTPS-запроса на HTTP-сервисный идентификатор, зарегистрированный в консуле: Службы, зарегистрированные в консуле, находятся на HTTP, за исключением шлюза API, мы хотим иметь возможность отправлять запрос HTTPS на серверную часть HTTP, т. е. завершать HTTPS только на шлюзе API.

Любая помощь в решении вышеуказанной проблемы будет хорошей

Редактировать 1: После некоторой помощи от @spencergibb мы настроили облачный шлюз Spring с https. Но есть некоторые дополнительные проблемы, с которыми мы столкнулись

  • Если HTTPS включен как на шлюзе API, так и на сервисе, мы получили следующую ошибку

javax.net.ssl.SSLException: handshake timed out at io.netty.handler.ssl.SslHandler.handshake(...)(Unknown Source) ~[netty-handler-4.1.31.Final.jar:4.1.31.

  • Если HTTPS включен только на шлюзе API, мы получили следующую ошибку

    There was an unexpected error (type=Not Found, status=404). org.springframework.web.server.ResponseStatusException: 404 NOT_FOUND and received

    для пути https://localhost:8443/api/hello-service/hello/message

    Unable to Connect

    для пути http://localhost:8080/hello-service/hello/message

Пожалуйста, найдите ссылку на примеры приложений

Инструкции:

  • перейдите в каталог консула и запустите сервер консула с помощью команды ./consul agent -dev
  • запустить проект api-gateway spring boot gradle
  • запустить проект rest-demo spring boot gradle

Редактировать 2

Спасибо, @spencergibb, мы смогли успешно применить ssl к шлюзу и вызвать зарегистрированные службы по HTTP. Начиная с Spring Webflux с Netty не поддерживает прослушивание двух портов, мы создали дополнительную привязку TCP-сервера к http-порту на основе этот ответ.

Мы все еще сталкиваемся с некоторыми проблемами, связанными с правилом RewritePath для /api/.

  predicates:
    - name: Path
      args:
        pattern: "'/api/'+serviceId.toLowerCase()+'/**'"
  filters:
    - name: RewritePath
      args:
        regexp: "'/api/' + serviceId.toLowerCase() + '/(?<remaining>.*)'"
        replacement: "'/${remaining}'"

ниже приведена полная трассировка запроса

DEBUG 13-02-2019 03:32:01 [FilteringWebHandler.java:86] VTC : Sorted gatewayFilterFactories: [OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@257505fd}, order=-2147482648}, OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.GatewayMetricsFilter@400caab4}, order=-2147473648}, OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@36e2c50b}, order=-1}, OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardPathFilter@66f0c66d}, order=0}, OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory$$Lambda$360/1720581802@5821f2e6, order=0}, OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@27119239}, order=10000}, OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@568a9d8f}, order=10100}, OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@6ba77da3}, order=2147483646}, OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyRoutingFilter@73c24516}, order=2147483647}, OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardRoutingFilter@461a9938}, order=2147483647}] TRACE 13-02-2019 03:32:01 [RouteToRequestUrlFilter.java:59] VTC : RouteToRequestUrlFilter start TRACE 13-02-2019 03:32:02 [NettyWriteResponseFilter.java:68] VTC : NettyWriteResponseFilter start TRACE 13-02-2019 03:32:02 [GatewayMetricsFilter.java:101] VTC : Stopping timer 'gateway.requests' with tags [tag(outcome=CLIENT_ERROR),tag(routeId=rewrite_response_upper),tag(routeUri=http://httpbin.org:80),tag(status=NOT_FOUN

могу попробовать помочь в понедельник

spencergibb 10.02.2019 06:26

Спасибо @spencergibb, тем временем мы также постараемся решить некоторые из этих проблем.

Nitishkumar Singh 10.02.2019 06:29

Привет, @spencergibb, у тебя была возможность изучить это?

Nitishkumar Singh 11.02.2019 14:52

У вас должен быть слеш перед заменой в RewritePath"/serviceId + '/${remaining}'". Чтобы соответствовать пользовательскому интерфейсу, создайте маршрут с путем /** вручную. Перенаправляя http на https, если в весенней безопасности нет чего-то (что, вероятно, есть), вам нужно написать фильтр. Для https на http это должно работать так автоматически, какую версию вы используете?

spencergibb 12.02.2019 17:51

Все зависимости связаны с загрузочной версией Spring 2.1.2•RELEASE.

Nitishkumar Singh 12.02.2019 18:24

Привет @spencergibb, мы попробовали упомянутый подход, но он не работал с http или https. Мы также включили ссылку на репозиторий git выше для демонстрационных приложений.

Nitishkumar Singh 12.02.2019 21:09

Таким образом, вы не можете использовать ярлык для настройки локатора обнаружения gist.github.com/spencergibb/7e49b72e55bc29767dad1faf460cc056.

spencergibb 12.02.2019 22:31

Удаление настроек http2 и httpclient.ssl ​​из конфигурации шлюза позволило мне пройти весь путь. Gist выше имеет полные настройки

spencergibb 12.02.2019 22:35

Большое спасибо @spencergibb, но RewritePath не работает должным образом, добавил дополнительную информацию об этом.

Nitishkumar Singh 13.02.2019 04:48

@spencergibb, не могли бы вы также взглянуть на stackoverflow.com/questions/54662179/…? НитишкумарСингх - извините за захват вашей темы.

Mubin 13.02.2019 10:17

@NitishkumarSingh Я не понимаю, что не работает, эти журналы мне ничего не говорят. Я успешно сделал запросы с вашим проектом.

spencergibb 13.02.2019 16:59

@Mubin, действительно, тебе не следует задавать другие вопросы. Я слежу за тегом.

spencergibb 13.02.2019 16:59

@spencergibb: извините за путаницу, это сработало. Большое спасибо. Не могли бы вы поставить это как ответ, чтобы я мог принять ответ.

Nitishkumar Singh 14.02.2019 18:53

сделаю это прямо сейчас

spencergibb 14.02.2019 22:02
3
14
4 412
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Потребовалось несколько вещей

  1. отключить http2
  2. Отключить конфигурацию ssl для httpclient
  3. Обновите предикаты и фильтры locator, чтобы использовать подробную конфигурацию.

Вот результирующие части application.yml

server:
  port: 8443
  http:
    port: 8080
  servlet:
  # enable HTTP2
#  http2:
#    enabled: true
  # enable compression

# ... removed for brevity

spring:
  application:
    name: api-gateway
  cloud:
    consul:
      enabled: true
    gateway:
#      httpclient:
#        ssl:
#          handshake-timeout-millis: 10000
#          close-notify-flush-timeout-millis: 3000
#          close-notify-read-timeout-millis: 0
#      routes:
      # - id: ui_path_route
      #   predicates:
      #   - Path = "'/**'"
      #   filters:
      #   - RewritePath = "'/**'", "/ui"
      discovery:
        instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
        locator:
          enabled: true
          predicates:
          - name: Path
            args:
              pattern: "'/api/' + serviceId + '/**'"
          filters:
          - name: RewritePath
            args:
              regexp: "'/api/' + serviceId + '/(?<remaining>.*)'"
              replacement: "'/${remaining}'"
#... removed for brevity

Другие вопросы по теме