Configure Eclipse to pre-bundle App Engine classes into a single JAR for faster warm-up

后端 未结 7 1514
青春惊慌失措
青春惊慌失措 2021-02-02 12:15

After some discussion with a colleague from another company that also uses App Engine, he told me that he managed to cut down his app warm up time from ~15 seconds to ~5 seconds

相关标签:
7条回答
  • 2021-02-02 12:24

    What we did in Eclipse was:

    • In Project Properties > Java Build Path (Source tab) change output folder from war/WEB-INF/classes to something else, e.g. bin (I believe Eclipse complained about this once)
    • In Project Properties > Builders add a new builder (I used type "program builder" and pointed it to the jar executable in my JDK, but as others mentioned an Ant builder would work too). Obviously you should configure this builder to take its input from wherever you decided to write your class files to, and output to something like war/WEB-INF/lib/myclasses.jar

    You can configure the jar builder to execute automatically as class files change (which in turn are usually automatically recompiled as your source files change).

    There are some downsides, though. For some reason the google eclipse plugin gets confused by your changing the output directory of the java compiler. This means you will have to manually point to the war directory when deploying, and I believe you'll have to manually copy some GAE jars into the war/WEB-INF/lib folder.

    0 讨论(0)
  • 2021-02-02 12:27

    I don't know how (or if) you can integrate it into eclipse, but it's fairly trivial to do with 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>
    

    I will add that I did not experience a 3X reduction in app startup time. I posted some experimental numbers in this thread:

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

    What I found is that instead of varying wildly from 20-45s, it made my app consistently load in 20s. It has not subsequently remained this consistent, but I still jar my classes as a standard part of deployment now.

    0 讨论(0)
  • 2021-02-02 12:28

    He argues that during instance warm up, since the instance need to load only a single bundled WAR file instead of thousands of separate classes, the warm up would be significantly faster. Any thoughts or opinions about this?

    I doubt it. WAR is just a ZIP file, which gets unpacked when it's deployed on the server. So there is an additional step, meaning the process can be equally fast (if unpacked when uploaded) or slower (if unpacked when instance is spun up).

    0 讨论(0)
  • 2021-02-02 12:30

    Note that as of version 1.7.4:

    You can now package all the WEB-INF/classes/* classes into jar files. This can be done via the new

    --enable_jar_classes option in the appcfg tools. By default, this option is not set.

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

    0 讨论(0)
  • 2021-02-02 12:36

    One way this can be achieved if by doing the deployment through Ant, as described in: https://developers.google.com/appengine/docs/java/tools/ant

    Next you can modify the ant build.xml file to call the ant command for building the jar file. Just before the actual deployment you can either delete or move the compiled artifacts away. The build jar-file should be placed in the WAR/WEB-INF/lib folder.

    Drawback of this solution is that you have to deploy through the build.xml, i.s.o. through the appengine eclipse plugin.

    0 讨论(0)
  • 2021-02-02 12:37

    As stated in an earlier answer, the App Engine SDK supports packaging WEB-INF/classes into a jar file, which will end up in WEB-INF/lib/_ah_webinf_classes-0000.jar. You can activate this

    1. using the appcfg tool with the option --enable_jar_classes.

    2. using the Google Plugin for Eclipse by configuring the properties of either your WAR or EAR project: Project properties > Google App Engine > Deployment > "Package WEB-INF/classes as a jar"

    For me, on App Engine 1.9.4, this resulted in only a minor improvement in instance spin-up (about 5-10 %, if any).


    Note that this will package all files in WEB-INF/classes (not only .class ones). Following the change, I got an error message during instantiation about not being able to read the logging.properties file anymore; probably because the new jar file hasn't been read at that time:

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

    As a workaround, I changed the path in appengine-web.xml to WEB-INF/logging.properties and configured the maven-war-plugin to copy the file to that location:

                    <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>
    
    0 讨论(0)
提交回复
热议问题