简体   繁体   English

Spring Cloud Gateway + Consul配置

[英]Spring Cloud Gateway+Consul configurations

We are using Spring Cloud Gateway before multiple microservices with consul as service discovery. 我们在使用具有Consul作为服务发现功能的多个微服务之前使用Spring Cloud Gateway。 There are several microservices developed in different languages. 有几种使用不同语言开发的微服务。

Please find build.gradle for the application 请找到该应用程序的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}"
    }
}

Below is the example of API gateway configuration 以下是API网关配置的示例
application.yaml application.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

There are a few configuration issues which we are facing, they are listed below: 我们面临一些配置问题,下面列出了它们:

  • Rewrite URL prefixed with /api/ to respective serviceId registered on consul : We tried to configure predicate to get path prefixed with api to rewrite path and remove api , but still it's not working. 将以/ api /为前缀的URL重写为在consul上注册的相应serviceId :我们试图配置谓词以以api为前缀的路径来重写path并删除api ,但仍然无法正常工作。 So there is another service /hello-service/ registered with consul server, but we want to do API call with /api/hello-service/ 因此,还有另一个服务/ hello-service /已在领事服务器上注册,但是我们想使用/ api / hello-service /进行API调用
  • Redirect unmatched request to default path : We want to redirect all unmatched request to UI. 将不匹配的请求重定向到默认路径 :我们要将所有不匹配的请求重定向到UI。
  • Redirecting HTTP to HTTPS on spring cloud gateway : We want to force all request coming to spring gateway to be https 在Spring Cloud Gateway上将HTTP重定向到HTTPS :我们要强制所有到Spring网关的请求都为https
  • Forwarding HTTPS request to HTTP serviceId registered with consul : Services registered with consul are on HTTP except for the API gateway, we want to be able to send HTTPS request to HTTP backend ie terminating HTTPS at API Gateway only. 将HTTPS请求转发到在consul中注册的HTTP serviceId :在consul中注册的服务在HTTP上,除了API网关,我们希望能够将HTTPS请求发送到HTTP后端,即仅在API Gateway处终止HTTPS。

Any help in solving the above issue would be good 解决上述问题的任何帮助都会很好

Edit 1: After some help from @spencergibb, we had setup the spring cloud gateway with https. 编辑1:在@spencergibb的帮助下,我们使用https设置了spring cloud网关。 But There are some additional issues which we faced 但是,我们还面临其他一些问题

  • If HTTPS is enabled on both API gateway and service both, we received below error 如果同时在API网关和服务上均启用HTTPS,我们将收到以下错误消息

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. javax.net.ssl.SSLException:握手在io.netty.handler.ssl.SslHandler.handshake(...)(未知源)〜[netty-handler-4.1.31.Final.jar:4.1.31。

  • If HTTPS is enabled on only API gateway, we received below error 如果仅在API网关上启用HTTPS,我们将收到以下错误消息

    There was an unexpected error (type=Not Found, status=404). 发生意外错误(类型=未找到,状态= 404)。 org.springframework.web.server.ResponseStatusException: 404 NOT_FOUND and received org.springframework.web.server.ResponseStatusException:404 NOT_FOUND并收到

    for path https://localhost:8443/api/hello-service/hello/message 用于路径https://localhost:8443/api/hello-service/hello/message

    Unable to Connect 无法连接

    for path http://localhost:8080/hello-service/hello/message 用于路径http://localhost:8080/hello-service/hello/message

Please find the link for the sample applications 请找到示例应用程序的链接

Instructions: 说明:

  • navigate to consul directory and Start consul server using command ./consul agent -dev 导航到consul目录并使用./consul agent -dev命令启动consul服务器
  • run api-gateway spring boot gradle project 运行api-gateway spring boot gradle项目
  • run rest-demo spring boot gradle project 运行rest-demo spring boot gradle项目

Edit 2 编辑2

Thank You @spencergibb, We were able to successfully apply ssl on gateway and call the registered services on HTTP. 谢谢@spencergibb,我们能够在网关上成功应用ssl并通过HTTP调用注册的服务。 Since Spring Webflux with Netty does not support listening on two ports , we created an additional tcp server bind to http port based on this answer . 由于带有Netty的Spring Webflux不支持在两个端口上侦听 ,因此基于此答案 ,我们创建了一个附加的TCP服务器绑定到http端口。

There is still some issue we are facing with RewritePath for /api/ rule 对于/api/规则, RewritePath仍然面临一些问题

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

below is the complete trace for the request 以下是请求的完整跟踪

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}, O DEBUG 13-02-2019 03:32:01 [FilteringWebHandler.java:86] VTC:排序的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},O rderedGatewayFilter{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. rderedGatewayFilter {delegate = GatewayFilterAdapter {delegate=org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@568a9d8f},order = 10100},OrderedGatewayFilter {delegate = GatewayFilterAdapter {delegate=org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@6 ,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跟踪13-02-2019 03:32:02 [GatewayMetricsFilter.java:101] VTC:正在停止带有标签[tag(outcome = CLIENT_ERROR),tag(routeId = rewrite_response_upper)的计时器'gateway.requests',标签(routeUri = http:// httpbin。 org:80),tag(status=NOT_FOUN 组织:80),标签(状态= NOT_FOUN

A number of things were needed 需要做很多事情

  1. disable http2 禁用http2
  2. Disable ssl configuration of httpclient 禁用httpclient的ssl配置
  3. Update locator predicates and filters to use verbose configuration. 更新locator谓词和过滤器以使用详细配置。

Here is the resulting portions of application.yml 这是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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM