2017-07-16 149 views
0

由于实现了重新启动机制,我正面临使用ScheduledExecutorService的错误行为。ScheduledExecutorService Thread创建多个线程

问题 - 短

每次重新启动尝试创建一个新的计划任务,然后重新启动旧的。

问题 - 龙

过程的目标是发布消息到RabbitMQ的不时(这是保活)。当RabbitMQ发生异常时,它使用ExceptionObserver通知 发生异常。实现的ExceptionObserver会停止服务并重新启动它。它试图重启3次,如果重启成功,计数为 重置为零。如果无法重新启动,则尝试计数会递增,如果达到尝试限制,则会关闭该过程。

每次服务重新启动时,它都会创建一个新的“KeepAliveService”并重新启动最后的服务。因此,每次发生异常时,都会创建一项新服务,并重新启动旧的服务。如果重启后有1次异常,则有2个进程正在运行。如果2个异常事件有3个进程正在运行,依此类推。

服务类处理保持连接服务(启动/停止ScheduledExecutorService的)

private KeepaliveExecutor keepaliveExecutor; // This is the runnable used inside the scheduledService 
private ScheduledFuture futureTask; // The escheduled task 
private ScheduledExecutorService scheduledService; // the scheduled service 
private ExceptionObserver exceptionObserver; // The Exception Handler, which will handle the exceptions 

public void startService(final int keepaliveTime) throws IllegalArgumentException, FInfraException { 
    keepaliveExecutor = new KeepaliveExecutor(new RabbitMQService(settings), settings); 
    keepaliveExecutor.setExceptionObserver(exceptionObserver); 
    scheduledService = Executors.newSingleThreadScheduledExecutor(); 
    futureTask = scheduledService.scheduleAtFixedRate(keepaliveExecutor, 0, keepaliveTime, TimeUnit.MINUTES); 
} 

public void stopService() { 
    futureTask.cancel(true); 
    scheduledService.shutdown(); 
} 

的KeepaliveExecutor类

class KeepaliveExecutor implements Runnable { 

private FInfraExceptionObserver exceptionObserver; 

@Override 
public void run() { 
    try { 
     final String keepAlive = JsonMapper.toJsonString(keepaliveMessage); 
     rabbitService.publishMessage(keepAlive); 
     keepaliveMessage.setFirtsPackage(false); 
    } catch(FInfraException ex) { 
     if(exceptionObserver != null) { 
      exceptionObserver.notifyExpcetion(ex); 
     } 
    }   
} 

的ExceptionObserver实现类

public class FInfraExceptionHandler implements FInfraExceptionObserver { 

private final FInfraServiceHandler finfraHandler; 

public FInfraExceptionHandler(FInfraServiceHandler finfraHandler) { 
    this.finfraHandler = finfraHandler; 
} 

@Override 
public void notifyExpcetion(Throwable ex) { 
    Util.logger.log(Level.INFO, "F-Infra Exception occurred", ex); 
    finfraHandler.stopService(); 
    Util.logger.log(Level.INFO, "Waiting 30s for restarting..."); 
    Util.wait(30, TimeUnit.SECONDS); 
    finfraHandler.startService(); 
} 

的FInfraServiceHandler

public class FInfraServiceHandler { 

private static final int ATTEMPT_LIMIT = 3; 

private FInfraService finfraService; 
private int keepaliveTime; 
private int attempt; 

public FInfraServiceHandler() { 
    this.finfraService = new FInfraService(); 
    this.finfraService.setExceptionObserver(new FInfraExceptionHandler(this)); 
    this.attempt = 0; 
} 

void startService(){ 
    if(attempt <= ATTEMPT_LIMIT) { 
     try { 
      attempt++; 
      Util.logger.log(Level.INFO, "Starting F-Infra Service. Attemp[{0} of {1}]", new String[]{String.valueOf(attempt), String.valueOf(ATTEMPT_LIMIT)}); 
      finfraService.startService(keepaliveTime); 
     } catch(FInfraException | RuntimeException ex){ 
      Util.logger.log(Level.INFO, "F-INFRA EXCEPTION", ex); 
      startService(); 
     } 
     Util.logger.log(Level.INFO, "F-Infra started!"); 
     attempt = 0; 
     return; 
    } 
    Util.logger.log(Level.INFO, "Restart attemp limit reached."); 
    Main.closeAll(new ShutdownException("It's not possible stablish a connection with F-Infra Service.")); 
} 

public void stopService() { 
    if(attempt > 0){ 
     Util.logger.log(Level.INFO, "Stpoping F-Infra..."); 
     finfraService.stopService(); 
    } 
} 

这里如下这告诉我有运行

jul 16, 2017 2:58:03 PM domain.FInfraServiceHandler startService 
INFO: Starting F-Infra Service. Attemp[1 of 3] 
jul 16, 2017 2:58:03 PM domain.FInfraServiceHandler startService 
INFO: F-Infra started! 
jul 16, 2017 5:01:15 PM domain.FInfraExceptionHandler notifyExpcetion 
INFO: F-Infra Exception occurred 
domain.FInfraException: java.net.UnknownHostException: rabbit.domain 
     at domain.RabbitMQService.openConnection(RabbitMQService.java:48) 
     at domain.RabbitMQService.publishMessage(RabbitMQService.java:66) 
     at domain.KeepaliveExecutor.run(KeepaliveExecutor.java:38) 
     at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) 
     at java.util.concurrent.FutureTask.runAndReset(Unknown Source) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
     at java.lang.Thread.run(Unknown Source) 
Caused by: java.net.UnknownHostException: rabbit.domain 
     at java.net.AbstractPlainSocketImpl.connect(Unknown Source) 
     at java.net.PlainSocketImpl.connect(Unknown Source) 
     at java.net.SocksSocketImpl.connect(Unknown Source) 
     at java.net.Socket.connect(Unknown Source) 
     at com.rabbitmq.client.impl.FrameHandlerFactory.create(FrameHandlerFactory.java:32) 
     at com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory.newConnection(RecoveryAwareAMQConnectionFactory.java:34) 
     at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.init(AutorecoveringConnection.java:91) 
     at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:670) 
     at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:722) 
     at domain.RabbitMQService.openConnection(RabbitMQService.java:45) 
     ... 9 more 

jul 16, 2017 5:01:15 PM domain.FInfraExceptionHandler notifyExpcetion 
INFO: Waiting 30s for restarting... 
jul 16, 2017 5:01:45 PM domain.FInfraServiceHandler startService 
INFO: Starting F-Infra Service. Attemp[1 of 3] 
jul 16, 2017 5:01:45 PM domain.FInfraServiceHandler startService 
INFO: F-Infra started! 
jul 16, 2017 6:01:58 PM domain.FInfraExceptionHandler notifyExpcetion 
INFO: F-Infra Exception occurred 
domain.FInfraException: java.net.UnknownHostException: rabbit.domain 
     at domain.RabbitMQService.openConnection(RabbitMQService.java:48) 
     at domain.RabbitMQService.publishMessage(RabbitMQService.java:66) 
     at domain.KeepaliveExecutor.run(KeepaliveExecutor.java:38) 
     at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) 
     at java.util.concurrent.FutureTask.runAndReset(Unknown Source) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
     at java.lang.Thread.run(Unknown Source) 
Caused by: java.net.UnknownHostException: rabbit.domain 
     at java.net.AbstractPlainSocketImpl.connect(Unknown Source) 
     at java.net.PlainSocketImpl.connect(Unknown Source) 
     at java.net.SocksSocketImpl.connect(Unknown Source) 
     at java.net.Socket.connect(Unknown Source) 
     at com.rabbitmq.client.impl.FrameHandlerFactory.create(FrameHandlerFactory.java:32) 
     at com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory.newConnection(RecoveryAwareAMQConnectionFactory.java:34) 
     at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.init(AutorecoveringConnection.java:91) 
     at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:670) 
     at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:722) 
     at domain.RabbitMQService.openConnection(RabbitMQService.java:45) 
     ... 9 more 

jul 16, 2017 6:01:58 PM domain.FInfraExceptionHandler notifyExpcetion 
INFO: Waiting 30s for restarting... 
jul 16, 2017 6:02:03 PM domain.FInfraExceptionHandler notifyExpcetion 
INFO: F-Infra Exception occurred 
domain.FInfraException: java.net.UnknownHostException: rabbit.domain 
     at domain.RabbitMQService.openConnection(RabbitMQService.java:48) 
     at domain.RabbitMQService.publishMessage(RabbitMQService.java:66) 
     at domain.KeepaliveExecutor.run(KeepaliveExecutor.java:38) 
     at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) 
     at java.util.concurrent.FutureTask.runAndReset(Unknown Source) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
     at java.lang.Thread.run(Unknown Source) 
Caused by: java.net.UnknownHostException: rabbit.domain 
     at java.net.AbstractPlainSocketImpl.connect(Unknown Source) 
     at java.net.PlainSocketImpl.connect(Unknown Source) 
     at java.net.SocksSocketImpl.connect(Unknown Source) 
     at java.net.Socket.connect(Unknown Source) 
     at com.rabbitmq.client.impl.FrameHandlerFactory.create(FrameHandlerFactory.java:32) 
     at com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory.newConnection(RecoveryAwareAMQConnectionFactory.java:34) 
     at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.init(AutorecoveringConnection.java:91) 
     at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:670) 
     at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:722) 
     at domain.RabbitMQService.openConnection(RabbitMQService.java:45) 
     ... 9 more 

jul 16, 2017 6:02:03 PM domain.FInfraExceptionHandler notifyExpcetion 
INFO: Waiting 30s for restarting... 
jul 16, 2017 6:02:28 PM domain.FInfraServiceHandler startService 
INFO: Starting F-Infra Service. Attemp[1 of 3] 
jul 16, 2017 6:02:28 PM domain.FInfraServiceHandler startService 
INFO: F-Infra started! 
jul 16, 2017 6:02:33 PM domain.FInfraServiceHandler startService 
INFO: Starting F-Infra Service. Attemp[1 of 3] 
jul 16, 2017 6:02:33 PM domain.FInfraServiceHandler startService 
INFO: F-Infra started! 

我不知道该怎么办,关闭旧线,或者使用当前的重新启动多个服务日志。我尝试过的很多方法都是调用Thread.currentThread()。interrupt();在调用start方法之前调用ExceptionObserver类。 但这并不奏效。

我不知道该怎么做。

回答

2

FInfraServiceHandler类中,如果attempt为零,则stopService方法不会执行任何操作。

public void stopService() { 
    if(attempt > 0){ 
     Util.logger.log(Level.INFO, "Stpoping F-Infra..."); 
     finfraService.stopService(); 
    } 
} 

所以原来的ScheduledExecutorService继续前进。当我删除条件时,代码表现良好。

请注意,顺便说一下,您在同一实例上从不同的线程调用startServicestopService。我想你需要在可变字段attempt上进行某种同步。

相关问题