1

We are developing a small e-commerce project for which we are using GAE as our web service backend but it's draining our financial resources. We studied our current infrastructure and how it was billed. That shows us that it's because of the instances we are using.

We have 7 services running which is using 12 instances as a whole.

Want to understand how to stop Google App Engine instances when not being used as it's the key contributor to our billing.

Services

UpdateFeed.yaml

application: ...
module: updatecategoryfeed
version: uno
runtime: python27
api_version: 1
instance_class: F1
threadsafe: true

automatic_scaling:
  min_idle_instances: 6
  max_idle_instances: automatic  # default value
  min_pending_latency: 30ms  # default value
  max_pending_latency: automatic
  max_concurrent_requests: 50

handlers:
- url: /.*
  script: FeedModule.FeedBuilder.update_category_feed



libraries:

- name: endpoints
  version: 1.0
- name: webapp2
  version: "latest"
- name: ssl
  version: latest

All other services following the same structure. We have a total of 7 active services.

Billing

UPDATE 2

We decreased the auto scaling values as per our project requirements which min idle instances to 0 and max idle instance to be 1. The price dropped drastically. But we are still looking for the answer on how to stop an instance when not being used. For ex. the below graph shows an instance started on its own without any activity and is being billed.

enter image description here

Community
  • 1
  • 1
silverFoxA
  • 4,549
  • 7
  • 33
  • 73
  • 1
    What are your service configurations? – Dan Cornilescu Nov 12 '17 at 06:51
  • @DanCornilescu Kindly follow the updated query – silverFoxA Nov 12 '17 at 12:55
  • Side note: the way you placed `app.yaml` before the `Services` seems to indicate that you *might* assume that `app.yaml` has a more important role. It doesn't, at best it is simply the config file for the default service. Unless you already have that separately, in which case it might actually be unused. See https://stackoverflow.com/questions/34110178/can-a-default-service-module-in-a-google-app-engine-app-be-a-sibling-of-a-non-de/34111170#34111170. Pls ignore if I misunderstood. – Dan Cornilescu Nov 12 '17 at 17:13

2 Answers2

2

Drop your min_idle_instances configuration in the automatic_scaling section - those configs effectively represent instances running at all times - also called resident instances for that reason.

Their role is not to handle traffic regularly. They only handle overflow traffic for short periods of time when the traffic exceeds the capacity of the running dynamic instances to keep the latencies low, while GAE spins up additional dynamic instances (which are the ones actually handling the bulk of the traffic).

Just in case it's not clear - resident instances aren't going away - it is their job to remain alive even if there is no activity on the site.

Dan Cornilescu
  • 39,470
  • 12
  • 57
  • 97
  • Does it imply that if there's no activity, keeping the `min_idle_instances` at a low level would stop creating instances separately if not required(i.e the image shared above shows 12 instances being created per hr basis would drop down to 0/1 if there's no activity)? also if certain services consuming more instances (i.e 5/6) and we have assigned `min_idle_instances` to be `1/2` would it conflict? – silverFoxA Nov 13 '17 at 03:55
  • 1
    I think you're misreading the graph - you don't have 12 instances being created per hr, you just have 12 instances running. And most (if not all) of them not doing anything - they're idle - those `min_idle_instances` you have configured. Whatever the services are consuming translate into dynamic instances, started and stopped as needed - but that's in addition to these idle ones. – Dan Cornilescu Nov 13 '17 at 04:26
  • Thank you for your response. I believe we were not in sync with the graph. We shall run this test case as you have suggested. 1. Do we need to define the autoscaling parameters because as much as we understand from the above comment `dynamic instances` are taking care of all the requests and major traffic? 2. If the services having an idle instance of 6(min) shouldn't there be total services*6 `instances` running? – silverFoxA Nov 13 '17 at 06:19
  • 1. You don't *have to*, but it's probably a good idea to do so - to get the best price/performance ratio for your particular app. But you should understand what you're doing. See https://stackoverflow.com/questions/40924353/how-does-google-app-engine-autoscaling-work 2. Yes, there *should* be 6 resident instances per service, plus whatever dynamic instances are active at the time. The graphs are just some summary representations, not very precise, especially for low numbers. – Dan Cornilescu Nov 13 '17 at 14:02
  • Added clarification to the answer. You appear to still have a resident instance left - you changed `max_idle_instances` from its default value to 1. I'd set it to 0 or remove it completely if 0 is not accepted. – Dan Cornilescu Nov 14 '17 at 05:01
  • Unless you actually have activity on the site - check your request log timestamps, +/- 15 min. The graph is not very good at showing which one is actually the billed instance. – Dan Cornilescu Nov 14 '17 at 05:14
1

You can start and stop GAE services, configuring to manual_scaling and use GAE API to start and stop.

const proj = ''        // project id here
const serv = 'default' // or your service id
const vers = ''        // version id here

const {google} = require('googleapis')
const appengine = google.appengine ({version: 'v1', auth: auth})

// To retrieve Status:
appengine.apps.services.versions.get ({
            appsId: proj,
            servicesId: serv,
            versionsId: vers,
            view: 'BASIC',
        })
.then ()
.catch ()

// To Change Status:

newStatus = 'STOPPED' // or 'SERVING'
appengine.apps.services.versions.patch ({
            appsId: proj,
            servicesId: serv,
            versionsId: vers,
            updateMask: 'serving_status',
            requestBody: {
                serving_status: newStatus
            }
        })
.then ()
.catch ()