spring-cloud / spring-cloud/spring-cloud-gateway

Add new routes by group instead of independent routes

Open
#2,904 0 comments 0 reactions 1 assignee View on GitHub

@spencergibb is already working on this.

Since Mar 23, 2023.

in progress
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

Is your feature request related to a problem? Please describe.

Related to how SCG persists (add + refresh) routes dynamically via Actuator endpoints

Currently, the routes are added one by one using /actuator/gateway/routes/{id}. In order to get changes applied, we need also to call /actuator/gateway/refresh endpoint which iterates over all the RouteDefinitions to refresh the Route instances.

For example, adding two routes requires the next requests

  • POST /actuator/gateway/routes/my-route-1 -> add my-route-1 into RouteDefinitions
  • POST /actuator/gateway/routes/my-route-2 -> add my-route-2 into RouteDefinitions
  • POST /actuator/gateway/routes/refresh -> convert my-route-1 and my-route-2 to Routes

When a route cannot be instantiated (for example, a predicate with wrong arguments), there are some issues depending on the spring.cloud.gateway.failOnRouteDefinitionError flag

When spring.cloud.gateway.failOnRouteDefinitionError=true

  • The wrong route remains in the RouteDefinitions, preventing new routes to be applied because the /refresh will fail silently when the wrong routeDefinition is again processed

When spring.cloud.gateway.failOnRouteDefinitionError=false

  • There is no feedback about the wrong route and the only way to figure out which route is wrong is by sending a request for getting all the routes and checking which wasn’t applied

Additionally, it also has the following issues

  • The /actuator/gateway/routes/refresh replies 200 OK even if the route failed
  • It cannot treat routes as a whole group. If one route is wrong, I don’t want to get routes available yet

It is extremely worth having feedback about which routes are wrong and refreshing them as independent groups. Then, I can update SCG routes incrementally without breaking the current RouteDefinitions I have.

Describe the solution you'd like

To use a metadata label for identifying groups of routes in SCG

  • If one route fails during /refresh, the whole group shouldn’t be applied
  • If no group, the route is treated as “default” group, having the same behaviour as in the past

Describe alternatives you've considered

I considered other options

A. Adding a query parameter to the /refresh endpoint so I can refresh specific route groups

  • But it doesn’t work because CachingRouteLocator rebuilds all the routeDefinitions, so I cannot incrementally refresh new routes

B. To implement a new endpoint that receives N routeDefinitions and validate them

  • The routeDefinitions are converted to Routes
  • Any error is returned in the response with the proper error code
  • If routeDefinitions are valid, the routes are stored in the RouteDefinitions so the next /refresh will apply them as usual

Additional context

Example expected behaviour having SCG running with management port 8090 I would like to get the next response after running the script below

Routes persisted:
"route-1-1"
"route-1-2"
"route-3-1"

Only group-1 and group-3 have a valid configuration.

add_route() {
# ... it depends on the solution, I can share my implementation using groupBy metadata approach
}

add_route "group-1" "route-1-1"
add_route "group-1" "route-1-2"
add_route "group-2" "route-2-1"
add_route "group-2" "route-2-2"
add_route "group-2" "route-2-3" "wrong-uri"
add_route "group-2" "route-2-4"
add_route "group-3" "route-3-1"

curl --location --request POST 'http://localhost:8090/actuator/gateway/refresh'

echo "Routes persisted: " 
curl -s "http://localhost:8090/actuator/gateway/routes" | jq '.[].route_id' 

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.