Liang Yinghong
Introduction
The TCP persistent connection service plays an important role in traditional intelligent network applications. Due to its high transmission efficiency, this service is widely used between the SCP module and the IP module of the intelligent network. For example, ss7gateway and SCF, SCF and Ines, Ines and external nodes, CN and Vn, and so on.
On the contrary, TCP short connection is widely used in various web applications. Most HTTP-based application protocols, such as HTML, XML, and soap, use the TCP short connection service. There are two reasons: First, these HTTP protocols have large data packets, the transmission overhead is large, and the connection establishment overhead is relatively small. In this case, using persistent connections does not significantly improve the performance. Second, compared with persistent connections, the implementation of short connections is much easier for both clients and servers.
Taking the Horizontal Service Platform spgw of China Netcom as an example, most external interfaces use HTTP/XML/SOAP protocol and short connections. However, for the sake of performance, there are two interfaces using TCP persistent connections:
L east interface (SPGW-DSMP): SCCP protocol uses binary messages.
L southbound interface (SPGW-SMSC): The sm7 protocol between spgw and SMSC of short message gateway uses binary messages.
From the perspective of Java development language, short connections are relatively simple to use. Because the Java Io library already provides an httpconnection class, it is mature, reliable, and easy to use. However, Java Io libraries do not directly support the use of TCP persistent connections. This article will discuss the general requirements of the TCP persistent connection service and our implementation considerations.
The TCP persistent connection service is also called the TCP Service.
Requirement
Anyone with network programming experience knows that TCPProgramThe compilation is "easy to learn and difficult to learn ". It is easy to write a TCP program, which has certain functions and can run in a few normal cases. However, it is not a simple task to make it run stably under various network conditions and loads. Specifically, the TCP persistent connection service must meet the following conditions:
High Performance
The key to achieving this is that the message receiving operation must be asynchronous. Take the message flow between spgw and SMS gateway as an example:
As shown in, spgw can send the next short message without waiting for the Response Message of the previous message. Therefore, on the same TCP connection, sm7 messages must be received asynchronously. Otherwise, subsequent messages will be blocked.
Robustness
Robust requirements: TCP persistent connection service must not only adapt to good network conditions and low load, but also adapt to poor network conditions and high load. To achieve this, you need:
L application-level heartbeat: Automatically detects network faults.
L application-level reconnection: automatically resolves network faults.
L request Distribution: distribute request messages to message queues or independent threads to avoid blocking the work of the receiving thread.
L statistics and management: You can query and count the work of the TCP Service Module. You can also control the status of TCP connections through a standard Network Management Protocol (such as SNMP), such as opening or closing.
Application friendliness
L Synchronous Response Message receiving API: although the TCP Service receives messages asynchronously, it must provide Synchronous Response Message receiving API to the application module, to simplify the development of application modules.
L clear two-way Interface: Generally, a service package only needs to provide one-way API interface, which is called by the application module. However, TCP service packages are different. Besides being called by the application module, it also calls back the application module. For example, when a message is received, you need to call back the method of the application module to define and distribute the message. During heartbeat detection, you need to call back the codec method of the application module. Therefore, it is necessary to clearly define the two-way interface between the TCP module and the application module.
Traditional implementation methods
In our previous program implementation, we generally use a single connection to send and receive asynchronous messages.
Extra Node
Application
Main thread
Transceive thread
Message Queue
The logical structure of the entire system is roughly as above. The application is generally divided into two threads: Main and transceive. The former is used to complete the application logic and the latter to send and receive messages. They communicate with each other through a shared message queue. The two processes use the Pseudo Code as follows:
Main thread:
While (true)
Retrieve input message from Message Queue
Process the message (an output message may be generated in the middle and sent to the Message Queue)
Transceive thread:
While (true)
If (connection writable)
Get Output Message from Message Queue
Write the message to connection
If (connection readable)
Read input messages from connection
Send the message to message queue
For transceive thread, determine whether the connection can be read and written to avoid blocking. This is done through the select function of the socket API.
In actual implementation, due to the portability problem in the multi-threading of C language, the above two threads are generally combined into one:
Single thread:
While (true)
Execute the main thread operation
Perform the transceive thread operation
Advantages
The advantages of the above method are very efficient, which has proved the performance of our previous system.
Disadvantages
The disadvantage of the above method is that the main thread is troublesome to write. Because there is no synchronous message receiving API, we need to use mechanisms such as FSM to associate multiple messages. After a message is sent, you must set the status and timer of the FSM instance. When a response message is received, the Response Message is delivered to the corresponding FSM instance for processing. Using the FSM mechanism for development is still too complex for general applications.
In addition, the traditional implementation method does not solve the problem of TCP Service callback application protocol functions, and some functions of the Application Protocol (such as demarcation and codec) are often integrated into the TCP module. As the application protocol type increases, the TCP module becomes increasingly bloated and complex. This problem occurs partly because, unlike Java, the C/C ++ language does not have an interface structure, which is used to clearly define the call interfaces between two modules.
Java implementation functions and structure
The functions of the TCP service module are as follows:
1. Message sending and receiving function: provides two sending APIs:
L sendrecv: send the request message and wait for the Response Message synchronously.
L send: send the message and return immediately. It is used when you do not need to wait for a response message.
2. Heartbeat function: the TCP module automatically performs heartbeat checks by setting heartbeat attributes, such as heartbeat mode, heartbeat interval, sent heartbeat, and displayed heartbeat.
3. reconnection: For TCP clients, the TCP module automatically performs reconnection after the connection is disconnected by setting the reconnection attribute, such as whether to reconnect or not.
4. Request distribution: distribute request messages to independent threads and automatically call the method of the application module for processing.
5. Statistics and management: You can query the statistics of the TCP Service Module. You can also use SNMP and JMX to control the status of TCP connections, such as enabling or disabling TCP connections.
Thread allocation
To meet both high performance and ease of use requirements, the TCP module makes full use of the Java language's good support for multithreading. It includes the following threads:
Heartbeat thread
S
TCP Service Module
S
Recv thread
S
APP Module
S
Send thread1
S
Send thread2
S
Process request thread3
S
Sendrecv
S
Send
S
Processrequest
S
Reconnect thread
S
Send thread: The sending thread is the application thread. That is to say, the TCP module completes the sending operation in the application thread.
Recv thread: Each TCP connection starts a receiving thread to receive messages from the peer end.
Heartbeat thread: Each TCP connection starts the heartbeat thread, which is used to periodically send heartbeat messages to the peer end and check whether the response is received in time.
Reconnect thread: the TCP module starts a reconnection thread to regularly check the connection status and attempts to reconnect closed connections.
Process request thread: The request processing thread is the application thread. When the receiving thread receives a request message, it starts a request processing thread and delivers the request message to the thread for processing.
Interface
The itcpservice interface provided by the TCP module to the application module is briefly listed below:
L open the connection: open (string IP, int port)
L close the connection: void close ()
L send data packets: void send (byte [] data)
L send data packets and wait for response: byte [] sendrecv (byte [] data, int timeout)
L set the application protocol interface: void settcpmessage (itcpmessage tcpmessage );
The itcpmessage interface provided by the application module to the TCP module is briefly listed below:
L determine whether a given message is a request message: Boolean isrequest (byte [] data)
L determine whether a given message is a heartbeat message: Boolean isheartbeat (byte [] data)
L determine whether a given message is valid: Boolean isvalid (byte [] data)
L get the message length: int getlength (byte [] data)
L get the key of the given message (the Message key is used to associate a pair of requests and responses): String getkey (byte [] data)
L encode heartbeatrequest message: byte [] encodeheartbeatrequest ()
L encode the heartbeat Response Message: byte [] encodeheartbeatresponse (byte [] request );
L request message processing: void processrequest (byte [] data );
L perform the reconnection operation: void reconnect ();
L set the tcpservice object: void settcpservice (itcpservice tcpservice );
Message demarcation
In the itcpmessage interface, you need to pay attention to the getlength method:
Int getlength (byte [] data) throws tcpserviceexception
This method is critical. On the surface, the function is to take the length of the message. In fact, the TCP module uses this method to define the message (delimiter ).
All application protocols that use the TCP persistent connection service must consider how to define messages. This is because the packet received each time on the TCP connection does not necessarily correspond to a complete message, and the packet may need to be split/merged. This process is cumbersome and error-prone, mainly completed by the TCP module. However, the application module must implement the appropriate getlength method to obtain robust demarcation results.
Parameters
Data-All unprocessed packets received so far
All other methods can regard the data parameter as a complete message. But this method is different. Data may contain one complete message, one part of one message, or multiple messages.
Return Value
Length of the returned message
Positive number: indicates the length of the specified message.
0: indicates that the data is insufficient and the message length cannot be determined. For example, some protocols use the first four bytes as an integer to save the message length. If the data is less than 4 bytes, the message length cannot be determined; some protocols use \ n as the message
If \ n is not in the data, the length of the message cannot be determined.
Negative (-N): indicates that the first n bytes in the data are invalid. It should start from the N + 1 bytes and be re-bounded. For example, if some protocols use the byte Fe as the starting byte of the message, all bytes before Fe are invalid bytes.
Exception
Throws tcpserviceexception if the message format is invalid, this exception is thrown.
For example, if the message length has been determined, but the length value is negative or exceeds the length limit stipulated by the application protocol. This indicates that the data packet is invalid.
Once this exception is thrown, the TCP module clears the receiving buffer.
Summary
Compared with the support for HTTP transient connections, the java standard Io library does not support TCP persistent connections. Our TCP persistent connection service implementation is a supplement to Java's standard Io library function.