简体   繁体   中英

Count number of active HTTP Requests in a Spring MVC container

In a rolling upgrade scenario, I would like to know when there are no active HTTP requests in a given Spring MVC container (starter by Spring Boot, running on Jetty).

That would allow the following flow:

  1. Disable server in reverse proxy
  2. Wait for all requests to finish
  3. Perform upgrade

Is there any way to tell how many requests are currently being handled in Spring MVC or Jetty?

You can get information about the number of active requests using Jetty's StatisticsHandler and JMX.

If you're using Jetty as an embedded container (the recommended approach), you can use an EmbeddedServletContainerCustomizer to set this up:

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {

        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            ((JettyEmbeddedServletContainerFactory) container)
                    .addServerCustomizers(new JettyServerCustomizer() {

                @Override
                public void customize(Server server) {
                    MBeanContainer mbContainer = new MBeanContainer(
                            ManagementFactory.getPlatformMBeanServer());
                    server.addEventListener(mbContainer);
                    server.addBean(mbContainer);

                    StatisticsHandler statisticsHandler = new StatisticsHandler();
                    statisticsHandler.setHandler(server.getHandler());
                    server.setHandler(statisticsHandler);
                }
            });
        }

    };
}

You'll need to add a dependency on org.eclipse.jetty:jetty-jmx to get access to MBeanContainer .

You can try with spring boot actuator. On endpoint /metrics you should have field "httpsessions.active"

You can think of using AoP. That worked for me. Snippets of code from my project:

public class CommonJoinPointConfig {

    @Pointcut("execution(* ru.outofrange.controller.ClaimController.searchClaims(..))")
    public void searchClaims() {
    }

}


@Aspect
public class CounterAspect {

    public CounterAspect() {
    }

    public CounterAspect(MBeanService mBeanService) {
        this.mBeanService = mBeanService;
    }

    @Before("ru.outofrange.aspect.CommonJoinPointConfig.searchClaims()")
    public void beforeMethod() {
        counterService.increaseNumberOfRunningRequests();
    }

    @After("ru.outofrange.aspect.CommonJoinPointConfig.searchClaims()")
    public void afterMethod() {
         counterService.decreaseNumberOfRunningRequests();
    }

}

@Configuration
@ComponentScan(value = {"ru.outofrange.controller", "ru.outofrange.mbean"})
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class RestConfig extends RepositoryRestConfigurerAdapter {

    @Autowired
    private CounterService counterService;

    @Bean
    CounterAspect counterAspect(CounterService counterService){
        return new CounterAspect(counterService);
    }

    ...
}

Some notes. In the Config you should use @EnableAspectJAutoProxy(proxyTargetClass=true) and this annotation should be added into the Config, which scans package with controller and the service, ie the defined aspect, the controller and the service should be in the same Spring context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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