How are cloud-native applications engineered? In contrast to the increasing popularity of the topic, there are surprisingly few reference applications available. In the previous blogpost we described a first version of a prototypical document management application consisting of composed containers which is called ARKIS Microservices. We elaborated on the challenges involved when designing and developing a cloud-native application. In addition, we showed some details about the architecture and functionalities of version 2.5 of this generic reference application .
In this blogpost, we now dive deeper into the architecture of the latest version 3.3, paying attention to each component. The document management software is a cloud-native application based on a microservices architecture. The software permits multiple tenants to manage their documents (create, read, update, delete and search patterns in documents). It manages the different tenants and offers different isolation models to store the documents of a tenant. Furthermore, the services are discoverable through declarative service descriptions, and their use is billed according to a pay-per-use scheme.
ARKIS Microservices 3.3 also offers some administration features, for example, migration between the different isolation models for a specific tenant or addition of hundreds or thousands generic documents to a tenant. This allows for a quick evaluation of the application without the need to import real data, and thus ensures an instant service experience.
Multi-tenancy is a common requirement of lots of applications in the cloud. There are different options to implement multi-tenancy with respect to stateful services. In older architectural designs one can find these options but in the new microservices approach we have found a more versatile multi-tenancy option thanks to the new features that microservices offer us. Summarizing, there are 5 multi-tenancy models ordered by level of isolation of the tenants (- to +):
- A: Shared DBMS, Shared database, shared schema, shared table/collection
- B: Shared DBMS, Shared database, shared schema, one table/collection per tenant
- C: Shared DBMS, Shared database, one schema per tenant
- D: Shared DBMS, one database per tenant
- E: One DBMS per tenant
The prototype covers all the models which a NoSQL database support (option C is not possible because MongoDB as used by us has not schemas) and it is possible to migrate the tenants between the different models and have tenants in all the models at the same time.
In the big picture above, all the components of the architecture are shown in relation. We can divide it in 3 layers: database, backend and frontend. A total of eight microservices implement the application-specific logic and presentation, whereas more microservices are generic and only parameterised and bound to the application.
- The database layer. We can find here the persistence of the data that the application manages, basically documents and users (tenants). It is composition of MongoDB microservices and covers all the multi-tenancy models. These microservices are the unique stateful microservices of the application. Optionally, they could be bound from an already running DBaaS.
- The backend layer. These are stateless microservices which implement a REST API. We can find five different microservices (independently scalable) implemented in Python which are the core of the application:
- User MS: CRUD of users.
- Document MS: CRUD of documents.
- Search MS: Search patterns inside the documents.
- Migrate MS: Migrate the documents of a tenant between the multi-tenancy models.
- Data MS: Add generic data for a tenant in its multi-tenancy model.
- Kong. It is an open-source API gateway and microservices management layer. Adding plugins to Kong, we can add easily extra functionalities to our API, as for example plugins of authentication, security, traffic control, transformation, serverless, logging, analytics and monitoring. Thanks to that we don’t need to implement these common characteristics to any of our microservices, avoiding to repeat code inside them and making lightweight our microservices. Kong is implemented for running as microservice itself and the application has been extended to run it in a Kubernetes cluster, through small modifications to the upstream Kong deployment files.
- OpenAPI specification. The goal is to define a standard, language-agnostic interface to REST APIs. This specification is also called Swagger specification. The Swagger editor is a open-source tool for helping application engineers to create the specification file and the complementary Swagger UI offers an interface to see in a user-friendly way all the API information described in the specification. With this specification a developer can easily learn and understand how to use the API. It is also a standard that helps to upload APIs to a marketplace such as Mashape One. Hence, we have modelled the ARKIS Microservices description declaratively in OpenAPI. Nevertheless, OpenAPI has limitations compared to many years of research on service description languages, and does not fully express the service behaviour.
- Cyclops: rating, charging and billing framework. Cyclops is open-source and it is designed following a microservice architecture. Easy to install, it is a fast solution to rate the usage of a tenant of the service API and generate a bill for any period of usage time. The clients of the application can also use Cyclops to see all their bills and details of their usage. We performed the integration with the ARKIS Microservices prototype in the search microservice, so each time that a user uses this function the microservice will send a JSON post to the Cyclops endpoint with the information to be charged properly.
This architecture was designed and developed inside the project ARKIS where we also compared different orchestration tools, created a formula to help us to scale properly the microservices and compare the multi-tenancy options with respect to isolation, resources usage and performance. The implementation thus reflects research results from our ongoing initiatives on Cloud-Native Applications, Service Tooling and Cloud Accounting & Billing.