"Editor's note" This is the third article that uses a microservices architecture to create its own application series. The first article introduces the microservices architecture pattern, compares it to the singleton pattern, and discusses the pros and cons of using a microservices architecture. The second article describes how to use the API gateway approach to communicate between application clients using MicroServices architecture. In this article, we will discuss how system services communicate with each other.
Brief introduction
In single-use applications, calls between modules are implemented by means of programming language-level methods or functions. But a micro-service-based distributed application is run on more than one machine. In general, each service instance is a process. Thus, as shown, the interactions between services must be implemented through interprocess communication (IPC).
We'll cover the IPC technology in detail later, so let's look at the design-related issues first.
Interactive mode
When you select IPC for a service, you first need to consider how the services interact with each other. There are a lot of interaction patterns between the client and the server, and we can categorize them from two dimensions. The first dimension is one-to-one or one-to-many:
? Single-to-one: Each client request has a service instance to respond to.
? One -to-many : Each client request has multiple service instances to respond to
The second dimension is these interactive synchronizations or asynchronous:
? Synchronous mode: Client requests require an immediate response from the server and may even be blocked by waiting.
? Asynchronous mode: The client request does not block the process, and the server response can be non-instantaneous.
The following table shows the different interaction modes:
one-to-two interaction modes are available in the following ways:
? Request/Response: A client initiates a request to the server and waits for a response. The client expects this response to arrive immediately. In a thread-based application, the wait process can cause a thread to block.
notification (that is, a one-way request): A client request is sent to the server, but the service side is not expected to respond.
request/Asynchronous response: The client sends the request to the server side, and the server asynchronously responds to the request. The client does not block, and the default response is designed to not arrive immediately.
one-to-many interaction modes are available in the following ways:
? Publish/Async Response mode: The client publishes the request message, and then waits for a response from the service that is interested in sending it back.
Each service is a combination of these patterns, and for some services, an IPC mechanism is sufficient , while for other services, a combination of IPC mechanisms is required. Shows how the service communicates between services in a taxi service request.
 
Service communication in is using notifications, request/response, publish/subscribe, and so on. For example, the passenger sends a notification via mobile to the trip management Service, wishing to apply for a rental service. The trip Management service sends a request/response message to the passenger service to confirm that the passenger account is valid. This itinerary is then created and notified by the Publish/subscribe interaction mode, including the dispatch service for locating available drivers.
Now that we understand the interaction pattern, let's look at how to define the API.
Defining the API
An API is a contract between a server and a client. Regardless of the IPC mechanism chosen, it is important to use an interactive definition language (IDL) to precisely define the API for a service. There are even some good reasons to define the service using the API first method (Api-first approach). Before development, you need to define the interface of the service and discuss the confirmation with the client developer in detail. Such discussions and design will significantly mention the usability and satisfaction of the API.
In the latter part of this article you will see that the API definition essentially relies on which IPC to choose. If you use the message mechanism, the API is composed of the message channel and the message type, and if you choose to use the HTTP mechanism, the API consists of a URL and a request and response format. IDL will be described in detail later.
Evolution of the API
The service-side API is constantly changing. In a single-use application, the API is often modified directly and then updated to all callers. In a microservices-based architecture application, this is difficult, and even if only one service uses the API, it is not possible to force users to synchronize updates with the server. In addition, developers may try to deploy a new version of the service, this time, the old and new services will be running colleagues. You need to know how to deal with these problems.
How you handle API changes depends on how big these changes are. Some of the changes are minor and can be compatible with previous versions. For example, you might just add a property to a request and response. It is important to follow the robustness principle when designing the client and service side. Clients using legacy APIs should also be able to work with the new version. The server still provides a default response value, and the client ignores a response that is not required by this version. Using IPC mechanisms and message formats is useful for API evolution.
However, there are times when the API requires large-scale changes and may not be compatible with previous versions. Since you cannot force all clients to upgrade immediately, services that support older versions of clients will need to run for a while. If you are using an IPC based on an HTTP-based mechanism, such as rest, a solution is to embed the version number in the URL. Each service may handle multiple versions of the API at the same time. Alternatively, you can deploy multiple instances, each of which is responsible for processing one version of the request.
Processing partial failure
In the previous article on API Gateway, we learned that partial failures in distributed systems were a common problem. Because both the client and the server are independent processes, one server may stop the service due to failure or maintenance, or the service will stop or react slowly due to overloading.
Consider some of the failed scenarios described in this article. Assuming that the referral service is unable to respond to the request, the client will be blocked by waiting for a response, which will not only give the customer a bad experience, but also consume a lot of resources in many applications, such as threads, so that the thread resources are consumed by the increasing number of clients waiting to be blocked in response. As shown in the following:
netfilix provides a better solution, specific response measures include:
? circuit Breaker mode (circuit breaker pattern): Records the number of successful and failed requests. If the loss of efficiency exceeds a threshold, triggering a circuit breaker causes subsequent requests to fail immediately. If a large number of requests fail, it may be that the service is unavailable, and the request is meaningless. After an expiration period, the client can retry and, if successful, close the circuit breaker.
netflix Hystrix is an open source library that implements related patterns. If using the JVM, it is recommended to consider using Hystrix. If you use a non-JVM environment, you can use a library of similar functionality.
IPC Technology
There are a lot of different IPC technologies now. Communication between services can use synchronous request/response patterns, such as HTTP-based rest or thrift. Alternatively, you can choose an asynchronous, message-based communication pattern, such as AMQP or stomp. Apart, there are other message formats to choose from, such as JSON and XML, both of which are readable, text-based message formats. Of course, there are also binary formats (more efficient), such as Avro and protocol Buffer. Next we will discuss asynchronous IPC mode and synchronous IPC mode, first of all to look at async.
Asynchronous, message-based communication
When using process communication based on asynchronous exchange messages, a client submits a request by sending a message to the server. If the server needs a reply, another independent message is sent to the client. Because the communication is asynchronous, the client is not blocked by waiting, instead, the client takes it for granted that the response is not received immediately.
A message consists of the head (metadata such as the sender) and the message body. Messages are sent through the channel, and any number of producers can send messages to the channel, and similarly, any number of consumers can receive data from the channel. There are two types of channel, Point-to-point and Publish/subscribe . The point-to-point channel sends the message exactly to a consumer who reads the message from the channel, and the server uses point-to-point to implement the one-to-one interaction pattern mentioned earlier, while the Publish/subscribe message is delivered to all consumers who read the data from the channel, and the server uses the Publish/ Subscribe to the channel to implement the one-to-many interaction pattern mentioned above.
Shows how the taxi software uses publish/subscribe:
The trip management Service creates a trip message within the publish-subscribe channel and notifies the dispatch service that there is a new trip request, the dispatch service discovers an available driver and then writes the driver advice message to the publish-subscribe channel (Driver proposed Message) to notify other services.
There are many message systems to choose from, preferably one that supports multiple programming languages. Some messaging systems support standard protocols, such as AMQP and stomp. Other messaging systems use unique protocols, with a large number of open source messaging systems available, such as RABBITMQ, Apache Kafka, Apache Activemq, and NSQ. They all support some form of message and channel, and are reliable, high-performance and extensible; However, their message models are completely different.
There are many advantages to using the messaging mechanism:
?decoupling the client and server: The client only needs to send the message to the correct channel. The client does not need to know the specific service instance at all, and there is no need for a discovery mechanism to determine the location of the service instance.
?Message Buffering: In a synchronous request/response protocol, such as HTTP, all clients and the server must remain available during the interaction. In message mode, message broker manages all messages written to the channel in a queue until it is processed by the consumer. In other words, the online store can accept customer orders, even if the order system is slow or unavailable, just keep the order message into the queue.
? Elastic Client-Server interaction: The messaging mechanism supports all of the above-mentioned interaction patterns.
?direct inter-process communication: RPC-based mechanism, attempting to wake a remote service looks like waking a local service. However, because of the physical laws and the possibility of partial failure, they are actually very different. The message makes these differences very clear and the developer does not have a problem.
However, the messaging mechanism also has its own drawbacks:
?Additional operational Complexity: The messaging system needs to be installed, configured, and deployed separately. The message broker (proxy) must be highly available or the system reliability will be affected.
?implementation of complexity based on request/response interaction Patterns: The request/Response Interaction mode requires additional work to be done. Each request message must contain a reply channel ID and a correlation ID. The server sends a response message containing the correlation ID to the channel, using the correlation ID to correspond the response to the client making the request. Perhaps this time, it would be easier to use an IPC mechanism that directly supports request/response.
Now that we've learned about the message-based IPC, let's look at the IPC based on the request/response pattern.
synchronous, request/response-based IPC
When using a synchronous, request/response based IPC mechanism, the client sends a request to the server, the server processes the request, and returns the response. Some clients can be blocked by waiting for a server response, while others may use asynchronous, event-driven client-side code (the future or Rx observable package). However, unlike using message mechanisms, clients need to respond in a timely manner. There are many optional protocols in this pattern, but the most common two protocols are rest and thrift. First of all, let's look at rest.
REST
is now popular with restful-style APIs. Rest is based on the HTTP protocol. In addition, a more important concept to understand is that rest is a resource that typically represents a business object, such as a customer or a product, or a group of business objects. Rest uses the HTTP syntax protocol to modify resources, which are typically implemented via URLs. For example, a GET request returns simple information about a resource, and the response format is usually XML or JSON object format. A POST request creates a new resource, and a put request updates a resource. Here is the reference to the rest of the father Roy Fielding said:
 
When you
need a holistic system that values module interaction extensibility, interface generalization, component deployment independence, and reduced latency, providing security and encapsulation, rest can provide a set of architectures that meet your needs.
Shows how the taxi software uses rest.
passenger via mobile end to trip management Service /trips
Resource submitted a POST request. After the trip management service receives the request, a GET request is sent to the passenger management Service to obtain the passenger information. Once the passenger information is confirmed, a trip is created and a 201 (translator note: status code) response is returned to the mobile side.
Many developers say their HTTP-based API is restful. But, as fielding in his blog, these APIs may not all be restful. Leonard Richardson defines a maturity model for rest with the following 4 levels (from IBM):
- The first (level 0) Web service only uses HTTP as a transport, and is actually a specific form of a remote method call (RPC). Both SOAP and Xml-rpc belong to this class.
- The second (Level 1) Web service introduces the concept of resources. Each resource has a corresponding identifier and expression.
- The third level of the Web service, which uses different HTTP methods for different operations, uses HTTP status codes to represent different results. such as the HTTP GET method to get the resource, the HTTP Delete method to delete the resource.
- The fourth tier (Level 3) Web service uses HATEOAS. The link information is included in the expression of the resource. The client can discover the actions that can be performed based on the link.
Using HTTP-based protocols has the following benefits:
? HTTP is very simple and everyone is familiar with it.
? You can use a browser extension (such as postman) or a command line like Curl to test the API.
? Built-in support for request/Response mode communication.
? HTTP is firewall friendly.
? No intermediate agents are required, simplifying the system architecture.
The deficiencies include:
? Only request/Response mode interaction is supported. HTTP notifications can be used, but the server must always send HTTP responses.
? Because the client communicates directly with the server (no proxy or buffer mechanism), it must be online during the interaction.
? The client must know the URL of each service instance. As mentioned in the previous article on API Gateway, this is also an annoying problem. The client must use the service instance discovery mechanism.
The developer community has recently re-discovered the value of the RESTful API interface Definition language. So there are some restful style service frameworks, including Raml and swagger. Some IDL, such as swagger, allows you to define the format of request and response messages. Other, such as Raml, requires the use of additional identifiers, such as JSON Schema. For the description api,idl there is generally a tool to define the client and service-side skeleton interfaces.
Thrift
Apache Thrift is a very interesting alternative to rest. It is a framework that Facebook implements as an efficient, remote service invocation that supports multiple programming languages. Thrift provides a C-style IDL definition API. Use the thrift compiler to generate client and server-side code frameworks. Compilers can generate code in multiple languages, including C + +, Java, Python, PHP, Ruby, Erlang, and node. js.
The thrift interface includes one or more services. A service definition is similar to a Java interface and is a set of methods. The thrift method can return a response, or it can be defined as one-way. The method of returning a value is actually the implementation of the request/response type interaction pattern. The client waits for a response and may throw an exception. The one-way method corresponds to the interaction mode of the notification type, and the server does not return a response.
Thrift supports a variety of message formats: JSON, binary, and compression binary. Binary is more efficient than JSON because binary decoding is faster. For the same reason, compressed binary formats can provide a higher level of compression efficiency. JSON, which is easy to read. Thrift can also be selected between bare TCP and HTTP, and bare TCP looks more efficient than HTTP. However, HTTP is more friendly to firewalls, browsers, and people.
Message format
After we've learned about HTTP and thrift, let's look at the message format problem. If you use the message system or rest, you can choose the message format. Other IPC mechanisms, such as thrift, may only support partial message formats, perhaps only one. Either way, we have to use a cross-language message format, which is very important. Because it means that you will use other languages someday.
There are two types of message formats: text and binary. Examples of text formats include JSON and XML. The advantage of this format is that it is not only readable, but also self-descriptive. In JSON, an object is a set of key-value pairs. Similarly, in XML, attributes are composed of names and values. Consumers can select the elements of interest and ignore the rest. At the same time, small amplitude format modifications can be very container backwards compatible.
The XML document structure is defined by the XML schema. As time progresses, the developer community realizes that JSON also needs a similar mechanism. One option is to use the JSON Schema, either standalone or for example swagger IDL.
The biggest drawback of text-based message formats is that messages become verbose, especially XML. Because the messages are self-describing, each message contains properties and values. Another drawback is the burden of parsing text too much. So, you might want to consider using binary format.
There are many binary formats as well. If you are using thrift RPC, you can use binary thrift. If you choose a message format, the common ones include protocol buffers and Apache Avro. They all provide a typical IDL to define the message schema. One difference is that protocol buffers uses tagged (tag) fields, and Avro consumers need to know the schema to parse the message. Therefore, using the former, the API is easier to evolve. This blog is a good comparison of the thrift, Protocol buffers, Avro three differences.
Summarize
MicroServices must use interprocess communication mechanisms to interact. When designing a service's communication model, you need to consider several issues: how the service interacts, how each service identifies the API, how to upgrade the API, and how to handle partial failures. The microservices architecture has two types of IPC mechanisms that are optional, asynchronous messaging mechanisms, and synchronous request/response mechanisms. In the next article, we will discuss service discovery issues in the microservices architecture.
Source: http://dockone.io/article/549
Micro-service Combat: In-depth micro-service architecture inter-process communication