BewareMyPower commented on issue #24894:
URL: https://github.com/apache/pulsar/issues/24894#issuecomment-3450985038

   The root cause is that Pulsar uses the configured `brokerShutdownTimeoutMs` 
to determine the 1st argument passed to `EventExecutorGroup#shutdownGracefully`.
   
   
https://github.com/apache/pulsar/blob/7c6a4aae336a631e0b88998cf54c656c2f193ba4/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java#L209-L211
   
   
https://github.com/apache/pulsar/blob/7c6a4aae336a631e0b88998cf54c656c2f193ba4/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java#L964-L973
   
   When `brokerShutdownTimeoutMs` is greater than 20000, the 1st argument will 
be 5000.
   
   This parameter represents the period to check if there was a new task 
executed since when the last task finished. See 
https://github.com/netty/netty/blob/6bb1a6bcae503423343b9155ac48b161f60368b5/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java#L785
   
   ```java
           if (nanoTime - lastExecutionTime <= gracefulShutdownQuietPeriod) {
               // Check if any tasks were added to the queue every 100ms.
               // TODO: Change the behavior of takeTask() so that it returns on 
timeout.
               taskQueue.offer(WAKEUP_TASK);
               try {
                   Thread.sleep(100);
               } catch (InterruptedException e) {
                   // Ignore
               }
   
               return false;
           }
   ```
   
   i.e. assuming the 1st argument is 5000, if the last task finished at `t` and 
`confirmShutdown` was called at `t + 1ms`, then it would sleep for 100 ms in a 
loop for at least 50 times so that the current time is greater than `t + 5000`.
   
   Here is a simple test to verify the behavior:
   
   ```java
       @Test
       public void test() {
           final SingleThreadEventExecutor executor = new 
DefaultEventExecutor();
           executor.execute(new Runnable() {
               @Override
               public void run() {
                   System.out.println(Thread.currentThread() + " " + 
System.currentTimeMillis() + " started");
                   try {
                       Thread.sleep(1000);
                   } catch (InterruptedException e) {
                       throw new IllegalStateException(e);
                   }
                   System.out.println(Thread.currentThread() + " " + 
System.currentTimeMillis() + " finished");
               }
           });
           final long startNs = System.nanoTime();
           executor.shutdownGracefully(5000, 10000, 
TimeUnit.MILLISECONDS).syncUninterruptibly();
           final long elapsedMs = 
TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
           System.out.println(Thread.currentThread() + " " + 
System.currentTimeMillis() + " shutdown: "
                   + elapsedMs + " ms");
       }
   ```
   
   Outputs:
   
   ```
   Thread[defaultEventExecutor-1-1,5,main] 1761566989756 started
   Thread[defaultEventExecutor-1-1,5,main] 1761566990761 finished
   Thread[main,5,main] 1761566995846 shutdown: 6090 ms
   ```
   
   Pulsar's `EventLoop` object created by `EventLoopUtils#newEventLoopGroup` 
uses `NioEventLoop` as the executor, which does not change the 
`confirmShutdown` and `shutdownGracefully` methods from the 
`SingleThreadEventExecutor` base class.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to