Book Image

Cloud Native Applications with Ballerina

By : Dhanushka Madushan
Book Image

Cloud Native Applications with Ballerina

By: Dhanushka Madushan

Overview of this book

The Ballerina programming language was created by WSO2 for the modern needs of developers where cloud native development techniques have become ubiquitous. Ballerina simplifies how programmers develop and deploy cloud native distributed apps and microservices. Cloud Native Applications with Ballerina will guide you through Ballerina essentials, including variables, types, functions, flow control, security, and more. You'll explore networking as an in-built feature in Ballerina, which makes it a first-class language for distributed computing. With this app development book, you'll learn about different networking protocols as well as different architectural patterns that you can use to implement services on the cloud. As you advance, you'll explore multiple design patterns used in microservice architecture and use serverless in Amazon Web Services (AWS) and Microsoft Azure platforms. You will also get to grips with Docker, Kubernetes, and serverless platforms to simplify maintenance and the deployment process. Later, you'll focus on the Ballerina testing framework along with deployment tools and monitoring tools to build fully automated observable cloud applications. By the end of this book, you will have learned how to apply the Ballerina language for building scalable, resilient, secured, and easy-to-maintain cloud native Ballerina projects and applications.
Table of Contents (15 chapters)
1
Section 1: The Basics
4
Section 2: Building Microservices with Ballerina
8
Section 3: Moving on with Cloud Native

The emergence of microservices

SOA provides solutions to most of the issues that monolithic applications face. But developers still have concerns about creating a much more scalable and flexible system. It's easy to construct a monolithic structure. But as it expands over time, managing a large system becomes more and more difficult.

With the emergence of container technology, developers have been able to provide a simple way to build and manage large-scale software applications. Instead of building single indivisible units, the design of microservices focuses on building components separately and integrating them with language-independent APIs. Containers provide an infrastructure for applications to run independently. All the necessary dependencies are available within a container. This solves a lot of dependency problems that can impact the production environment. Unlike virtual machines (VMs), containers are lightweight and easy to start and stop.

Each microservice in the system is designed to solve a particular business problem. Unlike monolithic architectures, microservices focus more on business logic than on technology-related layers and database designs. Even though microservices are small, determining how small they should be is a decision that should be taken in the design stage. The smaller the microservices, the higher the network communication overhead associated with them. Therefore, when developing microservices, choose the appropriate scope for each service based on the overall system design.

The architecture of microservices eliminates the concept of the ESB being the central component of SOA. Microservices prefer smart endpoints and dumb pipes, where the messaging protocol does not interfere with business logic. Messaging should be primitive in such a way that it only transports messages to the desired location. While the ESB was removed from the microservice architecture, the integration of services is still a requirement that should be addressed.

The following diagram shows a typical microservice architecture:

Figure 1.4 – Example microservice architecture

Figure 1.4 – Example microservice architecture

The general practice of the design of microservices is to provide a database for each service. The distributed system should be designed in such a way that disk space or memory is not shared between services. This is also known as shared-nothing architecture in distributed computing. Sharing resources creates a bottleneck for the system to scale up. Even if the number of processing instances increases, the overall system performance does not increase since accessing resources might become a bottleneck that slows down the whole process. As databases are shared resources for services, the microservice architecture forces the developer to provide separate databases for each service.

However, in traditional business applications, it is not feasible to split the schema into several mutually exclusive databases since different resources need to be shared by the same entities. This makes it important that services communicate with each other. Multiple protocols are available for interservice communication, which will be addressed in Chapter 4, Inter-Process Communication and Messaging. However, communication between services should also be treated with care, as consistency becomes another headache for the developer to solve.

There are multiple benefits of using microservices rather than monolithic architectures. One advantage of this type is the scalability of the system. When it comes to monolithic applications, the best way to scale is by vertical scaling, where more resources are allocated to the host computer. In contrast with monolithic applications, microservices can not only be scaled vertically but also horizontally. The stateless nature of microservices applications makes microservices more independent. These independent stateless services can be replicated, and traffic can be distributed over them.

Microservices enable developers to use multiple programming languages to implement services. In short, we refer to these as being polyglot, where each service is designed in a different language to increase the agility of the system. This provides freedom to choose the technology that is best suited to solve the problem.

As well as having advantages, the microservice architecture also has disadvantages.

The biggest disadvantage of the microservice architecture is that it increases complexity. Microservice developers need to plan carefully and have strong domain knowledge of the design of microservices. The following problems are also associated with the microservice architecture:

  • Handling consistency: Because each service has its own database, sharing entities with other services becomes an overhead for the system compared to monolithic applications. Multiple design principles help to resolve this problem, which we will describe in Chapter 5, Accessing Data in the Microservice Architecture.
  • Security: Unlike monolithic applications, developers need to develop new techniques to solve the security of distributed applications. Modern authentication approaches, such as JWT and OAuth protocols, help overcome these security issues. These methods will be explored in Chapter 7, Securing the Ballerina Cloud Platform.
  • Automated deployment: Distributed system deployment is more jargon that needs to be grasped clearly. It is not very straightforward to write test cases for a distributed system due to consistency and availability. There are many techniques for testing a distributed system. These will be addressed in Chapter 10, Building a CI/CD Pipeline for Ballerina Applications.

Compared to an SOA, a microservice architecture offers system scalability, agility, and easy maintenance. But the complexity of building a microservice architecture is high due to its distributed nature. Programming paradigms also significantly change when moving from SOA to a microservice architecture. Here's a comparison between SOA and microservice architectures:

Table 1.1 – SOA versus microservices

Table 1.1 – SOA versus microservices

Having understood the difference between monolithic and microservice architectures, next, we will dive into the cloud native architecture.