17

@Scheduled Annotation を使用して定期的にワーカー タスクを実行する (スケジュールされた遅延) Web アプリケーション (Spring 3.1 を使用) があります。ワーカー タスクは AWS DynamoDb への接続を開き、DB の読み取り/更新を行います。(Tomcat マネージャーから) webapp を停止すると、catalina.out に次のメッセージが表示されます。

「重大: Web アプリケーション [] は、[java-sdk-http-connection-reaper] という名前のスレッドを開始したようですが、停止できませんでした。これにより、メモリ リークが発生する可能性が非常に高くなります。」

これは、Tomcat が停止した後もスケジュールされたタスクがまだ実行されていることに関係しているように感じます。

@Service
public class TaskScheduler implements ApplicationListener<ContextClosedEvent>{

@Autowired
private WorkerTask workerTask;

AmazonDynamoDBClient myDbConn = null;

   private TaskScheduler() {    
   myDbConn = new AWSConnector("aws.properties").getDynamoConnection();
   }

/*
 * Will be repeatedly called, 10 seconds after the finish of the previous 
 * invocation.
 */
@Scheduled(fixedDelay=100000)
public void process() {
    System.out.println("Scheduling worker task");
            //worker task does some db read/writes
    Future<String> status = workerTask.work(myDbConn);
    if (status.isDone()) {
        System.out.println("Completed Task");
        return;
    }

}

@Override
public void onApplicationEvent(ContextClosedEvent arg0) {
    if(event instanceof ContextClosedEvent) {   
      // TODO Auto-generated method stub
      if(myDbConn != null) {
        this.myDbConn.shutdown();
      }
          }

}

ディスパッチャーサーブレット.xml:

<task:annotation-driven scheduler="taskScheduler"/>
<task:scheduler id="taskScheduler" pool-size="2"/>
......
<bean id="TaskScheduler" class="com.sample.TaskScheduler"/>

私はこれを正しくやっていますか?a) TaskScheduler を明示的に開始しません。したがって、春がこのサービスの開始を処理すると想定しています。「this.myDbConn.shutdown()」が呼び出されます。それにもかかわらず、エラーが発生します。Spring MVC を使用しています。

4

3 に答える 3

9

私もこの問題を抱えていましたが、上記の@David_Wartellの代替ソリューションを決定しました。

Amazon の aws-java-sdk ライブラリから、IdleConnectionReaper スレッドを起動しているがシャットダウンしない問題のあるオブジェクトを作成していたクラスを追跡しました (これらはcom.amazonaws.services.ec2.AmazonEC2Clientおよび com.amazonaws.servicesでした)。 .cloudwatch.AmazonCloudWatchClient _)。次に、静的メソッド com.amazonaws.http.IdleConnectionReaper.shutdown() を呼び出す destroy() メソッドをこのクラスに追加しました。クラスがガベージ コレクションされ、Spring applicationContext.xml を使用して構成されている場合、destroy メソッドが呼び出されます。この方法の利点は、非 Web アプリケーションでも機能し、Web コンテキストからスレッドのシャットダウンを切り離すことです。適切な解決策は、IdleConnectionReaper スレッドを開始する amazon aws-java-sdk ライブラリのクラスがそれをシャットダウンする必要がありますが、シャットダウンしないため、このバグです。私の解決策については、以下の参照とコード スニペットを参照してください。

applicationContext.xml

<bean id="YourBeanName" class="com.your.package.name.YourBeanName" destroy-method="destroy">
    <!-- other optional configuration goes here -->
</bean>

YourBeanName.java - (問題のある amazon オブジェクトを作成するクラス)

    public class YourBeanName {

        // omitted code

        public void destroy() {
            com.amazonaws.http.IdleConnectionReaper.shutdown();
        }

        // omitted code

    }

参照:

Amazon フォーラム - IdleConnectionReaper
Spring ドキュメントのシャットダウン - Bean の性質のカスタマイズ

于 2013-12-17T11:30:48.150 に答える
4

スチュアートの答えに加えて(そしてSpringを使用していると仮定して)、XML構成ファイルを使用しない場合の代替手段:

@Component
public class MyBean {

// ...

    @PreDestroy
    private void cleanUp() {
        try {
            // Shutting down AWS IdleConnectionReaper thread...
            com.amazonaws.http.IdleConnectionReaper.shutdown();
        } catch (Throwable t) {
            // log error
        }
    }

}

com.amazonaws.services.s3.AmazonS3インターフェイスを実装する Bean を使用したとき、それはうまくいきました。

于 2014-08-28T14:43:16.607 に答える