Best Practices - Azure App Service and Java Application
Recently we migrated an application used by 170 thousand users to Azure PaaS. This application has 3 tier model. The web tier uses HTML5 and ReactJS. The application tier uses Java and for Database we used Azure SQL DB. There was good amount of learning and I thought I should share those for everyone’s benefit.
- Environment – In our case the Java application was providing REST API which were in turn consumed by the Web Layer (ReactJS). This setup provides stateless transactions. We used Web App to host the Java APIs. It could be API App as well. We thought of using App Service Environment (ASE) in the beginning but continued with multi-tenant environment instead. This decision was taken after a discussion with Azure product team and they told us not to use ASE for Java applications. This is due to the current performance issues Java applications have with ASE. This I believe will be taken care before EOY 2016 and ASE should be suitable for Java as well.
- Connectivity between services – It is very important that you use connection pooling for your SQL DB. Find out what is the max no. of connection your SQL DB can hold. In our case it was 2000 and we were using JDBC/Hibernate to connect to SQL DB. Hence we used 100 max connection pool settings in our JDBC so that even we scale up to 20 instances of Web App (which is max no. of instances in case of Web App premiere), it works perfectly.
There are high possibilities of transient faults between service calls hence retry logic is something is a must in your code. Utilize Retry pattern as described here (https://msdn.microsoft.com/en-us/library/dn589788.aspx) and in some cases, if you are using an external service and you are not very sure about the responsiveness of the service, then Circuit Breaker pattern should also be useful (https://msdn.microsoft.com/en-us/library/dn589784.aspx).
- Caching – For any type of data that is not frequently changes, usage of caching will do wonder in performance. We found Redis very useful in this regards. Although we have an example in Azure web site of using a library called Jedis (https://azure.microsoft.com/en-us/documentation/articles/cache-java-get-started/), we used another library called Lettuce as it has TLS option that Jedis didn’t have (at least at that point in time). I posted regarding this in my previous post: https://blogs.msdn.microsoft.com/pranab/2016/04/14/how-to-use-azure-redis-cache-with-java-using-lettuce/
- Scalability – Azure App Service has the flexibility of auto-scale. We used the same in our production and it gave us great result as this application was seasonal in nature. But you should be very careful about configuring auto-scale. You need to decide whether the scale will it be CPU based, memory based or incoming request based. Please do extensive load test and then decide. Also make sure you planned for surge of incoming requests and have enough number of instances available at any point in time to tackle such situation. Otherwise, in case of seasonal application you can use fixed set of instances for the pick request days based on your test experience and then reduce to minimum no. of instances when that period is over.
- Special case with Hibernate – In case you are using JDBC + Hibernate, please make sure your SQL tables have nVarchar columns instead of Varchar columns. The reason is Hibernate “string” gets converted to nVarchar all the time. If you have Varchar in your table, then SQL DB will silently do implicit conversion between nVarchar and Varchar. And this will reduce the performance drastically.
- Last but not the least – test, test and test. All possible test especially load test is super critical to a successful implementation of Java application on Azure PaaS.