The Deployment Architecture for Microservices

A partial shift to the Microservices architecture in the world of enterprise Java, either driven by serious needs or by a desire to try something new, changed the way applications, now specialized as Microservices, are handled. In the old world, a curated set of common runtime libraries required for a usually monolithic application was represented by an application server. From a developer's point of view, an application server may have been viewed as a simple collection of Java libraries that implements a standardized API a developer could always rely on being there. Application servers provide much more functionality than that, such as the following:

  • Clustering
  • Load-balancing  
  • Fault-tolerance
  • Diagnostics
  • Security

Java applications could be automatically distributed among cloud nodes, while the application servers resolved load-balancing issues, reported errors, and operations were able to administrate all of the functionality easily.

In a Cloud environment, these functionalities, among many others, are usually moved to another layer.  Even end-to-end security is often not left for the application server to manage. Load-balancing and clustering are managed by tools specific to the chosen cloud environment. In a stateless world, where the number of active nodes changes rapidly based on current load, such functionality is obsolete. There are built-in tools to perform health checks, handle TLS/SSL and provide fault-tolerance monitoring or even testing. Docker especially has taken the role of a universal container handled by many cloud environments with ease. Applications are just deployed to the cloud and scaled in the cloud. And the cloud environment is completely abstracted from the application by thin, self-managing wrappers, which are mostly Docker containers. However, moving solutions from these problem domains to outside of the application server does not mean the problems are gone, only that they're handled by different code on a different layer.

As applications, and especially Microservices, are deployed and scaled independently (especially in a cloud environment), the need for a big, heavy application server that is ready to host multiple applications at once, while being able to connect and maintain a connection with a cluster of other servers, support replication, and security realms is gone. Likewise, replicating it multiple times across the cloud is gone. Having just the amount of functionality that is required for an application to run is an important optimization.

However, looking at application servers and getting an impression of them being big, slow to start, and difficult to manage may be just a wrong impression. First, application servers are smart and use lazy loading. They load only the libraries required to run the deployed applications into memory; not everything is loaded at startup. This concept of lazy loading may result in the same or only slightly higher memory usage than a rightsized runtime environment. There may be situations where an application server, even though considered big and heavy, may eventually save resources. Having a single physical machine with many applications or Microservices deployed, as those do not require much computational power, requires only one application server to be up and running. When compared to the memory footprint and the footprint on a persistent storage of multiple Microservices, each running in their own dedicated environment, an application server might actually win in absolute numbers.

Solutions such as Spring Boot or OpenLiberty may reach down to 15 megabytes of artifact size and require approximately 25-30 MB of memory on startup. On the other hand, a full-blown application server with all the functionality is often slightly more than 100 MB on the hard drive and takes about 40-50 MB of memory on startup with the same application deployed, due to lazy loading. However, such low numbers apply to rightsized solutions only in the case of the simplest applications. In the real world, Microservices use databases, thread pool management, and bean pooling, as well as publishing REST APIs and generating logs, and many other functionalities. The more functionality it has, the less difference can be measured in size between a rightsized solution and an application server, as we end up creating a MicroService which more or less provides functinality of a complete application.

An application server also held on the principle of layering. The need for layers is not gone in the world of Microservices. In fact, it is more essential than ever. A simple yet very important piece of advice for developers is to seek vendors who do not break the principle of layering. Forcing developers to restart the whole environment due to changes in one class of one deployment unit may be considered poor engineering compared to standards used in the rest of the industry for several years. Being forced to upload dozens or hundreds of megabytes into Docker hub due to a small change in a small Microservice is not ideal either.

Pure Java EE solutions usually respect layering principles or even provide multiple ways for fast redeployments and tiny changes. OpenLiberty has a very clever class loader and Maven/Gradle plugins, making it easy for developers to see changes instantly during the development phase. WildFly Swarm offers hollow JARs, which are rightsized exactly for the Microservice. Payara Micro also acts as a separate runtime for applications/Microservice, event if not rightsized. The situation is a little less optimal with Spring Boot; running and stopping a Spring Boot Java Archive may be time-consuming. However, Spring offers a solution named Spring Loaded ( github.com/spring-projects/spring-loaded ). This is an open source project that enables developers to reload classes at runtime. It is not as advanced as other commercial alternatives, yet it rapidly reduces the number of restarts required, reducing non-productive time.

The Java EE solutions for the new era of Microservices are very mature, including Spring Boot. There is no longer any need to explicitly declare every runtime-required library. There are mature project generators and plugins to assist in creating self-contained Microservices during the build phase. Usually, the service providing vendors include packages to make deployment in their very own cloud environment, which is a factor to consider in the process of choosing the right solution. This way, even when programming against a fully-standardized Java EE environment, some amount of vendor lock may be introduced.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.239.118