Pivotal Knowledge Base

Follow

Pushing large Java based applications to CloudFoundry

Symptoms

When pushing large Java based applications (this includes anything running on the JVM like Grails & Java Play), it is possible for the application take minutes to start.  

If you have a large or slow starting application, you may experience an issue similar to the following when you run cf push.

Checking status of app '<app-name>'................
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
0 of 1 instances running (1 down)
0 of 1 instances running (1 starting)
0 of 1 instances running (1 starting)
Push unsuccessful.

Cause

When running locally this does not cause an issue as your local application container will simply wait as long as it takes for your application to start.  However, when pushing to CloudFoundry, this is not the case and the system restricts the time that the application has to start and begin listening for requests.

Resolution

There are three workarounds for this issue.

  1. Adjust your application to start faster.
  2. Set the -t option for cf push.  This will allow you to increase the amount of time that CF will wait for your application to start.  You can increase this value up to 180 seconds on PWS.
  3. Fork the Java Build Pack and adjust the packaged Tomcat configuration so that it begins listening for connections prior to deploying your application.

    The default configuration of the Tomcat container that is setup by the Java build pack instructs the container to first deploy your application and then begin listening for incoming requests.  If we reverse this process, the container will begin listening for connections immediately and CloudFoundry will think that the application has started.  At this point, your application will have as much time as it needs to finish starting.

    If you would like to make the change, the first thing you'll need to do is fork and clone the Java Build pack.  After that, you'll need to remove the bindOnInit=false attribute from the <Connector /> tag in server.xml.  

    Ex:
  4. <Connector port='${http.port}' />

    Then commit your changes and push them back to your fork of the build pack.  Finally, push your application to CloudFoundry and specify the -b option to cf push to indicate that CloudFoundry should use your custom version of the Java Build pack.  For instructions on using a custom build pack, see this link.

Impact / Risks

Resolution #3 comes with the risk that an application's users may see failed requests during this period of time between the container starting and the application starting.  Because CloudFoundry thinks the instance has started, it will begin routing user requests to the application immediately.  Until the application has actually finished starting requests that come to the application are going to fail.

Comments

Powered by Zendesk