Architecture & Coding Guidance

Author: rafaelprocha

Context

Today Microservices architecture has become hype topic in software development industry. It is an approach to modularity which functionally decomposes an application into a set of services. The development teams can adopt the most appropriate technology stack in order to resolve specific issues. The microservices architecture also improves services scalability by enabling features such auto-scaling and micro-container approach.

API’s and Microservices are so related once the most common facade are API interface uses fully compliant RESTful services. But nowaday we are still facing issues when needs to integrate with legacy systems to externalize its functionalities as services once the most systems does not expose standards protocols such as Web Services or REST Interfaces. Let’s explore this issue.

The Problem and Microservice Approach

The most companies desire to expose API’s internally or externally but their systems or application were not built for this purpose. The most applications are based on the following architecture:

When facing this kind of scenario, it is a common approach build an adapter component to expose the service with standard protocol. This component should look like the diagram below:

The service adapter is the key component of solution since it will enable legacy service externalization. To provide this expected standardization, the following capabilities should be implemented:

RESTful compliant

Organized around common business domains

Easily scalable

Lightweight packages

As service adapters are considered kind of integration applications, they should follow an architectural style in order to be compliant with common standards. The architectural style that best suite the above capabilities and others commons requirements is the Microservice approach.

Microservice Implementation Strategy

Once decided that service adapter implementation are based on Microservice Architecture style some capabilities are required such as:

Small package and low memory consumption

Application startup should be fast to load new container instances.

Fast and simple development based on common standards such as Swagger specification.

Easy security integration to provide features such as Basic Auth or OAuth2.

Some frameworks has the most of capabilities listed above. The recommend are:

Java:

Spring boot

Spark Framework

Play Framework

Dropwizard

Apache Camel

JavaScript:

Node.js

Another crucial capability when enabling API endpoints through Microservice implementation is fully integration capability with legacy systems. This kind of feature requires specific frameworks which implements enterprise integration patterns. The recommendation here is use the most famous Java framework called Apache Camel.

Microservice Deployment Strategy

Once the package were built, it need to be deployed. The recommended strategy is deploy it into a PaaS (Platform as a Service) because it offers some built-in features such as:

Containerization

Container Orchestration

Storage

Monitoring

Logging

Also, another two crucial capabilities should be provided:

Being scalable in order to support traffic spikes

Automation API’s to create autonomous deployment pipeline

The main market PaaS offering should be considered to be used as deployment strategy are:

Pivotal Cloud Foundry: is good choice when using Spring stack technology because it has a native integration

Red Hat OpenShift: could be an alternative when using some Red Hat technology. It also uses docker and kubernetes to containerization

SalesForce Heroku: It abstracts the features implementations such as containers or logging. It’s a good choice when building applications using the Twelve Factor App methodology

Other choices to be considered are Amazon Elastic Beanstalk and Google App Engine. Both of them are interesting because have native integration with cloud services and infrastructure once they are strong IaaS providers.

But the best alternative to deploy and run microservices are solutions which provide the runtime platform (PaaS) and fully integration with API Manager Platform. In this case, the Sensedia API Management Suite offers a built-in feature called BaaS (Backend as a Service) which is compliant with PaaS features and capability.

The BaaS feature should be used to deploy and run those microservices which exposes API from legacy systems or also when creating new application or services using this architecture style. The Sensedia BaaS platform supports natively the following technologies:

Microservices and API Management Platforms

Once microservices are deployed and running, its interface should be exposed as an API and must be managed using an API Management Suite because this kind of solution offers a lot of advantages. The most of API Manager solutions have the features below:

Security and Resilience: to protect backend microservices from non-managed consumers. When the API are open to partners or community, those microservices should be protected from being overloaded with spikes of traffic using capabilities such as rate limit, payload size limit or spike arrest.

Access Control: the consumers should use the API under access policies. The API Manager must provide standard protocol such as OAuth 2.0 or JSON Web Token for consumer authentication and generate those tokens. Also, some policies may be configured such as expiration or rate limit.

Monitoring and tracing: the operation teams use this capability for platform health check and debugging.

All capabilities listed above are common in API Gateway solutions, but other features are crucial for API Manager solutions such as:

Caching: should be use to avoid unnecessary microservice use or latency once some read functions may be cached. Note that some cases, the backend services are rated and this feature could minimize some cost.

Analytics: the API usage could be monitored in real time. This kind of feature should provide dashboard for metric extractions.

As mentioned above, some API Manager platforms offers full integration and management for microservices deployment and runtime capabilities. This kind of feature offers end-to-end management platform, it is not necessary provide aparted infrastructure to run microservices.

The Sensedia API Manager Suite provides a solution look like the diagram below:

Summary

Using microservices architecture style is an development approach to enable RESTful interfaces from legacy systems which not expose these kind of endpoints natively, but the first challenge is choose the right implementation tools. There are a lot of frameworks and languages flavors which could help on microservices implementation. The decision of which one is chosen depends of scenario are being faced but there are some recommendations for help as mentioned above.

After development toolkits were chosen, the next decision is establish the microservice runtime and deployment platform. Once more, the decision depends of the scenarios are being faced. But in this case, the main goal is expose a legacy functionality as RESTful API and because this reason, it makes sense deploy the microservices in the same platform.

The Sensedia API Management Suite is a API Management Platform which provide the backend as a service (BaaS) feature which performs as microservices runtime having full platform as a services (PaaS) capabilities. Furthermore, the platform offers standard features as API Gateway, Caching and Analytics.

In short, the recommendation is use this kind of platform which provide full API management and also microservice runtime in all-in-one solution.

If you choose to use Apache Cassandra as your NoSQL database, keep in mind that you must consider the following characteristics in order to implement and design your model.

The Apache Cassandra is not fully compliance with ACID properties, however when design the application and the database model all of these properties and how Cassandra handle it should be considered.

See the following topics:

Isolation and Consistency

Apache Cassandra does not have isolation feature, so you must design considering that will not exist concurrency. It does not have lock feature comparing to relational databases, and so the approach must to be different. Consider the following scenario and how to handle it:

Many events arrive simultaneously to your system and you should parallelize to ensure performance. However, each event reads and write a same data that is stored in Cassandra, of course you should read the record and then write, however there is no isolation guarantee, and then it can share outdated data processing and thus may be inconsistent. The best way fix this scenario should be to get all the data you need and process it in memory and then update (write) in batch or serialized in order to evict chance of conflict.

Atomicity

One of the strongest features of the relational approach is atomicity that within a transactional context when an exception occurs all database updates are undone. It is the famous law of commit or rollback. However, Cassandra does not provide this transactional feature coupled with application method transaction and then the implementation of these scenarios turns complex. See the following situations and how to handle them:

# 1 – Within a application method that updates multiple tables in Cassandra it is necessary to ensure that all updates must be made in atomic way. In this scenario it is interesting to use batch feature that API provides and place within the same batch all writes of all tables.

# 2 – Within a application method you should ensure that others points may occurs errors (eg a REST call) and then the context should be rolled back. In this scenario it is interesting to create compensation routines: it should be an exception block to undo the update or create retentive routine to the point that has not been updated.

Asynchronous/Parallel Programming

One of the strongest features of Cassandra is the writing/reading optimization. However, the writing method used in the client can be more effective then using a serialized approach or even using batches. See the following scenario and how to handle it:

You will need to write to Cassandra a few million of records and the scenario implementation shoould be different ways:

# 1 – Write the records in the serialized way, it is one by one each of the records but this approach is not the most performative because its application should wait for execution confirmation.
# 2 – Write the records in the batch way, it is sending a block of records, but this way shoud increase network latency when handling very large block.

But we have a third approach that seems quite interesting, specially when not requiring transactional context: use the feature of parallel programming provided by the API. In the Java API, the driver handle the Future features (using Guava) and in our tests seemed much more performative than other approaches above. However, be careful because this feature uses threads and so your application must be set up to manage a large volume of threads.

Conclusion

The design and implementation of your application should use total different approach comparing when using a relational and transactional database. Keep in mind all of these characteristics should carefully be considered in design once we always used relational aproach.