Heroku, Grails: Missing resources if using multiple web dynos

后端 未结 3 1823
Happy的楠姐
Happy的楠姐 2021-01-23 04:54

I have created grails application and uploaded it in heroku.
If I use \'heroku scale web=1\' everything looks OK. But if I run \'heroku scale web=2\', some

相关标签:
3条回答
  • 2021-01-23 05:09

    All assets which are in your slug (your git push essentially) should be present on all dynos. Are these assets that have been uploaded? If so, Heroku has an effectively read-only file system (http://devcenter.heroku.com/articles/dyno-isolation#ephemeral_filesystem), so you need to ensure that these assets are going to something external such as Amazons S3.

    http://grails.org/plugin/amazon-s3

    0 讨论(0)
  • 2021-01-23 05:20

    I had similar issues with image files that cannot be directly defined in ApplicationResources.groovy. I found a workaround for this one, though:

    Add a CSS file to ApplicationResources.groovy that has multiple class definitions for all the assets you need to load like this:

    .asset1 {
      background: url('path/to/image1.png');
    }
    .asset2 {
      background: url('path/to/image2.png');
    }
    .asset3 {
      background: url('path/to/image3.png');
    }
    ...
    

    And in ApplicationResources.groovy define the following:

    modules = {
        ...
        myModule {
            resource url: 'path/to/assets.css'
        }
        ...
    }
    

    Now the Resources plugin has already those paths ready for the images when the module that contains the CSS file is loaded from a GSP view, or if the images are referenced dynamically from JavaScript etc.

    Rather hacky but it works. Tested this in Heroku with 2 dynos.

    0 讨论(0)
  • 2021-01-23 05:29

    https://github.com/grails-plugins/grails-resources/pull/11

    According to the owner of the resources plugin, Marc Palmer, they're ignoring a check for old references to static resources.

    So, this manifests itself as a load balancing issue that you would have on any system if you're not using sticky load balancing (which is the case with Heroku). Here's what's happening in the Heroku case:

    1. Request comes into someapp.com
    2. index.gsp is served from app server 1, web.1 index.gsp contains
    3. The resources plugin generates a mapping from /static/js/resource.js to /js/resource.js on web.1
    4. The client makes a request for /static/js/resource.js
    5. The request is routed to a different app server, web.2
    6. /static/js/resource.js has not been mapped on web.2 and 404s

    From my research, the best practice is to declare your resources in a resources file.

    See the following:

    http://grails-plugins.github.com/grails-resources/guide/3.%20Declaring%20resources.html

    This will tell the app server at boot time that a resource exists up front, avoiding the adhoc loading process.

    For example, as in my previous email, a MyResources.groovy would look like:

    modules = { 
      application { 
        resource url:'js/application.js' 
        resource url:'js/ui.geo_autocomplete.js' 
      } 
    }
    

    So, you can use either of the two methods -- explicitly specify resources, or use adhoc loading (add the following to your Config.groovy: )

    grails.resources.adhoc.includes = [] 
    grails.resources.adhoc.excludes = ["*"]
    

    It essentially disables adhoc resource processing.

    0 讨论(0)
提交回复
热议问题