Web User
Web User

Reputation: 7746

Update config on running ElasticBeanstalk Tomcat instance

I have deployed a Spring Boot REST application as a WAR into an AWS Elastic Beanstalk Tomcat 8 + Java 8 instance. Subsequently, I realized that I need to configure the following settings (applies to the Tomcat server.xml):

compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/css,..."

because application.properties in Spring Boot applies only to embedded Tomcat containers. It is too late to change the platform type of the Elastic Beanstalk instance now. Is there any way to update the configuration from the Elastic Beanstalk CLI, using eb config? I was looking at this AWS page, and it looks like it may be possible.

Updated 01/16/2017 Thanks to the answer from @dave-maple I started looking in the relevant parts of Elastic Beanstalk documentation.

First, I discovered that Apache is the default proxy server. I could have changed it to nginx, but I didn't have any particular justification to go that route.

Second, I found that adding an .ebextensions folder to the top level of my Spring Boot project. I did not want to pollute my code base with a cloud provider specific configuration file, but it seemed to be the lowest hanging fruit. So I went for it.

I added the following hierarchy:

MySpringBootProject
 |
 +- src
     |
     +- main
         |
         +- resources
             |
             +- ebextensions
                 |
                 +- httpd
                 |   |
                 |   +- conf.d
                 |       |
                 |       +- enable_mod_deflate.conf
                 |
                 +- myapp.config
                 |
                 +- tomcat-settings.config

Contents of tomcat-settings.config

option_settings:
  aws:elasticbeanstalk:environment:proxy:
    GzipCompression: 'true'

Contents of myapp.config

container_commands:
05-restart-apache:
    command: "sudo /etc/init.d/httpd restart"

Contents of enable_mod_deflate.conf

# mod_deflate configuration
<IfModule mod_deflate.c>
  # Restrict compression to these MIME types
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE text/xml
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/xml+rss
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE image/png
  AddOutputFilterByType DEFLATE image/gif
  AddOutputFilterByType DEFLATE image/jpeg

  # Level of compression (Highest 9 - Lowest 1)
  DeflateCompressionLevel 9

  # Netscape 4.x has some problems.
  BrowserMatch ^Mozilla/4 gzip-only-text/html

  # Netscape 4.06-4.08 have some more problems
  BrowserMatch ^Mozilla/4\.0[678] no-gzip

  # MSIE masquerades as Netscape, but it is fine
  BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

  <IfModule mod_headers.c>
    # Make sure proxies don't deliver the wrong content
    Header append Vary User-Agent env=!dont-vary
  </IfModule>
</IfModule>

Add the following lines to pom.xml (to set up the .ebextensions folder in the top level of the generated WAR file):

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
        <webResources>
            <resource>
                <directory>src/main/resources/ebextensions</directory>
                <targetPath>.ebextensions</targetPath>
                <filtering>true</filtering>
            </resource>
        </webResources>
    </configuration>
</plugin>

I could have sworn this worked, because I saw the Content-Encoding: gzip response header... only a couple of times. Any idea what could be happening?

Upvotes: 0

Views: 1447

Answers (1)

Dave Maple
Dave Maple

Reputation: 8422

The best way to implement compression would be at the nginx proxy which runs in front of tomcat. nginx is more efficient at this operation. To do this you can create an .ebextensions directory in the root of your deployment archive and add an nginx-proxy.config file such as the following:

.ebextensions/nginx-proxy.config

option_settings:
  aws:elasticbeanstalk:environment:proxy:
    GzipCompression: 'true'
    ProxyServer: nginx

Then you can build and deploy the new version of your app on Elastic Beanstalk.

If you need to avoid downtime when rolling out the new version you can use a rolling deployment (takes instances out of LB before deployment new versions) or even blue/green deployment (a new environment + cname swap).

=== EDIT ===

You may need to customize the Content-Type values that nginx will gzip.

To gzip everything, create a config file in .ebextensions:

.ebextensions/gzip.config

files:
  /etc/nginx/conf.d/gzip.conf:
    content: |
      gzip_types *;

or to be more selective, define the types you want compressed:

.ebextensions/gzip.config

files:
  /etc/nginx/conf.d/gzip.conf:
    content: |
      gzip_types text/plain text/css application/json application/x-javascript text/xml;

Upvotes: 1

Related Questions