In a monolithic architecture principle applications are developed as one single application where all the components (libraries / functions / procedures) would live on a single server and cannot be separated on different servers. In some cases these applications are developed in a way that two of those instances can work together in a clustered manner. However, in many cases the primary way of deploying them is to deploy them on a single server. If it turns out that the use of the application grows and due to this the application gets slower the common answer was, add more compute resources. Adding resources to a server to cope with the growth in demand for compute power is seen as vertical scaling.
Databases, Oracle databases, have adopted the model of horizontal scaling already for some time by using Oracle RAC. When the demand for more compute power grows additional nodes can be added to the RAC cluster. Adding additional nodes, rather than putting more compute power in a single node, is referred to as vertical scaling.
Also in the area of application servers and web servers the vertical scaling model is not something new. Creating a cluster of, for example, Weblogic application servers and loadbalance the load over the members of this cluster is something that already has been done for quite some time.
However, even though Weblogic clustering and Oracle RAC clustered databases are available it is often seen that the foundation of an architecture is not taking into account the vertical scaling model. When you intend to build an application that will make optimal use of vertical scaling you will have to ensure that you incorporate this directly in your architecture. It is good practice to ensure that your application (landscape) will be able to scale vertically even in cases where you do not see the direct use. This is to ensure that if you ever need to scale in the future you do not have to redesign the application from scratch or recode large parts of it.
One example of an architecture principle that will provide you an optimal vertical scaling model is the use of microservices. microservices is a software architecture style in which complex applications are composed of small, independent processes communicating with each other using language-agnostic APIs. These services are small, highly decoupled and focus on doing a small task, facilitating a modular approach to system-building.
Commonly microservices will communicate with each other by using the HTTP protocol, calling (REST-)API’s via HTTP has the advantage you can make use of all the scaling and load balancing options that are commonly available and are already proven technology for years for deploying large web enabled applications.
monolithic application design
By implementing microservices you will avoid building an application based upon a monolithic application design as shown in the below diagram.
Some of the characteristics of an application build based upon a monolithic application design are:
- Application has single code base with multiple modules
- Large internal dependencies between components and functions
- Components invoke one another via language-level method or function calls
- In general difficult to scale up and down when the situation demands this
- Poor resilience towards component failure, small disturbances often result if complete application unavailability
- Complex to maintain and difficult to change or integrate with new systems
- Poor re-use of developed functions and components outside of the application
- Commonly depending primarily on vertical scaling of the hardware and not capable of handling horizontal scaling
- Serial development process, takes in general longer to develop.
Microservice application design
Microservices allow you to build multiple smaller components, capable of running all on one or multiple dedicated machines instead of running the entire application on one single server that cannot be scaled easily. An example of the same application as above, however build upon a microservice architecture, is shown in the below diagram:
- Application is broken down in multiple (micro)services, each having their own code base / programming language
- Components are loosely coupled and communicate based upon API’s and HTTP calls with each other
- Easy to scale up and down, both vertical as well as horizontal. Each service can run on one, or multiple machines
- Highly resilient towards component failure due to the distributed system principles and the use of multiple small machines.
- Ease of changing components and integrate with new functions.
- Provides an easy way of function re-use outside of the original application realm.
- Parallel development process, takes in general less time to develop.
Implementing this model provides both advantages in scaling as well as in ensuring your application is resilient against component failure. In the below diagram you can see that some components are scaled to a four node implementation and have presence in two datacenters. This provides both benefits on load balancing as well as improved resilience
A node, when used in a microservice architecture will be a machine or virtual machine running one or more microservices. In general this is Linux machine running an application capable of providing an API. One way of building node’s and micorservices is making use of Flask, Flask is a micro web application framework written in Python and based on the Werkzeug toolkit and Jinja2 template engine. It is BSD licensed.
Flask is called a micro framework because it does not presume or force a developer to use a particular tool or library. It has no database abstraction layer, form validation, or any other components where pre-existing third-party libraries provide common functions. However, Flask supports extensions that can add application features as if they were implemented in Flask itself. Extensions exist for object-relational mappers, form validation, upload handling, various open authentication technologies and several common framework related tools. Flask is ideally suited to build microservices on.
In the below diagram we show a node build based upon Flask in combination with NGINX, NGINX is a free, open-source, high-performance HTTP server and reverse proxy and running both Flask as well as NGINX on an Oracle Linux operating system. In this example we have selected specifically Oracle Linux as microservice nodes are commonly used in deployments that demand high availability, extreme performance and extreme scaling. Oracle Linux can provide this in combination with Flask and NGINX.
As one of the advantages of microservices is that it can scale easily it is commonly a good practice to ensure that your nodes are based upon a virtualization strategy. As we use Oracle Linux in our example it also makes sense to use Oracle VM as a virtualization layer. When needed a new node with the associated microservice can be created and can be added to the loadbalancing.
When monitoring your entire footprint with Oracle Enterprise Manager you can create a solution in which Oracle VM automatically creates new nodes for you when performance drops due to an increase in the number of requests. Oracle Enterprise Manager will then be able to scale down again as soon the number of requests goes down. By implementing such a self scaling and self healing solution you are assured of a always performing and always available solution to your users. This will require good thought on what kind of hardware to use; in this case it would be a good solution to use for example the Oracle Private Cloud Appliance. The Oracle Private Cloud Appliance is an engineered system, developed by Oracle, specifically to run elastic and changing landscapes based upon Oracle Linux and Oracle VM.