GWT SerializationException,但仅在涉及marathon-LB时

时间:2018-02-01 19:34:26

标签: gwt mesos marathon mesosphere jsse

我有一个GWT网络应用正常运行 - 除非我把它放在Marathon-LB负载均衡器后面并使用HTTPS

失败发生在POST周围。

  • 当webapp不在Marathon-LB之后时,POST将获得200 OK。
  • 但是当它落后于Marathon-LB时,会出现GWT SerializationException的内部服务器错误,POST会出现500错误。

对于失败的情况,tomcat的服务器日志中的堆栈跟踪就是这个。请注意,该主题是https-jsse-nio-8080-exec-6

01-Feb-2018 18:43:39.863 SEVERE [https-jsse-nio-8080-exec-6] org.apache.catalina.core.ApplicationContext.log Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'com.company.SomeGwtSerializableClass' was not assignable to 'com.google.gwt.user.client.rpc.IsSerializ
able' and did not have a custom field serializer.For security purposes, this type will not be serialized.: instance = com.company.SomeGwtSerializableClass@6ce9a6c9
        at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:667)
        at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:130)
        at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:153)
        at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:587)

我怀疑问题在于运行Marathon-LB的docker容器与运行web Tomcat的docker容器之间的信任证书。

有关如何调试此问题的任何建议?例如,我如何确定Marathon-LB容器是否信任webapp容器?

谢谢!

2 个答案:

答案 0 :(得分:1)

两种可能的方式(至少)负载均衡器可以破坏应该起作用的GWT-RPC:

  • 提供错误的内容:这可能会以某种方式发生,例如,如果负载均衡器缓存了某些内容,或者其后面的某个服务器正在提供过期文件,那么该客户端就会连接到最多日期服务器。
  • 管理来电:负载均衡器有多种方法可能会出错或者提供帮助"并打破一些东西 - 删除标题,将请求中的moduleBaseUrl重写为其他内容等。

无论哪种方式,大多数情况都涉及无法找到正确的序列化策略文件(编译输出中的.gwt.rpc文件),而这又是由com.google.gwt.user.server.rpc.RemoteServiceServlet#loadSerializationPolicy方法中的某些错误引起的。据我所知,所有这些错误都应该导致记录一些错误,尽管它可能是一个不同的文件。也许检查其他服务器日志文件以查看是否出现问题,或者在负载均衡器后面附加并调试该方法,并确保在您看到错误时它返回实际策略。另请注意,这些策略文件已缓存,因此错误只会发生一次,直到您重新启动服务器Web应用程序。

答案 1 :(得分:0)

我认为你的问题是特定于RPC的。

作为某种验证/保护的一部分,RPC尝试服务器端,通过getServletContext()加载这些序列化策略.getResourceAsStream

/*
 * Check that the module path must be in the same web app as the servlet
 * itself. If you need to implement a scheme different than this, override
 * this method.
 */
if (modulePath == null || !modulePath.startsWith(contextPath)) {
  String message = "ERROR: The module path requested, "
      + modulePath
      + ", is not in the same web application as this servlet, "
      + contextPath
      + ".  Your module may not be properly configured or your client and server code maybe out of date.";
  servlet.log(message);
} else {
  // Strip off the context path from the module base URL. It should be a
  // strict prefix.
  String contextRelativePath = modulePath.substring(contextPath.length());

  String serializationPolicyFilePath = SerializationPolicyLoader.getSerializationPolicyFileName(contextRelativePath
      + strongName);

  // Open the RPC resource file and read its contents.
  InputStream is = servlet.getServletContext().getResourceAsStream(
      serializationPolicyFilePath);

你可以在这里看到这个:

https://github.com/stephenh/gwt/blob/master/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java

上述问题是serializationPolicyFilePath是基于客户端路径构建的。因此,如果您的客户端路径和服务器路径不同,您将遇到麻烦。

我在这方面遇到了很多麻烦,我最终通过RemoteServiceServlet覆盖了内容,以便能够从其他位置加载策略文件。

Edit1:添加了缺少的额外代码行;也忘了提及问题可以在getResourcesAsStream调用中,也可以在!modulePath.startsWith(contextPath)比较中。