In microservices architecture each service exposes APIs through which interactions with the service is possible. Clients of application should not be aware about the existence of services or make requests to them directly for various reasons such as the apps internal architecture can change .
Clients should not invoke service APIs directly as
- Apps internal architecture could change. (eg how an app is decomposed into services) .Clients should not have to worry about this.
- Mobile client apps may not be frequently updated by users, hence older apis need to be supported. If services fine grained apis are directly exposed , it is harder to evolve /modify the APIs. Note that thirdy party apps need more stable apis as forcing third party clients to upgrade would be very difficult.
- Fine grained service APIs will result in too many calls from mobile clients. Also the data required to handle a request may be spread across multiple services. Note that internet speeds are lesser than LAN and mobile network speeds lesser than internet speeds.Also the client code becomes complex as the client is performing api composition. Also too many api calls from mobile client will drain a mobile device battery faster.
- Services can use IPC mechanisms to communicate with each other which the client does not understand . Clients which run outside firewall typically use http , websocket . internally service may use different protocols (eg messaging protocols).
- Diffrent kind of clients (javascript spa apps running on browser,mobile app, desktop browser based ui, third party apps)will face one or more of the above problems to different extent, for example desktop browser based ui will have much greater problem with api composition as they tend to show more data compile to mobile userinterface and may have more bandwidth access . javascript apps running on browser are easier to modify along with the api change unlike mobile apps. When apps belong to third party the need to provide stable APIs is more.
Note that traditional web applications (which respond with html pages to http reqeusts from browser) have access to services over lan, and are developed in close collbaration with back end teams so could access services directly and performing functionalities of api gateway like api composition.
API gateway pattern
API gateway becomes the single entry point for api requests to application from the outside world and solves the core issues listed above . API gateway is similar to facade pattern of oops. The key functionalities of api gateway are
- Request routing (most reverse proxy also have this capability)
- api gatway routs the reqeust to appropriate service based on
- http method of reqeust (this is especially useful in cqrs pattern where writes and reads must go to different services)
- path of request eg /base/service1 , /base/service2 can be routed to different services.
- api gatway routs the reqeust to appropriate service based on
- API composition
- coarse grained api are provided by api gateway via api composition.custom code is required here.
- Protocol translation
- Synchronous rest calls can be handled via messaging driven microservices.
- Reactive interactive gateways are able to convert HTTP calls to message broker events.RIG can also wait for a corresponding response event from kafka topic. An interaction may look like this.
- The third-party client sends an HTTP request to RIG
- RIG produces a request event to a Kafka topic, adding a correlation ID representing the client connection
- A service picks up the request and emits a "processed" event, retaining RIG's correlation ID
- RIG listens on a Kafka topic for events that have a correlation ID set, picks up the "processed" event and sends it as a response down the still-open HTTP connection to the waiting third-party client.
- Note that the response will have to go back to correct instance of RIG .(where potentially a thread may be waiting)
- Read more here . https://accenture.github.io/reactive-interaction-gateway/docs/architecture.html
- Reactive interactive gateways are able to convert HTTP calls to message broker events.RIG can also wait for a corresponding response event from kafka topic. An interaction may look like this.
- Edge functions : Several edge functions if executed at api gateway layer will reduce the headache of handling these functions by a separate edge service and reduces a hop and results in fewer moving parts.
- Authentication
- Authorization
- Rate limiting
- Caching
- Aside from providing core functionality of request routing and api compostion,API Gateway also provide edge services like api caching. For instance amazon api gateway can be configured to cache rest end point responses for a specified time to live (TTL ) period. Note that while browsers can also cache api response, the response cached by API Gateway is server side caching once the api response is there in cache , it can be used by different client browsers. Typically useful for api which are commonly used across users, eg offer of sale.
- Metrics collection
- Request logging
More about API Gateway
- Performance and scalability. API Gateway needs to be highly avaliable and scalable.
- There is choice of blocking vs non blocking architecture.
- API Gateways built on non bloking architecture are more scalable. In the blocking IO architecture each request is typically handled by a single thread (thread per request pattern) where in thread is typically just waiting for things to happen (eg db calls to complete) but in this model the concurrent requests which can be handled becomes an issue as threads occupy a lot of memory (espcially in java). Non blocking architecture such as nodejs ,Netty , Vertx , spring reactor, jboss undertow are more scalable. Note that non blocking architecture should be non blocking all the way including when process accepts inbound requests or makes outbound requests .Note that while nodejs apps can be completely non blocking all the way including outbound reletional database calls, this is not possible if java process makes outbound database calls as reactive relational jdbc drivers (which do not block) are robust yet . Note that the benefits of non blocking architecture are more visible when process has io intensive logic, not cpu intensive logic.
- Programming style/paradigm
- API gateway code will often have api compostion code. Some api calls need to be sequential but many of the api calls can be done concurrently for better speed . Reactive style of coding is a good approach for api composition. Note that when you are using a non blocking architecture (for instance nodejs) you do not necessarily need a reactive style of programming. Callbacks/promises/asyc await can be used). To code in reactive style RxJs (reactive extension for javascript) can be used .
- Imperative code typically needs a thread per request . Reactive programming promotes event driven,non blocking approach to data processing . Reactive programming involves modeling data and events as observable data streams and implementing data processing routines to react to the changes in those streams. Note that reactive programming only promotes non blocking behaviour, it does not guratee it. Full benefits of reactive programming come into effect only if the entire stack is non blocking and if all participating components (application code, runtime container, integrations) respect deferred execution, non-blocking APIs.The point being that reactive is a programming style and does not gurantee non blocking behaviour. Hence it’s possible to bring blocking components to an application that is written in a functional-reactive style but the net result will be that the scalability and stability effects, the actual expected benefits, decrease. In the worst case, there’s little or no difference in runtime behavior. For instance java applications talk to RDMBS via JDBC and JDBC is blocking in nature. There are efforts to create reactive relational database connectivity which is non blocking. Read more here https://spring.io/blog/2018/12/07/reactive-programming-and-relational-databases.
- Non blocking libraries for databases, message brokers etc are also called reactive libraries eg
- Spring Data Mongo has support for reactive access through the MongoDB Reactive Streams Java Driver.
- Java can use reactive abstractions like
- java 8 completeable futures
- RxJava
- There is choice of blocking vs non blocking architecture.