Voice social source code restart, how will the tasks being performed be handled?

1. Preface

How will ongoing requests be handled during the restart of voice social source code? Will the message being consumed be lost? Will asynchronous tasks be interrupted? Since these problems exist, can't our voice social source code be restarted? However, our voice social source code is constantly restarted with the version iteration. Why do these problems not appear? Or did the application do additional processing? With these questions, combined with the scene simulation, see how to deal with the actual situation.

2. Scenario

2.1 http request

2.1. 1 create request

@RestController
public class ShutDownController {

    @RequestMapping("shut/down")
    public String shutDown() throws InterruptedException {
        TimeUnit.SECONDS.sleep(20);
        return "hello";
    }
}

2.1. 2 call request

2.1. 3 simulation restart

kill -2 application pid

2.1. 4 phenomenon

2.1. 5 Conclusion

During the execution of the request, the voice social source code is closed, and a prompt of inaccessibility appears

2.1. 6 turn on and turn off gracefully

The above phenomenon is very unfriendly to users and will cause users to look confused. Are there any measures to avoid this phenomenon? Can I execute accepted requests and reject new requests before the application closes? Yes, just add an elegant shutdown configuration in the voice social source code configuration file

server:
  shutdown: graceful # Set elegant shutdown. This function is available in spring boot2 Only in version 3. Note: you need to use Kill -2 trigger to close the application. This command will trigger shutdown hook

spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s # Set the buffer time. Pay attention to the time unit (this time is used to wait for the completion of task execution)

After adding the configuration, execute 2.1.1 again 2 and 2.1 3 process, you will see the following effects

It can be seen that even if the voice social source code is closed during the request execution, the received request will still be executed

2.2 message consumption

As mentioned in the preface, in the process of message consumption, if the voice social source code is closed, will the message be lost or put back into the message queue?

2.2. 1 create producer

@RestController
public class RabbitMqController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/sendBusinessMessage")
    public void sendBusinessMessage() throws InterruptedException {
        rabbitTemplate.convertAndSend(RabbitmqConfig.BUSINESS_EXCHANGE, RabbitmqConfig.BUSINESS_ROUTING_KEY, "send message");
        TimeUnit.SECONDS.sleep(10000);
    }
}

2.2. 2 create a consumer

@Component
@RabbitListener(queues = RabbitmqConfig.BUSINESS_QUEUE_NAME)
@Slf4j
public class BusinessConsumer {

    /**
     * Operation scenario:
     * 1.Start the application through the RabbitmqApplication startup class
     * 2.Call the / sendBusinessMessage interface to send a message
     * 3.RabbitMQ broker Send message to consumer
     * 4.Consumers consume after receiving the message
     * 5.When consumers consume messages, the application closes, the channel is disconnected, the connection is disconnected, and the messages without ack will be put back into the broker
     *
     * @param content Message content
     * @param channel channel passageway
     * @param message message object
     */
    @RabbitHandler
    public void helloConsumer(String content, Channel channel, Message message) {
        log.info("business consumer receive message: {}", content);
        try {
            // Simulated business execution time
            TimeUnit.SECONDS.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.2. 3 call request

2.2. 4 before closing the application

2.2. 5 after closing the application

2.2. 6 Conclusion
In the process of message consumption, turn off the voice social source code, and the messages without ack will be put back into the message queue to ensure that the messages will be consumed

2.3 asynchronous tasks

2.3. 1. Configuration of route pool

@Component
public class ThreadPoolConfig {

    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setThreadNamePrefix("test-");
        threadPoolTaskExecutor.setCorePoolSize(3);
        threadPoolTaskExecutor.setMaxPoolSize(3);
        threadPoolTaskExecutor.setQueueCapacity(100);
        return threadPoolTaskExecutor;
    }
}

2.3. 2 asynchronous task request

@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;

@RequestMapping("async/task")
public void asyncTask() throws InterruptedException {
  for (int i = 0; i < 10; i++) {
    threadPoolTaskExecutor.execute(() -> {
      try {
        TimeUnit.SECONDS.sleep(10);
      } catch (InterruptedException e) {
        throw new RuntimeException();
      }
      log.info("task execute complete...");
    });
  }
}

2.3. 3 call request

2.3. 4 simulation restart

kill -2 application pid

2.3. 5 phenomenon

Exception in thread "test-2" Exception in thread "test-1" Exception in thread "test-3" java.lang.RuntimeException
	at com.boot.example.ShutDownController.lambda$asyncTask$0(ShutDownController.java:37)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
java.lang.RuntimeException
	at com.boot.example.ShutDownController.lambda$asyncTask$0(ShutDownController.java:37)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
java.lang.RuntimeException
	at com.boot.example.ShutDownController.lambda$asyncTask$0(ShutDownController.java:37)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

2.3. 6. Modify thread pool configuration

Add the following configuration to the thread pool configuration:

threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskExecutor.setAwaitTerminationSeconds(120);

2.3. 7 phenomena after modifying the configuration

2021-12-09 17:09:40.054  INFO 22383 --- [         test-1] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:09:40.055  INFO 22383 --- [         test-3] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:09:40.055  INFO 22383 --- [         test-2] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:09:50.059  INFO 22383 --- [         test-3] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:09:50.059  INFO 22383 --- [         test-1] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:09:50.060  INFO 22383 --- [         test-2] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:10:00.062  INFO 22383 --- [         test-2] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:10:00.062  INFO 22383 --- [         test-1] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:10:00.065  INFO 22383 --- [         test-3] com.boot.example.ShutDownController      : task execute complete...
2021-12-09 17:10:10.066  INFO 22383 --- [         test-1] com.boot.example.ShutDownController      : task execute complete...

2.3. 8 conclusion

Use the thread pool to execute asynchronous tasks. Tasks cannot be completed without adding configurations. Tasks can still be completed with adding configurations.

3. Summary

In order to ensure that tasks can still be executed and completed during the restart of voice social source code, you need to turn on the graceful shutdown configuration and add the waiting task execution completion and waiting time configuration to the thread pool

Keywords: Java Linux

Added by rockstarmike on Tue, 14 Dec 2021 10:59:09 +0200