1
votes

I have a Java Spring application running on standard instances of Google App Engine. We recently switched from auto-scaling to manual scaling in order to accommodate for longer cronjobs.

We've been running into issues when trying to run the server locally ./gradlew startServer. This is due to our manual scaling configuration inside *appengine-web.xml":

<instance-class>B8</instance-class>
<manual-scaling>
    <instances>1</instances>
</manual-scaling>

Even though we try to set the instances number to 1. Gradle attempts to start the application more than 1 time, causing errors. The issues is only solved when I switch the settings back to auto-scaling:

<instance-class>@server.instance.class@</instance-class>
<automatic-scaling>
    <min-idle-instances>@min.idle.instances@</min-idle-instances>
    <max-idle-instances>@max.idle.instances@</max-idle-instances>
    <min-pending-latency>@min.pending.latency@</min-pending-latency>
    <max-pending-latency>@max.pending.latency@</max-pending-latency>
</automatic-scaling>

One solution for this is to swap manual scaling to autoscaling based on the env and add that to ./gradlew startServer with a script.

Is there a way from a configuration standpoint to this without going the script route

1
There is a way to determine in which environment your app is running, and a solution is offered in the documentation, "Using the Local Development Server", in the "Detecting application runtime environment" sub-chapter. The solution is based on checking the SERVER_SOFTWARE environment variable: if os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine/'): # Production else: # Local development server - George
@George The problem is that your suggestion only works dynamically, at runtime, while the scaling configuration is static, it can only be changed by re-deploying with a modified configuration file. - Dan Cornilescu
Thanks for replying guys. I actually came up with a solution that deals with changing the deployment dynamically based on the environment. Check down below - mauricioSanchez

1 Answers

0
votes

This is not the most elegant solution but gives the advantage of not be changing the .xml file every time I want to start my server locally. The only down side is that it forces me to write my xml like this:

<application>@sublink.project.id@</application><!-- unused for Cloud SDK based tooling -->
<service>sublink</service>
<runtime>java8</runtime>
<threadsafe>true</threadsafe>
<instance-class>@server.instance.class@</instance-class>

<!--<automatic-scaling>-->
    <!--<min-idle-instances>@min.idle.instances@</min-idle-instances>-->
    <!--<max-idle-instances>@max.idle.instances@</max-idle-instances>-->
    <!--<min-pending-latency>@min.pending.latency@</min-pending-latency>-->
    <!--<max-pending-latency>@max.pending.latency@</max-pending-latency>-->
<!--</automatic-scaling>-->

<manual-scaling>
    <instances>@scaling.manual.instances@</instances>
</manual-scaling>

<env-variables>
    <env-var name="SPRING_PROFILES_ACTIVE" value="@active.deploy.env@"/>
</env-variables>

Then in my build.gradle I do this:

   from('src/main/webapp/WEB-INF')
include '*.xml'
into("build/exploded/WEB-INF")

filter(ReplaceTokens, tokens: props)

if (deployEnv == "local") {
    // Use a closure to remove lines
    filter { String line ->
        line.trim().startsWith('<instance-class>') ? null : line
    }
    filter { String line ->
        line.trim().startsWith('<manual-scaling>') ? null : line
    }
    filter { String line ->
        line.trim().startsWith('<instances>') ? null : line
    }
    filter { String line ->
        line.trim().startsWith('</manual-scaling>') ? null : line
    }
}