Delete zuul route dynamically without restarting the gateway
Asked Answered
T

3

7

Hi I want to delete the zuul route which has been created dynamically. Im not using cloud server. Im able to add the routes using discoveryclientroutelocator.

But I don't find an option to de-register the route added dynamically. This deletion should happen without restarting the gateway. help.

    ZuulRoute zuulRoute = new ZuulRoute();
    zuulRoute.setId(externalapis.getServiceId());
    zuulRoute.setServiceId(externalapis.getServiceId());
    zuulRoute.setPath(externalapis.getPath());
    zuulRoute.setUrl(externalapis.getUrl());
    zuulRoute.setRetryable(true);
    discoveryClientRouteLocator.addRoute(zuulRoute);
Tetanic answered 12/3, 2019 at 10:40 Comment(2)
is this question and answer help? #40220965Proclus
Could you please share more information? if you are using on a discovery microservice?or just a service... more information about what you want to do.Dittmer
T
1

I used below code to add, delete and update.It works without restarting the gateway

Add Route:

this.zuulProperties.getRoutes().put(externalapis.getServiceId(), zuulRoute);

Delete Route:

this.zuulProperties.getRoutes().remove(externalapis.getServiceId());

Update Route:

this.zuulProperties.getRoutes().remove(oldExternalapis.getServiceId());

this.zuulProperties.getRoutes().put(newExternalapis.getServiceId(), zuulRoute);
Tetanic answered 26/4, 2019 at 3:17 Comment(0)
M
4

You can extend DiscoveryClientRouteLocator and add removeRoute() method: Here is my example of this

@SpringBootApplication
@EnableZuulProxy
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }


    public static class DeregistrableDiscoveryClientRouteLocator extends DiscoveryClientRouteLocator {
        private final ZuulProperties properties;
        public DeregistrableDiscoveryClientRouteLocator(String servletPath, DiscoveryClient discovery, ZuulProperties properties, ServiceInstance localServiceInstance) {
            super(servletPath, discovery, properties, localServiceInstance);
            this.properties = properties;
        }
        public DeregistrableDiscoveryClientRouteLocator(String servletPath, DiscoveryClient discovery, ZuulProperties properties, ServiceRouteMapper serviceRouteMapper, ServiceInstance localServiceInstance) {
            this(servletPath, discovery, properties, localServiceInstance);
        }
        //here is new method to remove route from .properties.getRoutes()
        public void removeRoute(String path) {
            this.properties.getRoutes().remove(path);
            refresh();
        }
    }

    @Bean
    DiscoveryClientRouteLocator discoveryClientRouteLocator(ServerProperties server, ZuulProperties zuulProperties, DiscoveryClient discovery, ServiceRouteMapper serviceRouteMapper, @Autowired(required = false) Registration registration) {
        return new DeregistrableDiscoveryClientRouteLocator(server.getServlet().getContextPath(),
                discovery, zuulProperties, serviceRouteMapper,
                registration);
    }

    @Component
    public static class AppRunner implements ApplicationRunner {
        @Autowired
        DeregistrableDiscoveryClientRouteLocator discoveryClientRouteLocator;

        @Override
        public void run(ApplicationArguments args) throws Exception {

            ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
            zuulRoute.setId("google");
            zuulRoute.setServiceId("google");
            zuulRoute.setPath("/");
            zuulRoute.setUrl("http://google.com");
            zuulRoute.setRetryable(true);
            discoveryClientRouteLocator.addRoute(zuulRoute);

            //now remove the pre-added route.
            discoveryClientRouteLocator.removeRoute(zuulRoute.getPath());
        }
    }
}

So after that you can create a rest endpoint which will remove a route without restarting the server.

Marsh answered 21/3, 2019 at 11:20 Comment(6)
I tried Still it doesn't work. the interface doesn't have option to delete route. I think I gotta try updating the applicaiton.yml file. That's the only option working.Tetanic
I have extended DiscoveryClientRouteLocator and added removeRoute method into it. so you now can use the extended version of the class to remove route dynamically aka DeregistrableDiscoveryClientRouteLocator. (you should autowire DeregistrableDiscoveryClientRouteLocator and not standard DiscoveryClientRouteLocator)Marsh
Hi stackoverflow.com/users/1241218/nonika, I got below error, It is not allowing me to create bean by extending the discoveryclientroutelocator caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'myDiscoveryClient': Requested bean is currently in creation: Is there an unresolvable circular reference? at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:339)Tetanic
you can create a simple project with my configuration to test. just simple spring boot project with spring-cloud-starter-netflix-zuul and with my DemoApplication config.Marsh
can you show me your extended class? the bean you are trying to create with myDiscoveryClient nameMarsh
Hi Nonika, I guess its singleton bean and it is not allowing me to create one. I used zuulproperties.getRoutes().remove(zuulRoute) which worked. Thanks for your helpTetanic
T
1

I used below code to add, delete and update.It works without restarting the gateway

Add Route:

this.zuulProperties.getRoutes().put(externalapis.getServiceId(), zuulRoute);

Delete Route:

this.zuulProperties.getRoutes().remove(externalapis.getServiceId());

Update Route:

this.zuulProperties.getRoutes().remove(oldExternalapis.getServiceId());

this.zuulProperties.getRoutes().put(newExternalapis.getServiceId(), zuulRoute);
Tetanic answered 26/4, 2019 at 3:17 Comment(0)
D
0

you might use @RefreshScope annotation in order to refresh properties:

1.- Add @RefreshScope on the class

@RefreshScope
@Component
public class ApplicationTest {

    @Autowired
    DiscoveryClientRouteLocator discoveryClientRouteLocator;

    @Value("${custom.property.id}")
    private String id;

    @Value("${custom.property.serviceId}")
    private String serviceId;

    @Value("${custom.property.path}")
    private String path;

    @Value("${custom.property.url}")
    private String url;

    @Value("${custom.property.retryable}")
    private boolean retryable;


    public void buildNewRoute(){
        ZuulRoute zuulRoute = new ZuulRoute();
        zuulRoute.setId(id);
        zuulRoute.setServiceId(serviceId);
        zuulRoute.setPath(path);
        zuulRoute.setUrl(url);
        zuulRoute.setRetryable(retryable);
        discoveryClientRouteLocator.addRoute(zuulRoute);
    }
}

2.- Add flag property and allow exposure the endpoint /refresh in order to refresh new properties.

application.properties

    custom.property.id=1
    custom.property.serviceId=service-id-01
    custom.property.path=/this/path
    custom.property.url=http://localhost:7070
    custom.property.retryable=true
    management.endpoints.web.exposure.include=*

3.- Once the application.properties is modified for example:

    custom.property.id=3
    custom.property.serviceId=service-id-03
    custom.property.path=/this/path/new3
    custom.property.url=http://localhost:9999
    custom.property.retryable=false

Then you can refresh configurations injected doing:

 curl localhost:8080/actuator/refresh -d {} -H "Content-Type: application/json"

REFERENCES - https://spring.io/guides/gs/centralized-configuration/

Dittmer answered 21/3, 2019 at 21:43 Comment(1)
Refreshing is working fine. It's just the update/delete which is not an available option programmaticallyTetanic

© 2022 - 2024 — McMap. All rights reserved.