Spring MVC WebApp:@schedule:java-sdk-http-connection-reaper:无法停止

age*_*ntx 15 java spring tomcat spring-mvc amazon-dynamodb

我有一个Web应用程序(使用Spring 3.1),它使用@Scheduled Annotation定期执行一个worker任务(计划延迟).工作人员任务打开与AWS DynamoDb的连接,并执行一些数据库读取/更新.当我停止webapp(来自Tomcat经理)时,我在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();
      }
          }

}
Run Code Online (Sandbox Code Playgroud)

调度员servlet.xml中:

<task:annotation-driven scheduler="taskScheduler"/>
<task:scheduler id="taskScheduler" pool-size="2"/>
......
<bean id="TaskScheduler" class="com.sample.TaskScheduler"/>
Run Code Online (Sandbox Code Playgroud)

我这样做了吗?a)我没有明确启动TaskScheduler.所以我假设spring负责启动这项服务.调用'this.myDbConn.shutdown()'.尽管如此,我还是得到了错误.我正在使用Spring MVC.

Dav*_*ell 13

这可能是由AWS库在后台启动一个名为com.amazonaws.http.IdleConnectionReaper的线程引起的.

您可以通过实现ServletContextListener来关闭它,以便在关闭时关闭它

public class YourListener implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent contextEvent) {

}

@Override
public void contextDestroyed(ServletContextEvent contextEvent) {

    try {
        com.amazonaws.http.IdleConnectionReaper.shutdown();
    } catch (Throwable t) {
        // log the error
    }
}
}
Run Code Online (Sandbox Code Playgroud)

并将其添加到您的web.xml

<listener>
    <listener-class>
        your.package.YourListener 
    </listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)


Stu*_*art 9

我也遇到过这个问题,但我决定采用上述@ David_Wartell的替代解决方案.

我跟踪了从Amazon的aws-java-sdk库中创建一个有问题的对象/对象的类,这些库启动了IdleConnectionReaper线程但从未关闭(这些是com.amazonaws.services.ec2.AmazonEC2Client和com.amazonaws.services .cloudwatch.AmazonCloudWatchClient).然后我在这个类中添加了一个destroy()方法,它调用静态方法com.amazonaws.http.IdleConnectionReaper.shutdown().当类被垃圾收集并且使用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>
Run Code Online (Sandbox Code Playgroud)

YourBeanName.java - (创建有问题的亚马逊对象的类)

    public class YourBeanName {

        // omitted code

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

        // omitted code

    }
Run Code Online (Sandbox Code Playgroud)

引用:

亚马逊论坛 - 关闭IdleConnectionReaper
Spring文档 - 自定义bean的性质