2013-08-05 24 views
10

Tôi có một ứng dụng web (sử dụng Spring 3.1) sử dụng @Scheduled Annotation để thực hiện một nhiệm vụ công việc định kỳ (chậm trễ theo lịch trình). Task worker mở một kết nối tới AWS DynamoDb và thực hiện một số DB đọc/cập nhật. Khi tôi dừng webapp (từ người quản lý Tomcat), tôi nhận được thông báo này trong catalina.out:Spring MVC WebApp: @schedule: java-sdk-http-connection-reaper: Không thể dừng

"SEVERE: Ứng dụng web [] dường như đã bắt đầu một chuỗi có tên [java-sdk-http-connection-reaper] nhưng đã thất bại trong việc ngăn chặn nó. Điều này rất có khả năng tạo ra rò rỉ bộ nhớ. "

Tôi có cảm giác rằng việc này có liên quan đến tác vụ đã lên lịch của tôi vẫn chạy ngay cả sau khi Tomcat dừng.

@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(); 
     } 
      } 

} 

phối-servlet.xml:

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

Am Tôi làm điều này một cách chính xác? a) Tôi không khởi động TaskScheduler một cách rõ ràng. Vì vậy, tôi giả định mùa xuân sẽ chăm sóc bắt đầu dịch vụ này. 'This.myDbConn.shutdown()' được gọi. Mặc dù vậy, tôi nhận được lỗi. Tôi đang sử dụng Spring MVC.

Trả lời

12

này có khả năng gây ra bởi các thư viện AWS mà bắt đầu một chủ đề trong nền gọi com.amazonaws.http.IdleConnectionReaper

Bạn có thể tắt nó bằng cách thực hiện một ServletContextListener để đóng nó trên shutdown

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 
    } 
} 
} 

và thêm này để web.xml

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

Tôi thích câu trả lời này mặc dù bên dưới có thể hoạt động. Vì tôi đang tiêu thụ AWS SDK từ bên trong một cái lọ khác mà tôi không biết. –

7

của bạn tôi có vấn đề này cũng nhưng tôi quyết định chọn một giải pháp thay thế cho @ David_Wartell của ở trên.

Tôi đã theo dõi các lớp học đã được tạo ra một đối tượng vi phạm/đối tượng từ thư viện AWS-java-sdk của Amazon đã được khởi động thread IdleConnectionReaper nhưng không bao giờ tắt (đây là những com.amazonaws.services.ec2. AmazonEC2Client và com.amazonaws.services.cloudwatch. AmazonCloudWatchClient). Sau đó, tôi đã thêm một phương thức destroy() vào lớp này, được gọi là phương thức static com.amazonaws.http.IdleConnectionReaper.shutdown(). Phương thức hủy được gọi khi lớp được thu thập rác và nó được cấu hình bằng cách sử dụng Spring applicationContext.xml. Những lợi thế của việc làm theo cách này là nó sẽ làm việc ngay cả đối với các ứng dụng không web và nó de-cặp vợ chồng các thread tắt máy từ bối cảnh web của bạn. Các giải pháp thích hợp là các lớp học từ amazon aws-java-sdk thư viện mà bắt đầu thread IdleConnectionReaper nên tắt nó xuống nhưng họ không - vì thế lỗi này. Xem tài liệu tham khảo và các đoạn mã dưới đây để biết giải pháp của tôi:

applicationContext.xml

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

YourBeanName.java - (lớp mà tạo ra các đối tượng vi phạm amazon) tài liệu tham khảo

public class YourBeanName { 

     // omitted code 

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

     // omitted code 

    } 

:

Amazon forum - Shutting down IdleConnectionReaper
Spring docs - Customizing the nature of a bean

+0

Đẹp nhất, câu trả lời hay. – bobmarksie

+0

Sử dụng Tomcat + Spring. Chính xác giải pháp tôi đang tìm kiếm để giải quyết nguyên nhân của thông báo lỗi này. – Joseph

2

Ngày đầu câu trả lời Stuart (và giả sử bạn đang sử dụng Spring), một thay thế nếu bạn không sử dụng tệp cấu hình 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 
     } 
    } 

} 

Nó đã làm việc cho tôi, khi tôi sử dụng một bean thực hiện com.amazonaws.services.s3.AmazonS3 giao diện.