Eugene Brown
Eugene Brown

Reputation: 4362

Google App Engine old versions of static files being served

I have a flask app that I am deploying to google app engine.

I have been making changes to the js and css scripts in this app and deploying the updated repository to gae. However, when I reload the *.appspot.com url after deploying, the js and css files that are loaded in my browser are not the latest versions.

I am unsure of how to solve this. I don't know whether it is a caching issue in my browser, a problem with my app.yaml file or something else altogether.

When I look in the app engine at the deployed files, the css & js are the current versions that should be being loaded in the browser but aren't.

enter image description here

Here is my app.yaml:

runtime: python27
api_version: 1
threadsafe: true

libraries:
- name: ssl
  version: 2.7.11

handlers:
- url: /.*
  script: app.app

I'm fairly new to gae. If anyone has any suggestions that'd be great.

Thanks!

UDPATE:

I've added to my app.yaml file according to the suggestion of @GAEfan and the page @Dave W. Smith linked to so that now it looks as follows:

runtime: python27
api_version: 1
threadsafe: true

libraries:
- name: ssl
  version: 2.7.11

handlers:
- url: /.*
  script: app.app
- url: /static
  static_dir: static
  expiration: '10s'

However the problem persists. I now expect it might have something to do with @Dave W. Smith's other suggestion, that there are "old instances serving requests until they die off."

Here is another screenshot from the GCP platform showing that there are multiple instances of my app running, one from each new deploy command:

Multiple versions/instances of my app running on google app engine

The latest version is the default one and the screenshot shows that 100% of traffic allocation is on that version. Should I be deleting old versions of the app everytime I deploy? If so, can this be done with the gcloud cli? Is there a way I can keep these older versions and just ensure that static files are definitely served from the latest version?

Thanks again.

Upvotes: 6

Views: 3747

Answers (3)

Gabriel H. Nunes
Gabriel H. Nunes

Reputation: 755

As pointed out by GAEfan, the docs for the standard environment for Pyhton state that both settings for static cache expiration, the individual element expiration and the top-level element default_expiration, are responsible for defining "the expiration time [that] will be sent in the Cache-Control and Expires HTTP response headers". This means that "files are likely to be cached by the user's browser, as well as by intermediate caching proxy servers such as Internet Service Providers".

The problem here is that "re-deploying a new version of the app will not reset any caches". So if one has set default_expiration to, e.g., 15 days, but makes a change to a CSS or JS file and re-deploy the app, there is no guarantee that those files will be automatically served due to active caches, particularly due to intermediate caching proxy servers, which may include Google Cloud servers - what seems to be the case since accessing your-project-name.appspot.com also serves outdated files.

The same documentation linked above states that "if you ever plan to modify a static file, it should have a short (less than one hour) expiration time. In most cases, the default 10-minute expiration time is appropriate". That is something one should think about before setting any static cache expiration. But for those who, like myself, didn't know all of this beforehand and have already been caught by this problem, I've found a solution.

Even though the documentation states that it's not possible to clear those intermediate caching proxies, one can delete at least the Google Cloud cache.

In order to do so, head to your Google Cloud Console and open your project. Under the left hamburger menu, head to Storage -> Browser. There you should find at least one Bucket: your-project-name.appspot.com. Under the Lifecycle column, click on the link with respect to your-project-name.appspot.com. Delete any existing rules, since they may conflict with the one you will create now.

Create a new rule by clicking on the 'Add rule' button. For the object conditions, choose only the 'Newer version' option and set it to 1. Don't forget to click on the 'Continue' button. For the action, select 'Delete' and click on the 'Continue' button. Save your new rule.

This newly created rule will take up to 24 hours to take effect, but at least for my project it took only a few minutes. Once it is up and running, the version of the files being served by your app under your-project-name.appspot.com will always be the latest deployed, solving the problem. Also, if you are routinely editing your static files, you should remove any expiration element from handlers related to those static files and the default_expiration element from the app.yaml file, which will help avoid unintended caching by other servers.

Upvotes: 1

GAEfan
GAEfan

Reputation: 11370

Yes, sounds like a caching issue. Read this: https://cloud.google.com/appengine/docs/standard/python/config/appref#static_cache_expiration

You can test by setting a small cache time for your static files, like this:

- url: /static
  static_dir: static/
  expiration: '10s'

Or, even more granular by:

- url: /static/css
  static_dir: static/css/
  expiration: '10s'

- url: /static/js
  static_dir: static/js/
  expiration: '5m'

Or globally by:

default_expiration: '2s'

Then, when you are satisfied with your static files, set the cache time to something much higher, to speed up your site and save server time.

Upvotes: 2

Dave W. Smith
Dave W. Smith

Reputation: 24966

If that's your app.yaml, you might think you have static files, but they're being served by the app. To make that static really static, you'll need bit extra in our app.yaml. See https://cloud.google.com/appengine/docs/standard/python/getting-started/serving-static-files

What you're probably seeing, unless you're bumping the version for the command line, is old instances serving requests until they die off.

Upvotes: 1

Related Questions