提问者:小点点

SpringMVCWebApp:@时间表:java-sdk-超文本传输协议-连接-收割机:无法停止


我有一个Web应用程序(使用Spring3.1),它使用@调度注释来定期执行工作任务(调度延迟)。工作任务打开与AWSDynamoDb的连接,并执行一些DB读取/更新。当我停止webapp(来自Tomcat管理器)时,我在catalina. out中收到此消息:

"SEVERE:Web应用程序[]似乎已经启动了一个名为[java-sdk-超文本传输协议-连接-收割机]的线程,但未能阻止它。这很可能会造成内存泄漏。"

我有一种感觉,这与我的计划任务在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();
      }
          }

}

调度程序-ser v let. xml:

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

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


共3个答案

匿名用户

这可能是由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
    }
}
}

并将其添加到您的web. xml

<listener>
    <listener-class>
        your.package.YourListener 
    </listener-class>
</listener>

匿名用户

我也有这个问题,但我决定了上面@David_Wartell的替代解决方案。

我从Amazon的aws-java-sdk库中找到了一个类,该类正在创建一个有问题的对象/对象,这些对象正在启动IdleConnectionReaper线程,但从未关闭(这些com.amazonaws.services. ec2.Amazon EC2Client和com.amazonaws.services.cloud dwatch.Amazon CloudWatchClient)。然后我在这个类中添加了一个销毁()方法,该方法称为静态方法com.amazonaws.http.IdleConnectionReail.Shutdown()。当类被垃圾回收时调用销毁方法,并使用Spring application ationContext.xml进行配置。这样做的优点是它甚至可以用于非Web应用程序,并且它将线程关闭与您的Web上下文分离。正确的解决方案是启动IdleConnectionReaper线程的amazon aws-java-sdk库中的类应该关闭它,但它们没有-因此bug。有关我的解决方案,请参阅下面的参考和代码片段:

应用上下文. xml

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

YourBeanName.java-(创建冒犯亚马逊对象的类)

    public class YourBeanName {

        // omitted code

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

        // omitted code

    }

参考文献:

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

匿名用户

除了Stuart的回答之外(假设你使用的是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
        }
    }

}

当我使用bean实现com.amazonaws.services. s3.Amazon S3接口时,它对我很有效。