Webservice APIs response times are critical for successful business. There are several strategies to improve the response time. One of the strategies is to compress the payload size. When payload sizes are compressed network latency between you and your client can be reduced.
HTTP Compression is a good technique to reduce the network latency between the HTTP client and server. It’s used to optimize the page loading time on the browsers. But however it’s an effective technique to be used in web service API invocations as well, especially where payload size are huge.
How to do HTTP compression in Apache Tomcat server?
A typical connector configuration in TOMCAT_HOME/conf/server.xml file would look like the one listed below:
To this connector you just need to add two additional attribute: compression and compressableMimeType.
When compression attribute is set to value “on” – Tomcat server will start to compress the response in GZIP format. GZIP compression typically compresses 70% of your payload size.
compressableMimeType indicates the comma separated list of MIME types for which HTTP compression may be used. Since for webservice APIs application/soap+xml, text/xml, application/json are commonly used MIME types those have been listed here.
You may also consider using additional attribute compressionMinSize. To this attribute you can specify the minimum amount of data before the response is compressed. If not specified, this attribute is defaults to “2048”. I would recommend not setting this property. As default 2 KB is the idle size after which you do want to compress the contents.
Can we do the HTTP compression in Load balancer?
Yes HTTP compression can be done at the Load balancer level as well. But however I will not recommend because of the CPU consumption. HTTP compression consumes CPU. At the load balancer level all of your transactions are flowing through, whereas at the application server level, traffic volume is distributed. So there won’t be CPU consumption concentration in one single resource.
Thus doing compression will make your implementation more scalable and available.
Will this change affect existing clients?
Change mentioned above will have global impact. It means even your pre-existing clients will start to receive response in compressed format. Some of your pre-existing clients may not be prepared to receive responses in compressed format.
How to rollout this change in a phased manner?
As all of your clients may not be ready to receive contents in compressed format, here is a strategy to rollout this architecture in a phased manner.
You can create a new connector configuration in the server.xml. This connector will listen on a new port (say 8090). In this port you can configure compression and it’s related attributes. Old connector configuration should remain undisturbed. So revised configuration might look:
To the new clients that you are on-boarding, you can publish them the URL with port 8090. Old clients can migrate from 8080 to 8090, when they are ready.
This is one of the least impact way to rollout the change in a controlled manner.
I like your articles. there is a lot of great content on this blog.
Compression as you stated has overhead on CPU which is why I have to disagree with you on the notion that it is best to compress it on the application server (tomcat in this case). It is infant in nearly all circumstances better to leave the CPU on the application to serve the business data rather then spending time on compression. Compression and SSL is best left to the loadbalancers.
Most hardware loadbalancers are quite powerful machines and they can easily handle compression next to SSL offloading without issues. Incase a software loadbalancer is used then it is just a matter of sizing it properly and or utilizing webserver/loadbalancer for compression and perhaps also caching both fully static or fairly static ( e.g. time bound ) responses.
In my experience I have never seen so far that Loadbalancer CPU became a issue because of compression / decompression. Infact it adds value when combined with caching where the requests to the backend (e.g. tomcat in this case) can be reduced and already compressed responses can be served directly from the webserver / loadbalancer.
is there an option for compression if the connector is ‘ajp’ instead of http ?