Original address: http://dockone.io/article/482
"Editor's note" The first article in this series describes the MicroServices architecture model. It discusses the advantages and disadvantages of using microservices, which are the ideal choice for complex applications, in addition to some complex microservices.
When you decide to use the app as a set of microservices, you need to decide how the application client interacts with the microservices. In a monolithic program, there is usually only one set of redundant or load-balanced service delivery points. In the microservices architecture, each microservices exposes a set of fine-grained service delivery points. In this article, we look at how it affects client-to-server communication, and proposes an API gateway approach.
Introduced
Suppose you are developing a native mobile client for an online shopping app. You need to implement a product final page to display product information.
For example, the following figure shows the information you see when you swipe the final page of a product on Amazon's Android client.
Although this is a smartphone app, the final page of this product shows a lot of information. For example, there is not only basic information about the product (name, description, and price), but also the following:
- Number of items in the shopping cart
- Order History
- User reviews
- Low inventory warning
- Courier Options
- A wide range of recommendations, including products that are often purchased with this item, products purchased by other customers who purchase the item, and which products are also viewed by customers who purchase the product.
- Optional shopping options
When using a monolithic application architecture, a mobile client will fetch the data through a rest request (get Api.company.com/productdetails/productid). One load balancer distributes the request to one of several application instances. The app queries the various databases and returns the request to the client.
In contrast, if a microservices architecture is used, the data on the final page will be distributed across different microservices. Some microservices that may be related to the final page data of the product are listed below:
- Shopping Cart Service--The number of items in the shopping cart
- Order Service--order history
- Classification Services-Basic product information such as name, picture, and price
- Comment Service--user reviews
- Inventory Service-Low inventory warning
- Courier Services--Express options, deadlines, cost calculations from different courier APIs
- Recommended Services-Recommended products
We need to decide how mobile clients can access these services. Here are a few ways to see
Client-to-micro service direct communication
Theoretically, a client can initiate a request directly to any of several microservices. Each micro-service will have an external service (HTTPS://SERVICENAME.API.COMPANY.NAME). This URL may be mapped to a microservices load balancer, which forwards the request to a specific node. To search for product details, the mobile side needs to make a request to the micro services mentioned above.
Unfortunately, the scheme has many difficulties and limitations. One problem is that the client's demand does not match the number of fine-grained APIs exposed by each microservices. , the client requires 7 separate requests. In more complex scenarios, more requests may be required. For example, Amazon's product final page requests hundreds of microservices. Although a client can initiate many requests over the LAN, this is not efficient on the public network, which is particularly prominent on the mobile internet. This scenario also causes the client code to be very complex.
Another problem is that the client's protocol to request microservices directly may not be web-friendly. One service may be RPC protocol with thrift, while another service may be using the AMQP message protocol. They are not browse or firewall-friendly, and are best used internally. Applications should use a similar HTTP or websocket protocol outside the firewall.
Another drawback of this scenario is that it is difficult to refactor microservices. Over time, we may need to change the current segmentation scheme for system microservices. For example, we might need to merge two services or split a service into multiple. However, this refactoring is difficult to implement if the client interacts directly with the microservices.
Due to the above three problems, the way the client communicates directly with the server is seldom used in practice.
Using an API Gateway
Generally, a better solution is to use the API gateway approach. API Gateway is a server or a unique node that enters the system. This is similar to the facade pattern in object-oriented design mode. API Gateway encapsulates the architecture of the internal system and provides APIs to individual clients. It may also have other features such as authorization, monitoring, load balancing, caching, request fragmentation and management, static response processing, and so on. Shows an API Gateway that adapts to the current architecture.
API Gateway is responsible for requesting forwarding, compositing, and protocol conversions. All requests from the client go through the API Gateway and then route the requests to the corresponding microservices. API Gateway will often process a request and aggregate the results of multiple services by invoking multiple microservices. It can be transformed between a Web protocol and a non-web-friendly protocol used internally, such as the HTTP protocol and the WebSocket protocol.
API Gateway can provide a custom API to the client. It exposes a coarse-grained API to mobile clients. Take the product final page of this usage scenario as an example. API Gateway provides a service delivery point (/PRODUCTDETAILS?PRODUCTID=XXX) that enables mobile clients to retrieve all the data from a product's final page in a single request. API Gateway processes this request and returns results by invoking multiple services, involving product information, referrals, reviews, and so on.
A good example of API Gateway is the Netfix API gateway. The Netflix streaming service offers hundreds of different microservices, including TVs, set-top boxes, smartphones, gaming systems, tablets, and more. At first, the Netflix view provides an API for all scenarios. However, they found this form not good because it involves a variety of devices and their unique needs. Now they use an API gateway to provide high-tolerance APIs that have code for different types of devices. In fact, an adapter handles a request on average to call 6 to 8 back-end services. Netflix API Gateway processes billions of of requests per day.
Advantages and disadvantages of API Gateway
As you expected, the use of API Gateway is also the pros and cons. One of the biggest benefits of API gateway is encapsulating the application's internal structure. Instead of invoking the specified service, the client interacts directly with the Gatway for a simpler point. API Gateway provides a specific API to each client, which reduces the number of client-to-server traffic and simplifies client-side code.
API Gateway also has some drawbacks. It is a highly available component that must be developed, deployed, and managed. There is also a problem that could be a bottleneck for development. Developers must update the API gateway to provide new service delivery points to support newly exposed microservices. The more lightweight the API gateway must be, the better. Otherwise, the developer will queue up for updating the gateway. However, in addition to these shortcomings, for most applications, the use of API gateway approach is effective.
Implementing an API Gateway
Now that we know the motivations and pros and cons of using API Gateway, here are some things to consider when designing it.
Performance and Scalability
Only a handful of companies need to deal with the size of Netflix, which requires processing billions of of requests per day. However, for most applications, the performance and scalability of the API gateway is also important. Therefore, it makes sense to create an API gateway that supports synchronous, non-blocking I/O. There are already different technologies that can be used to implement an extensible API Gateway. On the JVM, a framework based on NIO technology, such as Netty,vertx,spring reactor or JBoss Undertow, is used. node. JS is a non-JVM popular platform built on Chrome's JavaScript engine. An optional solution is Nginx Plus. NGINX Plus provides a sophisticated, scalable, high-performance Web server and reverse proxy that are easy to deploy, configure, and develop two of times. NGINX Plus manages authorization, privilege control, load balancing, caching, and provides application health checks and monitoring.
Adopting a reactive programming model
For some requests, API gateway can be processed by direct routing requests to the corresponding backend services. For other requests, it needs to call multiple backend services and merge the results for processing. For some requests, such as product final page requests, requests to the backend service are independent of each other. To minimize response time, API Gateway should handle separate requests concurrently. However, there are sometimes dependencies between requests. The API gateway may need to authenticate the request through the authorization service before routing to the backend service. Similarly, in order to obtain the customer's product wish list, we need to obtain the user's information first, and then return the product information on the list. One such API component is the Netflix Video Grid.
Using the traditional synchronous callback method to implement the API merge code will allow you to enter the nightmare of the callback function. This code will be very difficult and difficult to maintain. An elegant solution is implemented using reactive programming patterns. Similar reactions to abstract implementations have Scala's future,java8 of Completablefuture and JavaScript promise. Based on Microsoft. NET platform with reactive Extensions (Rx). Netflix created Rxjava for the JVM environment to use their API Gateway. Similarly, the JavaScript platform is RXJS and can be run on browsers and node. JS platforms. Using a reactive programming approach can help to quickly implement an efficient API gateway code.
Service invocation
A microservices-based application is a distributed system, and the mechanism of inter-thread communication must be adopted. There are two ways to communicate between threads. One is the use of asynchronous mechanisms, message-based methods. Implementations of this type are JMS and AMQP. In addition, for example, Zeromq belongs to the direct communication between services. There is also an inter-thread communication that uses synchronization mechanisms, such as thrift and HTTP. In fact, a system uses both synchronous and asynchronous mechanisms. Because there are many ways to implement it, API Gateway needs to support multiple communication methods.
Service discovery
API Gateway needs to know the IP and port of every micro-service. In traditional applications, you might hardcode these addresses, but in today's cloud-based microservices applications, this is a simple question. Basic services typically use static addresses, which can be specified using operating system environment variables. However, it is not that easy to probe the address of the application service. App services typically dynamically assign addresses and ports. Similarly, the instances of the service will change dynamically due to extensions or upgrades. As a result, API gateway requires a system-based service discovery mechanism that either uses server-side discovery or client discovery. This section will be described in more detail in a subsequent article. If the client Discovery service is used, the API gateway has to query the service registry, the database of the MicroServices instance address.
Processing partial failure
Another problem that needs to be considered in implementing the API gateway is partial failure. This problem occurs in distributed systems where a service invokes another service timeout or is not available. API gateway should not be blocked and wait indefinitely for downstream service status. However, how to handle this failure depends on the specific scenario and the specific service. For example, if the Referral Service module is not responding on the Product Details page, then API Gateway should return the rest of the information to the user, as this information is also useful. The recommended section can return empty, or it can return a fixed top of 10 to the user. However, if the product information service is unresponsive, then API Gateway should return an error to the client.
The API gateway should be able to return the cache when the cache is valid. For example, because product price changes are infrequent, the API gateway should return the values in the cache when the price service is not available. Such data can be cached by the API gateway itself, or by external caches such as Redis or memcached. By returning cached data or default data, API gateway ensures that system errors do not affect the user experience.
Netflix Hystrix is a very useful library for implementing remote service invocation code. Hystrix records those calls that exceed the pre-set limit values. It implements the circuit break mode, which allows the client to stop in an endless wait for unresponsive services. If the error rate of a service exceeds the preset value, Hystrix interrupts the service and all requests are immediately invalidated for a period of time. Hystrix can define a fallback action for request failure, such as reading the cache or returning a default value. If you are using the JVM, you should consider using Hystrix. If you are using a non-JVM environment, you should consider a library with similar functionality.
Summarize
For most microservices-based applications, implementing an API gateway would make sense, and it would be like a service delivery point into the system. The API Gateway is responsible for request forwarding, request compositing, and protocol conversions. It is provided to the application client with a custom API. API Gateway can mask back-end service errors by returning cache or default values. In the next article in this series, we will discuss communication issues between services.
Original link: Building microservices:using an API Gateway (translator: Chen Jie; revision: 杨峰)
Micro-service Combat (ii): Using the API gateway--ext.