spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.5k stars 3.31k forks source link

Allow to pass port to `uri` value and replace Eureka port with this value #1474

Open mbronshteyn opened 4 years ago

mbronshteyn commented 4 years ago

Allow to pass port as configuration parameter. For example uri would look like this:

    .route(p -> p
            .path("/sentence-service/**")
                        .filters( f-> f
                .rewritePath(
                                "/sentence-service/(?<segment>.*)", "/$\\{segment}")
                                .retry( 3 )
                        )
                        .uri( "lb://SENTENCE:8081" )
                )
                .build();

In this case Gateway will fetch path info from Eureka, but will use port 8081

Extend ReactiveLoadBalancerClientFilter class. Check if port is passed. If so, replace port from Eureka with the one passed.

spencergibb commented 4 years ago

why would you want to do this?

mbronshteyn commented 4 years ago

There is the scenario. Microservices are registered with Eureka and Gloud Gateway resolves the location and port from Eureka. management.server.port is configured on separate port, compare to server.port. In such case there is no way to route health check request ( /actuator/health ) to microservices, as you only have server.port from Eureka. This change would allow to specify the port which would override the Eureka port and will allow to access /actuator/health. @sabareeshkkanan

spencergibb commented 4 years ago

A health check thru a gateway is meaningless because you don't know what instance you are hitting. I'm not sure this is functionality I want to support.

mbronshteyn commented 4 years ago

I could for-see the scenario where external tool wants to check the status of the microservices. Let's say there is Spring Security configuration, which does not allow to go to mircorservice but only through gateway

http.authorizeRequests()
      .antMatchers("/**").hasIpAddress( gatewayIp )
      .and().addFilter( authenticationFilter );

In this case the only way to get to service is via Gateway. The tool can issue requests with the time interval and will alarm that service is down.

Yes, there is no way to tell which service is down, but Gateway will load balance the requests and will cover all of them which are still registered with Eureka but not healthy.

@sabareeshkkanan

spencergibb commented 4 years ago

Not a valid way to check health IMO. I've marked it as waiting for votes.

mbronshteyn commented 4 years ago

Please find the diagram below. We have users going through WAF, Cloud Gateway and Eureka to application port 8080 ( server.port ).

At the same WAF Health Check module is going through Cloud Gateway and Eureka checking health check on management.server.port 8081.

Screen Shot 2019-12-12 at 3 16 47 PM
mbronshteyn commented 4 years ago

Below is the example from our nginx config file which shows our current configuration

location ^~ /health {client_max_body_size 0;

proxy_read_timeout 300;proxy_connect_timeout 300;proxy_redirect off;

proxy_http_version 1.1;proxy_set_header X-Forwarded-Proto https;proxy_set_header Host $http_host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-Ssl on;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection $connection_upgrade;

proxy_hide_header Strict-Transport-Security;proxy_pass http://gateway:8081/actuator/health;}

location / {client_max_body_size 0;

proxy_read_timeout 300;proxy_connect_timeout 300;proxy_redirect off;

proxy_http_version 1.1;proxy_set_header X-Forwarded-Proto https; proxy_set_header Host $http_host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-Ssl on;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection $connection_upgrade;

proxy_hide_header Strict-Transport-Security;proxy_pass http://gateway:8080;}

@sabareeshkkanan

mbronshteyn commented 4 years ago

@spencergibb Hi Spencer. Could you please share how you would approach this problem? Thank you.

gabrielplanteia commented 4 years ago

@spencergibb we have a very similar use case where a company main gateway has to check the status of a service under a business division gateway in order to decide wether it returns a generic error page or not. What do you suggest?