用于处理HardDeadlineExceededError的任务策略
我有很多正在碰到HardDeadlineExceededError的任务/ servlet,它将一切都挂在'仍在执行'的状态。
正在完成的工作可以轻松超过29秒的阈值。
我尝试捕获DeadlineExceededException和基地异常为了保存退出状态,但这些异常处理程序都没有被捕获...
有没有办法确定哪些任务在队列中或当前正在执行?
有没有其他的策略来处理这种情况?
我正在处理的情况记录在“请求计时器”标题下。
// task handler for retrieving information from external web services
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String taskRetryCountParam = req.getParameter( "X-AppEngine-TaskRetryCount" );
int taskRetryCount = (taskRetryCountParam==null) ? 0 : Integer.parseInt(taskRetryCountParam);
// look up the persistent 'task' and mark it as 'running'
logger.info( this.getClass().getName() + ".doPost( "+ taskId + " ) retryCount=" + taskRestryCount );
// Do lots of heavy lifting here
// like calling external web services using URL fetch service
// and saving the contents into our database.
// look up the persistent 'task' and mark it as 'completed'
} catch ( DeadlineExceededException deadline ) {
// got this deadline exception
// look up the persistent 'task' and mark it as 'errored - try again'
logger.warning( "DeadlineExceeded Exception while loading content " + deadline.getMessage() );
resp.setStatus( HttpServletResponse.SC_REQUEST_TIMEOUT );
}
} catch ( Exception unknown ) {
// got some unknown exception
// look up the persistent 'task' and mark it as 'errored - cancelled'
logger.severe( "General Exception while loading content exception:" + unknown.getMessage() );
resp.setStatus( HttpServletResponse.SC_OK );
}
}
当我遇到这种情况时,这里是日志文件条目......看起来我的数据库事务处理时间太长了。
W 05-30 12:42PM 09.535
Error for /loadstatus
com.google.apphosting.runtime.HardDeadlineExceededError: This request (083793d1091c2ca3) started at 2010/05/30 19:41:39.814 UTC and was still executing at 2010/05/30 19:42:09.529 UTC.
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:443)
at java.util.concurrent.TimeUnit.timedWait(Unknown Source)
at com.google.apphosting.runtime.AsyncFuture.get(AsyncFuture.java:60)
at com.google.apphosting.runtime.ApiProxyImpl$AsyncApiFuture.get(ApiProxyImpl.java:326)
at com.google.apphosting.runtime.ApiProxyImpl$AsyncApiFuture.get(ApiProxyImpl.java:217)
at com.google.apphosting.runtime.ApiProxyImpl.doSyncCall(ApiProxyImpl.java:131)
at com.google.apphosting.runtime.ApiProxyImpl.access$000(ApiProxyImpl.java:43)
at com.google.apphosting.runtime.ApiProxyImpl$1.run(ApiProxyImpl.java:104)
at com.google.apphosting.runtime.ApiProxyImpl$1.run(ApiProxyImpl.java:102)
at java.security.AccessController.doPrivileged(Native Method)
at com.google.apphosting.runtime.ApiProxyImpl.makeSyncCall(ApiProxyImpl.java:102)
at com.google.apphosting.runtime.ApiProxyImpl.makeSyncCall(ApiProxyImpl.java:43)
at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:98)
at com.google.appengine.api.datastore.DatastoreApiHelper.makeSyncCall(DatastoreApiHelper.java:58)
at com.google.appengine.api.datastore.TransactionImpl.makeSyncCall(TransactionImpl.java:42)
at com.google.appengine.api.datastore.TransactionImpl.makeSyncCall(TransactionImpl.java:56)
at com.google.appengine.api.datastore.TransactionImpl.commit(TransactionImpl.java:66)
at org.datanucleus.store.appengine.DatastoreTransaction.commit(DatastoreTransaction.java:61)
at org.datanucleus.store.appengine.DatastoreXAResource.commit(DatastoreXAResource.java:88)
at org.datanucleus.transaction.Transaction.commit(Transaction.java:149)
at org.datanucleus.transaction.TransactionManager.commit(TransactionManager.java:95)
at org.datanucleus.TransactionImpl.internalCommit(TransactionImpl.java:390)
at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:258)
at org.datanucleus.jdo.JDOTransaction.commit(JDOTransaction.java:83)
at org.datanucleus.store.appengine.jdo.DatastoreJDOTransaction.commit(DatastoreJDOTransaction.java:56)
<snip>
C 05-30 12:42PM 09.629
Uncaught exception from servlet
com.google.apphosting.runtime.HardDeadlineExceededError: This request (083793d1091c2ca3) started at 2010/05/30 19:41:39.814 UTC and was still executing at 2010/05/30 19:42:09.529 UTC.
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:443)
at java.util.concurrent.TimeUnit.timedWait(Unknown Source)
at com.google.apphosting.runtime.AsyncFuture.get(AsyncFuture.java:60)
at com.google.apphosting.runtime.ApiProxyImpl$AsyncApiFuture.get(ApiProxyImpl.java:326)
at com.google.apphosting.runtime.ApiProxyImpl$AsyncApiFuture.get(ApiProxyImpl.java:217)
at com.google.apphosting.runtime.ApiProxyImpl.doSyncCall(ApiProxyImpl.java:131)
at com.google.apphosting.runtime.ApiProxyImpl.access$000(ApiProxyImpl.java:43)
at com.google.apphosting.runtime.ApiProxyImpl$1.run(ApiProxyImpl.java:104)
at com.google.apphosting.runtime.ApiProxyImpl$1.run(ApiProxyImpl.java:102)
at java.security.AccessController.doPrivileged(Native Method)
at com.google.apphosting.runtime.ApiProxyImpl.makeSyncCall(ApiProxyImpl.java:102)
at com.google.apphosting.runtime.ApiProxyImpl.makeSyncCall(ApiProxyImpl.java:43)
at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:98)
at com.google.appengine.api.datastore.DatastoreApiHelper.makeSyncCall(DatastoreApiHelper.java:58)
at com.google.appengine.api.datastore.TransactionImpl.makeSyncCall(TransactionImpl.java:42)
at com.google.appengine.api.datastore.TransactionImpl.makeSyncCall(TransactionImpl.java:56)
at com.google.appengine.api.datastore.TransactionImpl.commit(TransactionImpl.java:66)
at org.datanucleus.store.appengine.DatastoreTransaction.commit(DatastoreTransaction.java:61)
at org.datanucleus.store.appengine.DatastoreXAResource.commit(DatastoreXAResource.java:88)
at org.datanucleus.transaction.Transaction.commit(Transaction.java:149)
at org.datanucleus.transaction.TransactionManager.commit(TransactionManager.java:95)
at org.datanucleus.TransactionImpl.internalCommit(TransactionImpl.java:390)
at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:258)
at org.datanucleus.jdo.JDOTransaction.commit(JDOTransaction.java:83)
at org.datanucleus.store.appengine.jdo.DatastoreJDOTransaction.commit(DatastoreJDOTransaction.java:56)
<snip>
W 05-30 12:42PM 09.644
A serious problem was encountered with the process that handled this request, causing it to exit. This is likely to cause a new process to be used for the next request to your application. If you see this message frequently, you may be throwing exceptions during the initialization of your application. (Error code 104)
http://groups.google.com/group/google-appengine-java/msg/e3fd2b621bb96013
如果它发生在你自己的代码中,HDEE可以在没有DEE的情况下抛出。
通常最耗时的是等待API调用
返回,所以这里的超时将导致API调用停止
DEE。 所以如果你不经常打电话给API,你可以直接打HDEE。
我也有长时间运行的任务迭代通过数据处理
并存储结果。 我使用一个停止返回结果的迭代器
20秒后保存最后处理的对象,然后踢
关闭一项新任务以继续处理。
我原来的解决方案抓住了DEE,然后清理干净,但是这个
停止可靠工作。