© Kasun Indrasiri and Prabath Siriwardena 2018
Kasun Indrasiri and Prabath SiriwardenaMicroservices for the Enterprisehttps://doi.org/10.1007/978-1-4842-3858-5_10

10. APIs, Events, and Streams

Kasun Indrasiri1  and Prabath Siriwardena1
(1)
San Jose, CA, USA
 

In this chapter, we focus on how microservices can connect with external services, systems and data using APIs, Events and Streams.

As discussed in previous chapters, any of the microservices applications that you develop have to expose the business capabilities to consumers in such a way that you can create, manage, secure, analyze, and scale those capabilities. Therefore, such capabilities are exposed to consumers as APIs, which are governed by a process commonly known as API management. Similarly, Microservices can consume external APIs via invoking API calls. APIs more or less follow a synchronous and request-response messaging type communication.

Microservices can also build on top Event-driven architecture, where applications are fully decoupled from each other and communicate via asynchronous events or messages. An event can be emitted by a given service or a system and some other service can act on it. Microservices have to cater to various event-driven communication styles, with internal as well as external service boundaries.

A stream is an unbounded set of events that a service processes continuously. The consumer service of a given stream keeps processing that stream and can emit the resulting events based on the stream processing logic.

The business capabilities of your microservices based applications can be exposed using APIs, events or stream and they can also connect and consume external APIs, events and streams.

Let’s delve deeply into each of these areas and see how we can leverage them when building a microservices architecture.

APIs and API Management

Any business capability that you want to expose to a consumer (internal or external) can be considered an API. Exposing such business capabilities in a way that you can create, manage, secure, analyze, and scale them, is known as API management . By using API management solutions, you can enable policy and key validation, service versioning, quota management, primitive transformations, authorization and access control, observability, self-service capabilities, ratings, and so on, for your microservices.

When it comes to API management, there are several main components that should be part of any API management solution. They are:
  • API Publisher

  • API Developer Portal/Store

  • API Gateway

  • API Analytics/Observability

  • API Monetization

  • API Quality of service (security, throttling, caching, etc.)

It’s important to understand that most of these components are generic and not tightly coupled to the microservices architecture. Therefore, exposing a microservice as an API and exposing an API for a monolithic system is pretty much the same. (There is a certain set of components that you will make decentralized with the introduction of the microservices architecture. We discuss them in the next few sections of this chapter.)

Figure 10-1 illustrates these key API management components and shows how they interact.
../images/461146_1_En_10_Chapter/461146_1_En_10_Fig1_HTML.jpg
Figure 10-1

Components of API management

Prior to going into detail about the responsibilities of each of these components, we can also identify some of the different roles that are associated with API management. They are:
  • API Creator/API Developer: A creator is a person in a technical role who understands the technical aspects of the API (interfaces, documentation, versions, etc.) and uses the API Publisher to provision APIs into the API store. The creator uses the API Store to consult ratings and feedback provided by API users. The creator can add APIs to the store but cannot manage their lifecycle.

  • API Publisher: A publisher manages a set of APIs across the enterprise or business unit and controls the API lifecycle, subscriptions, and monetization aspects. The publisher is also interested in usage patterns of APIs and has access to all API statistics. (In certain cases, the API creator and publisher roles may be combined into a single role.)

  • Subscriber/Application Developer: A subscriber uses the API store to discover APIs, read the documentation and forums, rate/comment on the APIs, subscribe to APIs, obtain access tokens, and invoke APIs.

  • Admin: The API management provider who hosts and manages the API management solution. S/he is responsible for creating user roles in the system, assigning them roles, managing databases, enabling security, etc.

At a high level, the typical execution flow of API management starts at the API Publisher layer. In fact, at that time you should decide which microservices you want to expose as an API. The created APIs are pushed into both the developer portal (the API Store) and the API gateway. Consumers discover APIs from the API Store and they can find all the details required to consume those. When a consumer invokes an API, it directly comes to the API gateway. The gateway is responsible for doing QoS validations (security token validation, throttling, etc.).

Now let’s take a closer look at each of these components and learn about their responsibilities.

API Publisher/API Lifecycle Manager

When you develop microservices, you design them around business capabilities. You may also integrate multiple microservices and form a composition to build them. If you need to expose this capability as a managed capability to the consumers, you will have to create an API for doing so.

API providers or creators are responsible for designing, developing, publishing, deploying, versioning, governing, monitoring availability, and measuring performance. The API Publisher/Lifecycle Manager component of an API management solution is responsible for this.

The API Publisher or API Lifecycle Manager allows you to develop, document, scale, and version APIs. It also provides API Lifecycle Management-related tasks, such as publishing an API, monetization, analyzing statistics, and promoting.

We can identify some of the key steps that are related to each lifecycle state of the API lifecycle manager:
  • Develop phase: Identifying and developing business capabilities that we should expose as managed APIs. This task may involve combining multiple microservices and creating composite functionalities, as well as exposing existing microservices as an API.

  • Publish phase: Once we implement the API’s functionality, then we need to publish that API so that it will be visible on the API developer portal/store. We also associate SLAs (Service Level Agreements) and other QoS (Quality of Service) related (security, throttling) functions to the APIs that we publish.

  • Manage phase: API versioning strategy that manages lifecycle states of an API.

  • Observability phase: When APIs are consumed by the consumers, all the data related to metrics, tracing, and logging are captured by the API gateway component. The API providers should use this data to enhance, change, or monetize their API consumption.

API Gateway

When you publish an API from the API Publisher, the API definition is pushed into the API gateway component. API gateway secures, protects, manages, and scales API calls. All the requests that the API consumers send are intercepted by the API gateway. It applies policies such as throttling and security, using handlers, publishes data for API observability and other API governance tasks. Also, in certain cases, we may implement composition of multiple business functionalities at the API gateway level. However, you need to be cautious about what type of compositions you do at the API gateway level and must avoid the monolithic gateway antipattern discussed in Chapter 7, “Integrating Microservices”.

Note

We discussed the Monolithic API Gateway anti-pattern in Chapter 7, where you develop certain microservices composition at a monolithic gateway level. (Refer to the section entitled “Monolithic API Gateway for Integrating Microservices” in Chapter 7.)

The best approach to avoid this is to create a composite service on top of the microservices that you want to integrate and then expose that at the API gateway. If you want to do compositions at the API gateway, your API gateway needs to have the ability to function as a micro-gateway, in which you will have independent runtimes for each and every API that you deploy at the API gateway.

Most of the API management solution vendors often call their entire solution an API gateway. You should keep in mind that all the other functionalities of the other components may get baked into a single solution.

API Micro-Gateway

Most of the API gateways are initially built as monolithic runtimes. However, with the advent of the microservices architecture, most API management solutions now offer micro-gateway capability too. The key idea behind a micro-gateway is that we develop the APIs and deploy them independently on a container-native gateway runtime, which is managed/governed by a centralized API publisher/lifecycle manager.

Note

We will further analyze how you can morph your entire microservices architecture around the API micro-gateway concept when we discuss the microservice reference architecture with APIs, streams, and events.

API Store/Developer Portal

When API providers publish APIs through an API Publisher, those APIs are pushed into the corresponding API Store or developer portal. API developers self-service, discover, evaluate, subscribe to, and use secured, protected, authenticated APIs via the API Store. Let’s look at some of the lifecycle activities related to an API Store.
  • Discover phase: Find out the APIs that match the API developer’s business capability.

  • Explore phase: View ratings and comments for the API, read documentation, and try out some of the capabilities.

  • Subscribe phase: Register an application and subscribe to APIs, obtain the required security tokens, etc., to invoke the API and subscribe to notifications about API lifecycle changes.

  • Evaluate phase: Once we start consuming an API, we can rate, comment, and give feedback on it.

API Analytics/Observability

API analytics or observability is a critical factor from both the technical and business perspectives. Therefore, API management solutions provide various API analytics capabilities out of the box. This includes metrics on API invocation, API subscribers, top APIs, top developers, slow/fast APIs, API invocation errors, trending APIs, and so on. Also, the ability to trace the API traffic is a critical factor for troubleshooting and identifying bottlenecks. It is also required to have conventional runtime monitoring capabilities and logging. Some other solutions, such API monetization, are built on top of the API analytic data.

API QoS

API Quality of Service (QoS) has multiple perspectives such as security, caching, throttling, and other SLAs (Service Level Agreements). We have two dedicated chapters (Chapter 11, “Microservices Security Fundamentals” and Chapter 12, “Securing Microservices”) covering microservices security fundamentals and we cover API security as part of them. Other QoS aspects, such as caching, throttling, etc. are pretty straightforward to implement with any API management solutions (and they have no special notion in the context of a microservice). Most of the QoS-related enforcements are done at the API gateway level and offload the actual decision making (e.g., security token validation) to an external entity.

API Monetization

APIs are all about your business capabilities and you can generate revenue by exposing them to your customers/partners. API management solutions provide such capabilities out-of-the-box to build a monetary ecosystem around your API management solution.

API Definition with OpenAPI

The key idea of designing an API for a microservice is to hide the implementation details and only expose the interface that addresses a specific business functionality. The OpenAPI specification (OAS), which is formerly known as Swagger, defines a standard programming language-agnostic interface description for REST APIs. It allows both humans and computers to discover and understand the capabilities of a service without requiring access to source code, additional documentation, or inspection of network traffic.

OpenAPI documents describe an API’s services and are represented in either YAML or JSON formats. These documents may be produced and served statically or be generated dynamically from an application.

You can either start by designing the API first (contract first) and then implement the API (may be using code-generation plugins) or you can first implement the API and derive the OpenAPI definition for your service. However, it’s important to keep in mind that OpenAPI is not intended to cover all possible styles of RESTful service design. You can learn about building an OpenAPI-based API definition by referring to OpenAPI samples1.

A Query Language for Your APIs: GraphQL

As discussed in Chapter 3, “Inter-Service Communication,” GraphQL provides a query language for APIs, which are not necessarily based on the REST architecture. We can still implement API management on top of GraphQL-based services and expose them as managed APIs. An API based on GraphQL can be more powerful than a conventional RESTful API, as it provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

API Management and Service Mesh

API gateways/management solutions and service mesh have similar characteristics, which confuses some in the community. In order to differentiate an API gateway from a service mesh, let’s take a closer look at the key characteristics of both. It’s important to understand the users who interact with the management of API gateways and service mesh.
  • API management: The users who interact with the API management are creating and managing business functionalities that they want to expose as APIs.

  • Service Mesh management : The users interact with the service mesh are primarily responsible for managing the non-business logic aspects of the communication between microservices. More or less, they manage the inter-service communication infrastructure of the services.

With this distinction, Figure 10-2 shows how you can use API management along with a service mesh.
../images/461146_1_En_10_Chapter/461146_1_En_10_Fig2_HTML.jpg
Figure 10-2

Service-to-service communication with service mesh and the API gateway

The API/edge services that we develop at the API gateway layer serve a specific business functionality. They call the downstream microservices and may contain some business logic that creates compositions/mashups of multiple services. API services also need to call the downstream services in a resilient manner and apply various stability patterns, such as circuit breakers, timeouts, and load balancing/failover. They can offload such functionalities to the service mesh. Therefore, there will be a service mesh sidecar proxy running alongside each API service. (Although most of the API gateway solutions out there have these features built in, they can still offload such functionalities to the service mesh.) Since the service mesh is the network communication infrastructure, and it allows you to decouple and offload most of the application network functions from your service code, you will have a separate control plane to manage such capabilities. There can be certain overlapping features such as observability of a given API service, which is available from both service mesh and API management observability capabilities. We can still keep them as two different things, as the API management layer is designed for business capabilities, while the service mesh layer is designed for non-business logic inter-service communication requirements. Another important difference is that the API management layer only manages your API services, while the service mesh control plane manages all your service instances.

Note

There are some overlapping features of API management and service mesh, but it’s important to understand that these two concepts serve fundamentally different requirements.

There are some API management solutions that support both API management and service mesh management from the same layer/component. For example, Apigee and Istio support a similar architecture pattern. With Apigee support for Istio integration, the user can expose one or more services from an Istio mesh as APIs by adding API management capabilities via Istio’s native configuration mechanism. Apigee APIM publishes the API policies etc. via the Istio mixer and application of such policies are done at each sidecar. With this approach, we no longer use the API micro gateways but everything is offloaded to sidecar proxies. API token validation, throttling can be managed via APIM UI. This pattern is relatively new and yet to be battle-tested with real-world production use cases.

Implementing API Management

Implementation of comprehensive API management for your microservices requires catering all the API management aspects that we discussed earlier. There are quite a few solutions, which have drastically cut down the API management features and promote them as an API gateway for microservices. You need to be cautious when selecting an API management solution and make sure you can facilitate all your API management requirements. Also, if you have fully embraced a container-native architecture, the components such as API gateway must be container-native too (i.e., they must support a micro-gateway architecture).

There are quite a few API management solutions out there, such as Apigee, WSO2 API Manager, Kong, MuleSoft, etc. We don’t focus on comparing and contrasting them or recommending a specific solution. We want to give full freedom to the readers to evaluate them and select the most suitable technology. You can find couple of API Management use cases built with such API Management solutions in the samples of chapter 10.

Events

Event-driven architecture (EDA) is a widely used architectural paradigm in software applications in which a given application executes some form of code/logic in response to a one or more event notifications. EDA makes applications/services more autonomous than the client-server architecture, where the party that sends the notification waits or depends on the consumer who consumes the event.

In the context of microservices, we already discussed multiple forms of EDA under the asynchronous communication style (Chapter 2, “Designing Microservices”) and reactive compositions/choreography (Chapter 7). Basically, we can design microservices so that they operate in a full event-driven model and asynchronous message passing allows them to be more autonomous. In this chapter, we explore some of the commonly used event-driven patterns in a microservices architecture.

Event Notifications

Event notification is a common form of EDA where a service sends events to notify other services of a change in its domain. Often the event receiver must have the autonomy to carry out the task, if it wishes to do so. An event needs not carry much data on it; often a reference to where the updated information can be retrieved is sufficient.

For example, as shown in Figure 10-3, suppose we have two microservices, called Customer and Shipping. When there is a change in customer information, such as a customer’s address, we can send an event notification to the Shipping service. The event itself may not have all the details of the change, but includes a reference to where the information related to the change can be obtained. As discussed in Chapter 3, the asynchronous event-based communication can be used to realize such scenarios; we can use queue-based communication or topic-based communication to do this.
../images/461146_1_En_10_Chapter/461146_1_En_10_Fig3_HTML.jpg
Figure 10-3

Event notifications

Obviously, most of the message/event broker solutions can be used as the backbone to implement this pattern and Kafka, RabbitMQ, and ActiveMQ are most commonly used in this domain.

It is an anti-pattern to have logic flow that runs as part of event notifications. For example, if your event publisher expects the receivers to do a certain tasks upcon the receipt of your event. then there is a logic flow between the event publisher and receiver. Some of the mere theoretical microservices books and other resources suggest that every integration/composition of microservices must be done using asynchronous event-driven communication. That literally means having logic flows across your microservices that run via event notifications.

Having these kinds of logic flows is not a practical approach because they are extremely hard to manage and troubleshoot. Maybe the only way that you can derive such a logic flow is via observability (tracing). Therefore, you need to be cautious when applying an event-notification pattern to a scenario where you need to pass commands (you expect the receiver would do a definite task upon the receipt of your event).

Event-Carried State Transfer

This is a subtle variation of the event notification pattern. When an event is trigged, the subscribers are notified with events that contain details of the data that changed. So, the recipient services don’t need to access or refer to any other systems or services. The data is already being received as part of the event. Figure 10-4 shows the same scenario that we discussed in the previous section, which is now modified with an event-carried state transfer.
../images/461146_1_En_10_Chapter/461146_1_En_10_Fig4_HTML.jpg
Figure 10-4

Event-carried state transfer

One of the possible downsides of this approach is the duplication of data across multiple services, because all the subscribers will receive the same data. The implementation technology can be similar to event notifications. On the flip side, there is also decreased network traffic, because in this approach, the shipping service would not need to make a request to the customer service to get the updated address.

Event Sourcing

By using asynchronous messaging techniques, we can persist each state-changing event of an entity as a sequence of events. All such events are stored in an event bus or event log and subscribers can derive the state of that entity by processing the sequence of events that has taken place on that entity. For example, as shown in Figure 10-5, the Order Processing service publishes the changes taken place on the Order entity as events. The state-changing events such as order created, updated, paid, shipped, etc. are published to the event bus. With event sourcing, since we have all the state changing events in the event log, multiple consumers can materialize different view of the same data and those consumers can discard the application state completely and rebuild it by re-running the events from the event log on an empty application. Also, we can determine the application state at any point in time as the events are recorded sequentially. If we need to replay the events executed previously (maybe with some modifications to those events), we can also do that using the event log.
../images/461146_1_En_10_Chapter/461146_1_En_10_Fig5_HTML.jpg
Figure 10-5

Event sourcing

The subscriber applications and services can recreate the status of an order by just replaying the events that are taking place on an order. For example, it can retrieve all the events related to order 11234 and derive the current state of the order.

Command Query Responsibility Segregation (CQRS)

Most of the conventional services or applications are developed with the assumption that we create new records, read records, update existing records, and delete records when we’re done with them. These are known as CRUD (Create, Read, Update, and Delete) operations and all these operations are executed on top of a common model. This approach is known as the CRUD model.

However, with the microservices and modern sophisticated enterprise requirements having a common data model for all, such operations are not always feasible. For example, suppose that you have two functionalities of a given service, one to search and read records from the table and the other one to update records in the table. In most cases, these two functionalities are drastically different and using a common data model often complicates the implementation. In such cases, we can split the common data model into a query model and a command model. This is the fundamental concept behind CQRS.

In CQRS (see Figure 10-6), the query model is primarily used for reading data from the datastore, while the command model is used for managing records in the datastore.

These models may operate on the same database but often have dedicated databases with significant advantages. If we assume that we use two dedicated databases for each model, then we need some sort of event-driven messaging mechanism to keep the data in sync. In most cases, eventual consistency (we discuss this in detail in Chapter 5) is sufficient for CQRS scenarios, hence the event-driven messaging techniques that we discussed earlier can be used to build CQRS.
../images/461146_1_En_10_Chapter/461146_1_En_10_Fig6_HTML.jpg
Figure 10-6

CQRS involves splitting the data model into two and operating them on top of dedicated databases, which are eventually consistent via events

In the context of microservices, we can consider that each query and command model are part of two different microservices. Since they have dedicated databases and well-defined functionalities, they are adhering to most of the microservice data management techniques. The complete decoupling of query and command model allows us to use two completely different persistent layers (databases) for command and query services. For example, we can use a database that is optimized for reads in the query model while we use a write-optimized database for command model. While CQRS has several advantages, such as independent scaling and management of read and write components of your application, we should use it when it is absolutely necessary to have the separation between the command and query models, because it comes with added complexity related to synchronizing the same data across multiple datastores/caches. For most commons use cases, the CRUD model fits elegantly.

Streams

A stream is a sequence of events/data elements made available over time. A series of events over time is quite common in modern enterprise applications, where continuous streams are generated with regard to many use cases, such as financial trading systems, weather data, traffic information, etc. The seams between the event-driven architecture and streams are pretty hard to determine, if you don’t delve deep into the concept of stream processing.

Stream Processing

The software components that receive and send data streams and execute the business logic are called stream processors. Unlike conventional event-driven architecture, the processing logic of a stream is written against not one event but across multiple.

In the context of microservices, some of the input to your microservice can come from streams or microservices, which have to publish to a given stream. Therefore, the ability to integrate stream processing along with your service is a common requirement.

Programmatic Stream Processing

Stream processing can be done by writing code to process events sequentially from a source event stream. As shown in Figure 10-7, an actor or agent that accepts an event, processes the event and produces new events. A stream processor allows you to write logic for each actor, which takes care of most of the heavy lifting tasks such as collecting data, delivering to each actor, ordering, results collection, scaling, and error handling.
../images/461146_1_En_10_Chapter/461146_1_En_10_Fig7_HTML.jpg
Figure 10-7

Stream processing with code

There are quite a few stream processor solutions out there, including Apache Storm2, Apache Flink3, and Kafka Streams4, and they are based on a coding approach to stream processing.

Streaming SQL

Rather writing code to do stream processing, we can use SQL-like syntax to process streams. This is known as streaming SQL. With streaming SQL, you don’t need to write code to build your stream processing use cases. Rather most of the essential functionalities can be abstracted into a streaming SQL engine.

Therefore, streaming SQL enables us to manipulate streaming data declaratively without having to write code. There are many stream-processing solutions, such as Apache Flink, Kafka (KSQL), that now offer streaming SQL support.

A Microservices Architecture with APIs, Events, and Streams

A pragmatic microservices architecture is often built on top of APIs, events, and streams. We discussed in Chapter 6, “Microservices Governance,” how to organize services around core services, integration services, and API services. You can extend the same model to support events and streams. In Figure 10-8, you can observe that we used API services to expose business functionalities to the consumers and those API services are centrally managed by the API management component. API services are deployed on micro-gateway nodes, which means each API service has an independent runtime but is controlled by the central API management layer.
../images/461146_1_En_10_Chapter/461146_1_En_10_Fig8_HTML.jpg
Figure 10-8

Microservices reference architecture with APIs, events, and streams

Microservices are integrated using active/orchestration and reactive (choreography) patterns and the event bus is used as the messaging backbone.

Microservices can receive events from external event sources and each consumer service has the business logic of processing those events. Similarly, stream-processing logic is also part of the services that consume the source streams. They can either implement using streaming SQL runtimes or programmatically process the event streams. Unlike API management, the consumption of events and streams is managed when services publish events to the consumers. If required, the events and stream-sinking services can be managed via an event and stream-management layer when we sink events or streams. Similar to the API management ecosystem, we can build an event and stream management layer, so that we can fully manage the event sinking or stream sinking (publishing) channels of our microservices implementation.

Summary

In this chapter, you learned about how to expose your microservices as managed APIs. The API management layer is the primary entry point to your microservices consumers where you expose business functionalities as APIs. We discussed the key components of an API management solution—API Gateway, API Store/Developer portal, API Publisher/Lifecycle Manager, API Analytics/Observability, and API Security solutions. We identified the differences between the API Gateway and service mesh proxy, and we discussed how API management and service mesh can coexist.

An event-driven architecture is quite useful for making services autonomous. We discussed the commonly used pattern for an event-driven architecture—event notification, event state transfer, event sourcing, and CQRS. Most of the event-driven communication patterns are implemented with the technologies that are used in messaging queuing and publisher-subscriber messaging infrastructures.

Streams are a special case of an event-driven architecture, where a sequence of events are processed over time. Stream processing is often done using a dedicated query language called streaming SQL, while some solutions are based on a pure coding approach to process streams.

APIs, events, and streams act as the front door to your enterprise’s microservices implementation. You can extend the microservices reference architecture with APIs, events, and streams by connecting the external systems with the internal microservices.

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

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