【问题标题】:Configure Eclipse to pre-bundle App Engine classes into a single JAR for faster warm-up配置 Eclipse 以将 App Engine 类预捆绑到单个 JAR 中以加快预热
【发布时间】:2012-03-12 22:00:23
【问题描述】:

在与另一家也使用 App Engine 的公司的同事讨论后,他告诉我,他通过以下步骤将应用预热时间从大约 15 秒缩短到了大约 5 秒:

  1. 配置 Eclipse 以将编译期间生成的类捆绑到单个 JAR 文件中。
  2. 配置 Eclipse 以在 App Engine 部署期间上传此单个 JAR 文件,而不是上传数百(或数千)个单独的 Java 类。

他认为,在实例预热期间,由于实例只需要加载单个捆绑的 JAR 文件而不是数千个单独的类,因此预热会明显更快。对此有何想法或意见?

我肯定想自己尝试一下,但是我没有足够的 Eclipse-mojo 知道如何配置这些步骤。有谁知道如何配置 Eclipse 或 Google Plugin for Eclipse 来执行上述步骤? (当然要让已部署的应用程序在 App Engine 中成功运行)

谢谢,

【问题讨论】:

  • 你为什么不给你的同事发一个链接到这个页面,这样他就可以准确地解释他做了什么? (:
  • 我确定他告诉过你jar,而不是war
  • 我听说这对于大型应用程序来说要快得多。我看到有人将他们的启动时间减少了几秒钟。似乎 Google 的文件系统相对较慢,加载单个压缩 JAR 比加载小文件或未压缩数据快得多。解压缩是一种相对便宜的操作。
  • Akamai 是领先的内容分发网络之一,通过将它们从索引 ZIP 文件中提取出来,比我单独存储它们更有效地提供大量静态文件。由于 WAR 和 JAR 都是特定类型的 ZIP 文件,我可以肯定地想象 Google 的 AppEngine 也会看到很多加速。我认为这与在分布式文件系统中定位文件的成本(高)与在找到文件后读取文件(低)有关,特别是当您可以将多个文件塞进一个块/磁盘读取/缓冲区时大小/内存页/随便什么。
  • eclipse 插件仅执行“appcfg.sh update /path/to/wardir”。当我尝试对战争文件“appcfg.sh update /path/to/filename.war”执行相同操作时,我收到消息“appcfg 只接受 webapp 目录,而不接受战争文件”。这是应用引擎“发布:1.6.3”

标签: java eclipse google-app-engine deployment jar


【解决方案1】:

earlier answer 中所述,App Engine SDK 支持将WEB-INF/classes 打包到一个 jar 文件中,该文件将在 WEB-INF/lib/_ah_webinf_classes-0000.jar 中结束。你可以激活这个

  1. 使用带有选项--enable_jar_classes 的appcfg 工具。

  2. 通过配置 WAR 或 EAR 项目的属性来使用 Google Plugin for Eclipse:项目属性 > Google App Engine > 部署 > “将 WEB-INF/类打包为 jar”

    李>

对我来说,在 App Engine 1.9.4 上,这仅导致实例启动方面的小幅改进(大约 5-10 %,如果有的话)。


请注意,这会将 所有 文件打包在 WEB-INF/classes 中(不仅是 .class 文件)。更改后,我在实例化过程中收到一条错误消息,提示无法再读取 logging.properties 文件;可能是因为当时还没有读取新的jar文件:

Unable to read the java.util.logging configuration file, WEB-INF/classes/logging.properties

作为一种解决方法,我将 appengine-web.xml 中的路径更改为 WEB-INF/logging.properties 并配置 maven-war-plugin 以将文件复制到该位置:

                <webResources>
                    <resource>
                        <directory>lib</directory>
                        <targetPath>WEB-INF/lib</targetPath>
                    </resource>
                    <resource>
                        <!-- Workaround: During GAE deployment, all files in WEB-INF/classes will be packaged into WEB-INF/lib/_ah_webinf_classes-0000.jar, 
                            which prevents the logging.properties referenced in appengine-web.xml from being read. -->
                        <directory>src/main/resources</directory>
                        <includes>
                            <include>logging.properties</include>
                        </includes>
                        <targetPath>WEB-INF</targetPath>
                    </resource>
                </webResources>

【讨论】:

  • 我在 Google App 引擎菜单中看不到任何部署菜单。所以右键 -> 属性 -> Google -> App Engine-> ??? .这个菜单到底在哪里。可能他们已经删除了这个,并且正在自动执行此操作?
【解决方案2】:

请注意,从 1.7.4 版开始:

您现在可以将所有 WEB-INF/classes/* 类打包到 jar 文件中。这可以通过新的

appcfg 工具中的--enable_jar_classes 选项。默认情况下,未设置此选项。

http://code.google.com/p/googleappengine/wiki/SdkForJavaReleaseNotes

【讨论】:

  • 太棒了!使用这个简单的选项,我可以减少加载时间。现在冷启动请求大约需要 8.5 秒,而之前总是超过 15 秒。注意:这个模块加载了大约 65 个类。看来磁盘 i/o 延迟确实是瓶颈。
  • Richard,你知道如何在 eclipse 的配置中集成这个选项,以便通过 eclipse 插件进行部署吗?我并不是说用正确的 appcfg 命令创建一个简单的脚本很无聊,而是单击快捷方式而不是打开控制台来启动脚本/输入命令更简单......非常感谢!跨度>
【解决方案3】:

一种方法可以通过 Ant 进行部署来实现,如:https://developers.google.com/appengine/docs/java/tools/ant

接下来可以修改ant build.xml文件,调用ant命令构建jar文件。在实际部署之前,您可以删除或移动已编译的工件。构建 jar 文件应放在 WAR/WEB-INF/lib 文件夹中。

此解决方案的缺点是您必须通过 build.xml 进行部署,即 i.s.o。通过 appengine eclipse 插件。

【讨论】:

    【解决方案4】:

    我们在 Eclipse 中所做的是:

    • 在项目属性 > Java 构建路径(源选项卡)中,将输出文件夹从 war/WEB-INF/classes 更改为其他内容,例如bin(我相信 Eclipse 曾经抱怨过这个)
    • 在“项目属性”>“构建器”中添加一个新构建器(我使用类型“程序构建器”并将其指向我的 JDK 中的 jar 可执行文件,但正如其他人提到的那样,Ant 构建器也可以工作)。显然,您应该配置此构建器以从您决定将类文件写入到的任何位置获取其输入,并输出到类似 war/WEB-INF/lib/myclasses.jar 的位置

    您可以将 jar 构建器配置为在类文件更改时自动执行(而这些文件通常会在您的源文件更改时自动重新编译)。

    不过,也有一些缺点。出于某种原因,google eclipse 插件会因为您更改 java 编译器的输出目录而感到困惑。这意味着您在部署时必须手动指向 war 目录,并且我相信您必须手动将一些 GAE jar 复制到 war/WEB-INF/lib 文件夹中。

    【讨论】:

      【解决方案5】:

      我不知道如何(或是否)可以将它集成到 eclipse 中,但使用 ant 是相当简单的:

      <import file="${appengine.sdk.dir}/config/user/ant-macros.xml" />
      
      <target name="deploy">
          <delete dir="${staging.dir}" />
          <mkdir dir="${staging.dir}" />
      
          <copy todir="${staging.dir}">
              <fileset dir="war">
                  <exclude name="WEB-INF/classes/**" />
                  <exclude name="WEB-INF/appengine-generated/**" />
              </fileset>
          </copy>
          <jar destfile="${staging.dir}/WEB-INF/lib/classes.jar" basedir="${classes.dir}" />
      
          <appcfg action="update" war="${staging.dir}" />
      </target>
      

      我要补充一点,我的应用启动时间并没有减少 3 倍。我在这个线程中发布了一些实验数字:

      https://groups.google.com/d/msg/google-appengine/dStBW4wIemY/K69f9ufDiN0J

      我发现,我的应用程序在 20 秒内始终加载,而不是在 20 到 45 秒之间变化很大。它后来并没有保持这种一致,但我现在仍然将我的类作为部署的标准部分。

      【讨论】:

        【解决方案6】:

        我认为最简单的方法是创建一个单独的项目,您可以在其中编写所有代码并存储任何其他依赖项。当您准备好部署时,Eclipse 导出到可运行 JAR 文件可以将所有依赖项和您的类重新打包到一个 JAR 文件中,然后您可以将其用作可部署的 Google App Engine 项目中的一个依赖项,该项目基本上包含任何WEB-INF 文件夹中的配置文件以及其他静态资源 + 一个大 JAR 文件。

        除了 eclipse 导出之外,您还可以将其设置为 Maven 或 Ant 构建,它也可以进行重新打包。

        【讨论】:

        • 赏金即将到期,但如果答案令人满意,我可以开始新的。假设项目 A 是我的应用程序的核心所在,项目 B 是具有配置文件和静态资源的可部署骨架项目。每次将项目 B 部署到 GAE 时,是否可以自动将项目 A 的 jar 导出到项目 B 的 WEB-INF/lib 文件夹?
        • 不容易。用于 Eclipse 的 google GAE 插件没有任何钩子或触发器可以让您在上传之前运行命令。但是,您可以编写一个 shell(或 ant 或 maven)脚本来构建项目 A 并将 jar 导出到项目 B,然后运行 ​​GAE 部署命令行脚本(“appengine-java-sdk/bin/appcfg.sh update战争”)。您可以通过 run->external tools->external tools configuration 将其作为启动配置添加到 Eclipse
        【解决方案7】:

        他认为在实例预热期间,因为实例只需要加载一个 单个捆绑的 WAR 文件而不是数千个单独的类,热身 会明显更快。对此有何想法或意见?

        我对此表示怀疑。 WAR 只是一个 ZIP 文件,它在部署到服务器时会被解压缩。所以有一个额外的步骤,这意味着该过程可以同样快(如果在上传时解包)或更慢(如果在实例启动时解包)。

        【讨论】:

        • 谢谢彼得。我倾向于认为当实例启动时拆包已经完成。与加载数千个单独文件相比,加载单个文件时的磁盘 I/O 速度可能更快。与 zip 解包相比,磁盘 I/O 会慢几个数量级,因此总体节省可能大于额外开销。一旦有人提出可行的配置,我将通过一些基准比较来编辑问题。
        • 很抱歉挑剔了,但这真的不是问题的答案。
        • @jeffrey_t_b,这是我自己的错,我就我的问题征求了意见,尽管我最初希望这些意见会在 cmets 中而不是答案中表达出来。 =/但是你是对的,我的问题不是试图在这个答案中解决的问题。 :)
        • OP 可能对将所有类文件打包为一个 jar,而不是将整个项目打包为一个 war 文件感到困惑。 GAE 部署工具不适用于war 文件,虽然它当然可以上传WEB-INF/lib 目录中的jar 文件。
        • 我想我们应该问问那些知道appengine的类加载器是如何实现的。那么,谷歌的家伙,有什么提示吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-12
        • 1970-01-01
        • 2012-04-27
        • 1970-01-01
        • 1970-01-01
        • 2011-01-09
        • 2013-07-13
        相关资源
        最近更新 更多