A high performance message forwarding architecture

zhaozj2021-02-08  263

Turn a wake-up angle AUTOASM.BLOG-CITY.COM

A high performance message forwarding architecture

Alex Dou

Autoasm@yahoo.com

Abstract This article describes a message forwarding architecture based on multi-channel selection and reverse route, which has a greater throughput, better scalability and smaller response delay.

Key words distributed messages forwarding high performance software architecture

1. Message Forwarding Application and Challenge

Various types of messaging agents are used in the Internet business or the core switching system of the telecommunications system. As shown below

Figure 1.1

The above figure shows a typical instant messaging service architecture. Since both PC1 and PC2 are located after the firewall with address conversion function, these two clients cannot directly establish a connection. A simple solution is to use the message server forwarding. First, both PC1 and PC2 are established with the message server and remain connected. PC1 first sends a message to the message server, then the message server forwards the message to the PC2 according to the destination address information in the message.

In addition to instant messaging services, various gateways and network game servers in the telecommunication switching system have a demand for forwarding a large number of messages.

Realizing messaging is very simple without considering scale scalability. The following pseudo codes describe a simplest implementation.

// Get Request

Request Req = conn1.getRequest ();

// Search Route Table for Destination Connection

Connection conn2 = routetable.getConnbyAddr (Req.getDestination ());

// forward request

Conn2.send (REQ);

// ... Wait for Response

Response respon = conn2.getResponse ();

// forward response

Conn1.send (resp);

// ok

The above code describes the most basic forwarding logic.

First, the request message is obtained from the requesting party, and then the connection to the destination address is obtained from the routing table according to the requesting address, and then forward the message to the destination connection. After the request forwarding is completed, you will need to wait for a response. After receiving the response, then forward the answer to the original request one.

Although this code can work correctly, this simple design is difficult to handle massive messages forwarding business.

In the above code, the time consumption of the response operation is uncertain. The response may be received within 0.5 seconds, but it may not be received for 15 seconds, even simply timeout. Let a valuable handling task (responsible for implementing forwarding logic daemon or thread) White is a waste here. In the process of waiting for timeout, the task queue may have been covered with new forwarding requests, which correspond to a number of anxiously waiting for users.

There is no reason to let the user have anxious to prevent the task to sleep because of waiting for a response (in the implementation of the majority platform, the synchronized IO will make the process or thread where the caller is located. Hang up until the data or timeout event occurs. Therefore, we need a design that makes it more busy to handle the task, and the new design will ensure that you don't have to delay other forwarding for a slow forward task.

2. Scalable architecture

Fish and bear's paw are not available.

This simple dialectical law is equally applicable in the information age. The forwarding architecture described herein is more complicated while obtaining scalability.

The following figure shows the relationship between the main participants in the forwarding architecture.

Figure 2.1

The REQUEST and RESPONSE classes represent abstract requests and answers messages, respectively. Each Request object has an ID attribute that each Response object has a responseFor property. If the Response object's responseFor property is the same as the Id properties of the Request object, the answer is a response to the Request object. The CONNECTION class represents an abstract connection. The Selector class is a multi-channel selector that has the ability to select a activated connection (ie, need to process) from a set of Connection objects.

The ProxyDaemon class represents a message forwarding processing task. In a real system, ProxyDaemon should be a series of active objects.

The PENDINGRESPONSE class indicates an unresparable response. This class records who will send it to any important information. This information is an important basis for the routing response message (ie, reverse routing) and whether the answer is timeout.

PENDINGLIST maintains a list of PendingResponse objects.

TimerDaemon is mainly used for timeout detection. The daemon is scheduled to detect whether the universal response in the pendinglist is timeout, if the timeout is timeout, the timeout message is issued.

3. Request processing

Proxydaemon is used to forward requests and answers. The logic of Proxydaemon is similar to the logic described in the first quarter of this article, but just just need to add an outgoing response, without waiting for a synchronous waiting to answer. The following code describes how to handle requests.

// .. Shows How To Handle Request

Connection conn = selector.getactiveConnection ();

Message msg = conn.recv ();

IF (msg.isRequest ()) {

Request Req = New Request (MSG);

Connection dest = routetbl.getConnectionbyAddr (Req.getDestination);

// forward request

Dest.send (REQ);

// Add Pending Response

PendingResponse Pending = New PendingResponse (REQ);

// Get Reference of Sender's Connection

Pending.set Shender (CONN);

PendingList.Add (Pending);

// Add Destination Connection Into Selector, So, Once Response Received, Selector Can Detect IT

Selector.AddConnection (DEST);

}

Else {

// Response

}

In the above code, this first determines based on the received message type is a request or a response. If it is a request, forward, then add an unreasonable response, which records for reverse addressing and timeout detection (PENDINGRESONSE) Information of the timestamp in the constructor). Finally, add a request to the selection of the request to the Selector's waiting pool. This allows the selector to return the connection object if the response message arrives on the connection.

4. Forward response

The forwarding response is also the main job of Proxydaemon.

In the new architecture, we used multiple selection mechanisms instead of synchronous waits, so we also need to adopt a reverse addressing and routing mechanism such that the response message can be correctly forwarded to the requesting initiator.

The PENDINGRESPONSE object records information for reverse addressing. By requesting the ID number of the request and answering message, the request should be promised correctly; in addition, PendingResponse retains the connection object of the request initiator, so it can forward the response to the initial request initiator. The following pseudo codes describe the forwarding response process. // ...

Connection conn = selector.getactiveConnection ();

Message msg = conn.recv ();

IF (msg.isRequest ()) {

// Request

}

Else {

// Get Response

Response Resp = New Response (MSG);

// Get Correct Pending Response BY ID

PendngResponse Pending = PendingList.getPENGRESPONSE (RESP);

IF (PENDING! = null) {

// forward response

Pending.getConnection (). Send (resp);

}

Else {

// Timeout

}

}

When receiving the answer message, first, depending on the ResponseFor property of your response, you will find the unresponsive response object that records the reverse routing information. If the object is not found, the indication response has timeout, the unprecedable response object has been deleted; if the unprecedable response object is found, the response is forwarded according to the connection object application of the request initiator reserved.

5. Overtime processing

Distributed systems are unreliable, anyone can't assume that the message can be properly delivered and handled correctly, so waiting timeout must be processed.

In the simplest implementation logic described in the first section of this article, since it is synchronized to wait a response, it is easy to judge, as long as the RECV () method can support timeout. In the architecture described in this article, the response is also driven by multiple selection mode messages, which brings complexity to the timeout judgment and processing.

We need to use TimerDaemon to dynamically detect the unresparable response queue. Every time TimerDaemon is waken, it is necessary to traverse the entire pending response queue. If there is an unprecedable response object timeout, then according to the reverse routing information, send timeout messages to the request initiator, and remove the unprecedable response from the unreasonable column. Object.

// ...

While (! stop) {

SLEEP (500);

While (true) {

PENDINGRESPONSE PENDING = PendingList.getNextpending ();

IF (pending == null) {

Break;

}

Else {

IF (PENDING.IMEOUT ()) {

// send Time OUT MESSAGE

Connection Sender = Pending.getConnection ();

Sender.send (Message.Timeout);

// Remove Pending Response from List

Pendinglist.removependingResponse (PENDING);

}

}

}

}

Since each unprecedomous response object requires time, TimerDaemon's sleep cycle should be less than the minimum timer interval specified by the protocol.

6. Conclude

转载请注明原文地址:https://www.9cbs.com/read-1066.html

New Post(0)