反向代理对 GWT 应用程序有啥影响?

Posted

技术标签:

【中文标题】反向代理对 GWT 应用程序有啥影响?【英文标题】:What is the effect of reverse proxy on a GWT application?反向代理对 GWT 应用程序有什么影响? 【发布时间】:2011-09-30 13:20:23 【问题描述】:

我正在 Glassfish 3.0.1 上部署 GWT 2.4 应用程序。我可以通过http://host:PORT/appContext/ 轻松访问我的应用程序但是,当我使用 Apache 对应用程序进行反向代理时,我得到了一个异常,摘录如下(来自 Glassfish 日志):

分派传入 RPC 调用时出现异常 com.google.gwt.user.client.rpc.SerializationException: 类型 'com.ozdokmeci.basicgwtproject.shared.GroupData' 不能分配给 'com.google.gwt.user.client.rpc.IsSerializable' 并且没有自定义字段序列化程序。 出于安全考虑,此类型不会被序列化。

实施IsSerializable 解决了Chi 在related question 中建议的问题。 相关问题中还有其他解决方法。

我的问题是这个问题的根本原因是什么,两个看似无关的解决方案(实现标记接口和扩展 servlet 类)如何解决这个问题? related question中提到的两种方法也有什么缺点吗?

注意:如果直接访问应用程序,则不会发生异常。

注意2:与异常相关的类已经实现了接口Serializable,就GWT而言应该等价于IsSerializable。

【问题讨论】:

你确定只有在通过 Apache 访问时才会发生异常 - 你需要检查这个假设。我认为即使您直接访问它也会发生错误。该异常与反向代理无关。 只有当它在 Apache 后面被代理时才会发生异常(我并不是说 Apache 导致了它)。当我直接访问该应用程序时,不会发生此类异常。这不是一个假设,我在发布问题之前不止一次检查了日志。我知道异常与反向代理没有直接关系,这就是我问这个问题的原因:) 我认为还有其他问题-当您说非apache是​​托管/ devmode或访问已编译的js版本时。您能否检查两者是否运行相同版本的代码(缓存、不正确的构建等被排除)。在主页上进行一些可见的更改,并检查更改是否通过 apache 代理出现。 应用部署到远程服务器,所以它运行的是编译版本。我将部署的应用程序放在同一服务器上的反向代理后面。所以在代理后面运行的和直接访问的是一样的。顺便说一下,代理不是缓存代理,它只是为了让最终用户看起来更漂亮的 URL。 这里有同样的问题。 【参考方案1】:

我遇到了完全相同的问题,当我跟踪源代码时,我发现反向代理时找不到 GWT 序列化文件的目录(我认为是因为该目录是相对路径)。这就是为什么即使您已经实现了 IsSerializable 也会出现序列化异常的原因。

我最终的解决方案是为我的 RPC 迁移到 restful JSON。使用 JSON 将允许您进行反向代理,因为它不需要查找这些序列化文件。

编辑

如果您仍然想使用 GWT RPC,我知道它是如何实现的(尽管我自己还没有实现)。

首先,查看有关这些 rpc 文件的 GWT 帮助: https://developers.google.com/web-toolkit/doc/2.4/DevGuideCompilingAndDebugging#key_application_files

你会注意到它说:

您的 RPC RemoteServiceServlet 必须可以通过 ServletContext.getResource() 调用访问序列化策略文件

因此您需要覆盖 RemoteServiceServlet 并重新指向 rpc(序列化策略)文件的位置。

这里有一个建议,取自这个网站:http://code.google.com/p/google-web-toolkit/issues/detail?id=4817

    public class MyRemoteServiceServlet extends RemoteServiceServlet
    

    ...

    @Override
    protected SerializationPolicy doGetSerializationPolicy(
            HttpServletRequest request, String moduleBaseURL, String strongName) 
            //get the base url from the header instead of the body this way 
            //apache reverse proxy with rewrite on the header can work
            String moduleBaseURLHdr = request.getHeader("X-GWT-Module-Base");

            if(moduleBaseURLHdr != null)
                    moduleBaseURL = moduleBaseURLHdr;
            

            return super.doGetSerializationPolicy(request, moduleBaseURL, strongName);
    

    ...

在 apache 配置中添加:

    ProxyPass /app/ ajp://localhost:8009/App-0.0.1-SNAPSHOT/

    <Location /app/>

    RequestHeader edit X-GWT-Module-Base ^(.*)/app/(.*)$ $1/App-0.0.1-SNAPSHOT/$2

    </Location>

希望我上面的建议至少为某人指明了正确的方向。 请让我们知道是否有人实现了此功能并且有效。

【讨论】:

您的解决方案很好。如果您能详细说明根本原因(相对目录?)或概述 GWT 序列化的结构(如果您知道的话),这对其他人将是有益的:)谢谢 @Kaan - 好的,我已经用更多细节更新了我的解决方案......我自己还没有实现这个,所以请尝试一下,让大家知道它是否有效! @jsop - 感谢您的更新、不错的建议和指针。我不能很快尝试这个。在此之前接受作为答案。

以上是关于反向代理对 GWT 应用程序有啥影响?的主要内容,如果未能解决你的问题,请参考以下文章

反向代理和网关有啥区别? [复制]

nginx服务器有啥作用以及啥是反向代理

将 nginx 配置为 node.js 的反向代理有啥问题?

API(网关)提供的反向代理和Service Fabric有啥区别?

反向代理背后的 SOP 问题

Ingress 和反向代理有啥区别?