随机时间段内使用Java Google App Engine Standard的memcache中的服务错误

怀抱观古今,寝食展戏谑。这篇文章主要讲述随机时间段内使用Java Google App Engine Standard的memcache中的服务错误相关的知识,希望能为你提供帮助。
在过去的一个月里,我们的java Google App Engine标准Web应用程序在看似随机的时间开始出现奇怪的错误(请参阅下面的堆栈跟踪)。大约在这个时候我们做了以下改动:

  1. 从Java7运行时切换到Java8 / Jetty9运行时(这使我们能够更灵活地链接到第三方支付库)。
  2. 切换到使用Google Cloud SDK部署,而不是单独的Google App Engine SDK。
【随机时间段内使用Java Google App Engine Standard的memcache中的服务错误】昨天我们遇到了3个有错误的时期。其中一个发生在2月28日从0530PST到大约0600PST。突然所有从数据库加载的尝试都开始失败:
com.google.appengine.api.memcache.LogAndContinueErrorHandler handleServiceError: Service error in memcache (LogAndContinueErrorHandler.java:50) com.google.appengine.api.memcache.MemcacheServiceException: Memcache getIdentifiables: exception getting multiple keys at com.google.appengine.api.memcache.MemcacheServiceApiHelper$RpcResponseHandler.handleApiProxyException(MemcacheServiceApiHelper.java:77) at com.google.appengine.api.memcache.MemcacheServiceApiHelper$1.absorbParentException(MemcacheServiceApiHelper.java:122) at com.google.appengine.api.utils.FutureWrapper.handleParentException(FutureWrapper.java:56) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:95) at com.google.appengine.api.memcache.MemcacheServiceImpl.quietGet(MemcacheServiceImpl.java:28) at com.google.appengine.api.memcache.MemcacheServiceImpl.getIdentifiables(MemcacheServiceImpl.java:61) at com.googlecode.objectify.cache.EntityMemcache.getAll(EntityMemcache.java:215) at com.googlecode.objectify.cache.CachingAsyncDatastoreService.get(CachingAsyncDatastoreService.java:253) at com.googlecode.objectify.impl.engine.LoadEngine$Round.fetchPending(LoadEngine.java:172) at com.googlecode.objectify.impl.engine.LoadEngine$Round.execute(LoadEngine.java:118) at com.googlecode.objectify.impl.engine.LoadEngine.execute(LoadEngine.java:258) at com.googlecode.objectify.impl.cmd.LoaderImpl.refs(LoaderImpl.java:110) at com.googlecode.objectify.impl.cmd.LoaderImpl.refs(LoaderImpl.java:98) at com.googlecode.objectify.impl.cmd.LoaderImpl.ref(LoaderImpl.java:88) at com.googlecode.objectify.impl.cmd.LoadTypeImpl.refOf(LoadTypeImpl.java:92) at com.googlecode.objectify.impl.cmd.LoadTypeImpl.id(LoadTypeImpl.java:86) at com.codeavengers.LoginServlet.doPost(LoginServlet.java:62) at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:848) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1772) at com.codeavengers.UrlFilter.doFilter(UrlFilter.java:143) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759) at com.codeavengers.payments.PermissionsFilter.doFilter(PermissionsFilter.java:114) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759) at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:59) at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:49) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759) at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759) at com.google.apphosting.runtime.jetty9.SaveSessionFilter.doFilter(SaveSessionFilter.java:43) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759) at com.google.apphosting.utils.servlet.JdbcmysqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:60) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:48) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:582) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at com.google.apphosting.runtime.jetty9.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:297) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) at org.eclipse.jetty.server.Server.handle(Server.java:534) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320) at com.google.apphosting.runtime.jetty9.RpcConnection.handle(RpcConnection.java:202) at com.google.apphosting.runtime.jetty9.RpcConnector.serviceRequest(RpcConnector.java:81) at com.google.apphosting.runtime.jetty9.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:108) at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchServletRequest(JavaRuntime.java:680) at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchRequest(JavaRuntime.java:642) at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:612) at com.google.apphosting.runtime.JavaRuntime$NullSandboxRequestRunnable.run(JavaRuntime.java:806) at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:274) at java.lang.Thread.run(Thread.java:745) Caused by: com.google.apphosting.api.ApiProxy$UnknownException: An error occurred for the API request memcache.Get(). at com.google.apphosting.utils.runtime.ApiProxyUtils.statusException(ApiProxyUtils.java:207) at com.google.apphosting.utils.runtime.ApiProxyUtils.getRpcError(ApiProxyUtils.java:128) at com.google.apphosting.runtime.ApiProxyImpl$AsyncApiFuture.setRpcError(ApiProxyImpl.java:601) at com.google.apphosting.runtime.ApiProxyImpl$AsyncApiFuture.failure(ApiProxyImpl.java:589) at com.google.apphosting.runtime.http.HttpApiHostClient.communicationFailure(HttpApiHostClient.java:170) at com.google.apphosting.runtime.http.JettyHttpApiHostClient$Listener.onComplete(JettyHttpApiHostClient.java:141) at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:193) at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:185) at org.eclipse.jetty.client.HttpExchange.notifyFailureComplete(HttpExchange.java:269) at org.eclipse.jetty.client.HttpExchange.abort(HttpExchange.java:240) at org.eclipse.jetty.client.HttpConversation.abort(HttpConversation.java:141) at org.eclipse.jetty.client.HttpRequest.abort(HttpRequest.java:735) at org.eclipse.jetty.client.HttpDestination.abort(HttpDestination.java:267) at org.eclipse.jetty.client.PoolingHttpDestination.failed(PoolingHttpDestination.java:90) at org.eclipse.jetty.client.DuplexConnectionPool$1.failed(DuplexConnectionPool.java:159) at org.eclipse.jetty.util.Promise$Wrapper.failed(Promise.java:84) at org.eclipse.jetty.client.HttpClient$1$1.failed(HttpClient.java:587) at org.eclipse.jetty.client.AbstractHttpClientTransport.connectFailed(AbstractHttpClientTransport.java:152) at org.eclipse.jetty.client.AbstractHttpClientTransport.connect(AbstractHttpClientTransport.java:141) at org.eclipse.jetty.client.HttpClient$1.connect(HttpClient.java:592) at org.eclipse.jetty.client.HttpClient$1.succeeded(HttpClient.java:569) at org.eclipse.jetty.client.HttpClient$1.succeeded(HttpClient.java:562) at org.eclipse.jetty.util.SocketAddressResolver$Async.lambda$resolve$1(SocketAddressResolver.java:181) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) ... 1 more

从我迄今为止所做的调查来看,我认为它可能与我们使用的Objectify版本有关。我们在objectify-4.0b1.jar。我尝试升级到objectify 4.1,该版本的网站正在与4.0版本无法正常工作。那么也许这与它有关呢?
我犹豫是否将使用objectify 4.1的版本切换到生产,因为一旦你这样做,我们就无法切换回旧的稳定版本的网站。所以我想确保升级实际上能解决我们的问题。
更新1
在应用程序正常运行22小时后,应用程序再次启动失败并出现更多Memcache错误。我们尝试清除Memcache,但没有做任何事情。 24小时后,该版本的应用程序仍无法正常工作。
我们通过使用完全相同的代码重新部署新版本来克服这个问题,并且它再次开始正常工作。 24小时后,该版本仍然正常运行。
更新2
我们切换到使用Objectify 4.1.3的版本,到目前为止24小时后该版本正常运行。
有关相关问题的额外信息
自从切换到Java 8 + Cloud SDK以来,过去一个月我们遇到了其他奇怪的问题。
例如,在随机时间(主要是在星期五下午太平洋标准时间),该站点将停止在某些计算机上正常工作。然后在30分钟左右后它会再次起作用。然后一周后发生了同样的问题。
在仔细阅读了Google Cloud SDK的文档之后,它表示他们更改了用于delete-jsps的Cloud SDK的默认登台选项是正确的,而使用App Engine SDK则是错误的。我们的服务器正在从几个JSP文件中读取数据......所以这个改变打破了我们的网站。
问题是,它在本地服务器上运行良好,在实时服务器上它也可以在99%的时间内正常工作。就好像他们是AB测试随机时间在某些百分比的实例上更改默认参数的效果。这似乎很疯狂,因为他们可以检查我们的数据日志,看到我们的网站正在加载并从jsp文件中读取值。
一旦我们从JSP文件中删除了这些数据并将其放在单独的配置文件中,那么问题就消失了。
似乎Google再次在随机时间尝试对Memcache进行一些更改,这在使用Objectify 4.0b2时完全破坏了我们的网站?这可行吗?
答案IIRC在Objectify在4.0b2和4.1之间使用memcache的方式有一些变化。虽然看起来不太可能,但使用模式可能会在memcache中产生某种潜在问题。
4.0b2真的很老 - 超过4年 - 并且从那以后已经修复了大量问题。迁移到当前版本是明智的。

    推荐阅读