如何退出Java SDK中的SQS读取
我们有一个JavaWeb服务,它轮询AWS SQS队列中的消息。它使用20秒的最大等待时间。在Tomcat中更新服务时,Tomcat会尝试关闭现有服务,然后启动更新版本。发生这种情况时,如果正在读取队列,则线程被卡住,Tomcat无法停止它,从而导致内存泄漏。从我的实验来看,只有Tomcat在等待队列时试图停止服务时,才会发生内存泄漏 如何在关闭过程中停止Java中的SQS队列 这里有更多的细节如何退出Java SDK中的SQS读取,java,multithreading,spring,amazon-web-services,amazon-sqs,Java,Multithreading,Spring,Amazon Web Services,Amazon Sqs,我们有一个JavaWeb服务,它轮询AWS SQS队列中的消息。它使用20秒的最大等待时间。在Tomcat中更新服务时,Tomcat会尝试关闭现有服务,然后启动更新版本。发生这种情况时,如果正在读取队列,则线程被卡住,Tomcat无法停止它,从而导致内存泄漏。从我的实验来看,只有Tomcat在等待队列时试图停止服务时,才会发生内存泄漏 如何在关闭过程中停止Java中的SQS队列 这里有更多的细节 Jan 03, 2014 7:52:52 PM org.apache.catalina.loader
Jan 03, 2014 7:52:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application appears to have started a thread named [pollSQSQueue-1] but has failed to stop it. This is very likely to create a memory leak.
Jan 03, 2014 7:52:52 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application created a ThreadLocal with key of type [com.amazonaws.auth.AWS4Signer$2] (value [com.amazonaws.auth.AWS4Signer$2@71f69c90]) and a value of type [java.text.SimpleDateFormat] (value [java.text.SimpleDateFormat@ef87e460]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
Jan 03, 2014 7:52:52 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application created a ThreadLocal with key of type [com.amazonaws.auth.AWS4Signer$1] (value [com.amazonaws.auth.AWS4Signer$1@75a0ec63]) and a value of type [java.text.SimpleDateFormat] (value [java.text.SimpleDateFormat@6f64295a]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
该服务使用Spring并使用Spring调度程序来启动轮询过程
<task:scheduler id="pollSQSQueue" pool-size="1"/>
接下来我尝试使用AmazonSQSAsync和异步检索。然后,我获得了未来
,并在Spring关机期间尝试调用取消
。这也不是很得体
另外,我知道需要关闭IdleConnectionReaper,并在Spring关闭时执行此操作,因此我认为这与此无关。您可以为轮询工作创建单独的线程。大致如下:
class MyService extends/implements ... {
private SQSPollingThread pollingThread;
//this is just my guess of what the "service start" method looks like
@Override
public void onApplicationEvent(ContextStartedEvent contextStartedEvent)
{
pollingThread = new SQSPollingThread();
pollingThread.start();
}
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent)
{
pollingThread.stop();
}
}
class SQSPollingThread implements Runnable() {
private volatile boolean stopped = false;
public void stop() {
stopped = true;
}
@Override
public void run() {
while (!stopped) {
message = pollSqsBlockingFor20seconds();
process(message);
}
}
}
通过这种设置,当TomCat“告诉”您的服务停止时,您的服务将设置停止标志并立即返回。可能仍有一个轮询请求挂起,最终将在接下来的20秒内完成并得到处理。处理完最后一个事件后,内部SQSPollingThread也将结束。我遇到了同样的问题。你找到解决方案了吗?没有,我没有找到解决方案。你用什么来阅读SQS?我是说,线程是你的一个类?您可以发布代码吗?更好的是,您应该能够
中断执行轮询的线程,这样您就不必等待20秒的轮询。只要确保你不接受/忽略打断。
class MyService extends/implements ... {
private SQSPollingThread pollingThread;
//this is just my guess of what the "service start" method looks like
@Override
public void onApplicationEvent(ContextStartedEvent contextStartedEvent)
{
pollingThread = new SQSPollingThread();
pollingThread.start();
}
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent)
{
pollingThread.stop();
}
}
class SQSPollingThread implements Runnable() {
private volatile boolean stopped = false;
public void stop() {
stopped = true;
}
@Override
public void run() {
while (!stopped) {
message = pollSqsBlockingFor20seconds();
process(message);
}
}
}