preface

In the last article, we learned the election process of Zookeeper and the implementation process of the FastLeaderElection algorithm, and understood the process of Zookeeper from initialization to election. In this article, we began to study the session mechanism system in Zookeeper

The session

Sessions are one of the most important concepts in Zookeeper. Any interaction between the client and server is closely related to sessions, including the life cycle of Zookeeper temporary nodes, client request execution, and Watcher notification mechanism. Zookeeper handles session related operations from global session state changes to session creation and session management

Session state

The client needs to create a session with the server. In this case, the client needs to provide a server address list, such as host1: port,host2: At this time, the state of the client changes to CONNECTION. At the same time, the client will try to establish a network CONNECTION by obtaining IP addresses in sequence according to the above address list until it successfully connects to the server. At this point, the state of the client can be changed to CONNECTED. When the ZooKeeper server provides services, the client may be disconnected from the server due to network fluctuations. At this time, the client will re-connect to the zooKeeper server. When the CONNECTION is re-established, the state of the client changes to CONNECTED again. In other words, as long as ZooKeeper is running, the client can always remain in CONNECTION or CONNECTED state. Of course, in the process of establishing a connection, if there is a connection timeout, permission check failure or in the process of establishing a connection, we actively quit the connection operation, this time the state of the client will become CLOSE.

The session to create

Session

Session is the instance carrier of a Session in Zookeeper. A Session refers to a client Session. A session must contain the following basic attributes:

  • SessionID: SessionID, which uniquely identifies a session. Each time a client establishes a connection, the Zookeeper server assigns a globally unique SessionID to the client
  • TimeOut: indicates the TimeOut period of a session. When constructing a Zookeeper instance, the client configures a sessionTimeOut parameter to specify the TimeOut period of a session. The Zookeeper server calculates and determines the TimeOut period based on the TimeOut parameter sent by the connected client
  • TickTime: indicates the timeout time of the next session. To facilitate Session management by Zookeeper, it can efficiently check and clear sessions. TickTime is a 13-bit value of type Long, which is generally close to TimeOut, but not exactly equal
  • IsCloseing: Indicates whether the current session is closed. If the server detects that the timeout period for the current session has expired, the isCloseing attribute is marked as closed, so that further requests for access to the session will not be processed

SessionID

As a globally unique identifier, we can explore how Zookeeper can ensure the global uniqueness of Session sessions in cluster environment:

During sessionTracker initialization, initializeNextSession is called to generate a session. The algorithm is as follows:

public s ta tic long initializeNextSession(long id) { long nextSid = 0; NextSid = (system.currentTim eM illis() « 24) » 8; NextSid = nextSid | « 5 6 (id); return nextSid;}}Copy the code

From this code, we can see that the session creation is roughly divided into the following steps:

1. Obtain the milliseconds of the current time

We assume that the current value of System.currentTimemills () is 1380895182327, and its 64-bit binary representation is:

00000000 00000000 00000001 01000001 10000011 11000100 01001101 11110111

  1. Moving 24 bits to the left, we get the result:

01000001 100000011 11000100 01001101 11110111 00000000 00000000 00000000 00000000 00000000, you can see that the low level has completed the high level, and the remaining low level has been completed with 0

3. Move 8 places to the right and the result becomes:

00000000 01000001 100000011 11000100 01001101 11110111 00000000 00000000

4. Calculate machine code ID:

In the initializeNextSession method, an ID variable appears. This variable is the value of the generated SID, which at deployment time is the value we configured in myID. It is usually an integer, assuming the value is 2, converted to a 64-bit binary representation:

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010

At this time, it is found that the high position is almost 0. After 56 places are moved to the left, the value is as follows:

00000010 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

5. Will get the results of the steps in front of the third and the fourth for | operation:

The result can be:

00000010 01000001 10000011 11000100 01001101 11110111 00000000 00000000

At this time we can get a unique serial number ID in the machine, the whole algorithm can probably be understood as, first through the high 8 bits to determine the machine, the following 56 bits according to the millisecond random, you can see the current algorithm! Zk uses the current machine time as the base number of milliseconds, but what is the value of System.currentTimemillis () after April 8, 2022?

Date d = new Date (2022-1900 f 3,8); System.out. p rin TLN (long.tobinaryString (d. getTime ()));Copy the code

The printed result is:

0000000000000000000000011000000000000100110000010000010000000000
Copy the code

Then we move 24 bits to the left and find that the value is still negative, so to ensure that it does not happen, the solution is as follows:

public static long initializeNextSession(long id { ) { long nextSid = 0; NextSid = (system.currentTim eM illis() « 24) > » 8; NextSid = nextSid | « 5 6 (id); return nextSid;}}Copy the code

This will avoid generating negative numbers

SessionTracker

SessionTracker is a session manager in Zookeeper. It is responsible for the creation, management and clearing of sessions throughout the zK life cycle. Each session is kept in SessionTracker as follows:

1. SessionsWithTimeout This is a data structure of type ConcurrentHashMap<Long,Integer> used to manage the session timeout. This parameter will be persisted to the snapshot file

2. SessionsById is a HashMap<Long,Integer> data structure used to manage session entities based on session ids

3. SessionsSets are also data structures of the type HashMap<Long,Integer>, used for archiving session timeout, facilitating session recovery and management

The session to create

The process of creating a session can be generally divided into several steps, which are respectively processing ConnectRequest request, creating a session, processing processor link and responding. In zK server, NIOServerCnxn is responsible for receiving the session creation request from the client and deserializing it. Then start allocating the timeout. Once the allocation is complete, the sessionId will be created and registered with SessionsById and sessionsWithTimeOut to activate it. At this point you can consider processing the flow.

Session management

SesssionTracker is responsible for session management in Zookeeper. A special mechanism is used internally, called bucket policy. The bucket policy actually manages similar sessions in a block. This helps ZooKeeper isolate sessions from different blocks and process sessions in the same block in a unified manner

Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context Context context context context context context context

ExpiractionTime = CurrentTime + SessionTimeout

But remember, the Zookeeper Leader server will periodically check whether it times out during the running time. This periodic interval is a ExpiractionInterval, in seconds. By default, it is a tickTime value, that is, 2000 milliseconds. Complete ExpiractionTime calculation method is as follows:

ExpirationTime_  = CurrentTime + SessionTimeout ;
ExpirationTime =  (ExpirationTime_ / Expirationlnterval+ 1) x Expirationlnterval ;
Copy the code
Session activation

Similarly, during the whole ZooKeeper running process, the client will send a PING request to the server within the timeout period to maintain timeliness, commonly known as heartbeat detection. After receiving the heartbeat request from the client, the server needs to activate the session state again. This process is called TouchSession, and the flow is as follows:

1. The Leader checks whether the session is closed. If the session is closed, the Leader will not deactivate the session

2. If the session is not closed, the system starts to calculate the Expiration_New time of the next Expiration_New time using the preceding formula

3. After calculating the new timeout time, it will get the original timeout time of the member and locate the original block according to the time

4. Then, locate the session from this block, migrate the session, and put it into the block corresponding to the new Expiration_New, as shown in the picture:

Session activation is basically completed after the preceding steps, and each heartbeat detection is a session activation operation. During the whole Zookeeper running process, the following two operations generally lead to session activation:

1. When the client sends requests to the server, including read/write requests, a session is activated

2. If the client does not communicate with the server within the sessionTimeOut / 3 period, that is, no request is sent, the client initiates a PING request to activate the session on the server

In addition, since the activation between sessions is saved according to the bucket policy, we can use this policy to optimize the session timeout check. In Zookeeper, session timeout check is also handled by SessionTracker, and there is an internal thread dedicated to session timeout check. You only need to check sessions in each block one by one. Since buckets distribute sessions according to multiples of ExpriationInterval, you only need to check sessions at these time points. In this way, the number of checks can be reduced and sessions can be cleared in batches to achieve higher efficiency.

Session cleaning

After the session check operation, the session clearing operation is performed when a timed out session is detected. The session clearing operation in Zookeeper is as follows:

1. The session clearing process takes a certain period of time. In order to ensure that the session will not accept or process any more requests during the session clearing process, after the session check is completed, SessionTracker will first mark the isClose of the session as true. This takes effect in the entire cluster. Zookeeper submits to the PreRequestProcessor processor for processing

2. After a session becomes invalid, the list of temporary nodes created by the session should be deleted. Therefore, before deleting the session, you need to find the list of temporary nodes corresponding to the changed session. However, we need to consider some special cases, for example, during the session deletion, there is an unfinished request to delete the node, and the deleted node happens to be the temporary node corresponding to the session, or the temporary node creation request is being processed at this time, and it is also the request of the current session. This time we have to consider treatment scheme, prevent data inconsistency, and the first case, is to prevent duplicate deletion, we only need to the corresponding node deletion request first, to delete the corresponding list, and the second case, we also need to add node executes the request first, ensure no delete node omission.

3. When the temporary node list corresponding to the session is found, Zookeeper will turn all nodes in the list into node deletion requests and throw them to the OutStandingChanges queue. Then FinalRequestProcessor will trigger the node deletion operation. Delete from an in-memory database.

4. When the temporary node corresponding to the session is deleted, it is necessary to remove the session from the SessionTracker, mainly from the SessionById, sessionsWithTimeOut and sessionsSets. When all operations are completed, the clearing operation is completed. At this point the final connection NioServerCnxn will be closed.

Session reconnection

During the running of Zookeeper, sessions may be disconnected and reconnected. In this case, the client will reestablish connections from the connection list in sequence until it is CONNECTED to one of the machines. In this case, there may be two states: CONNECTED. In this case, if the Zookeeper client connects to the server within the timeout period, the session status of the Zookeeper client is EXPIRED and the session is considered invalid.

And before the reconnection, may be disconnected because of other reasons, namely CONNECTION_LESS, throws an exception org. Apache. Zookeeper. KeeperException $ConnectionLossException, we need to catch exceptions, In addition, after successful reconnection, the setData operation can be performed in the none-SyncConnection notification. During this process, two things can happen to the session:

Session expired :SESSION_EXPIRED

Session failure generally occurs during ConnectionLoss. The client tries to reconnect, but the connection is established with the server after the timeout period. At this time, the server will notify the client that the current session is invalid

Session move :SESSION_MOVED

Session transfer is also A common situation in the process of reconnection. For example, before disconnection, the session is on server A, but after disconnection and reconnection, the session is finally recovered with server B. This situation is called session transfer. And session transfer may bring a new question, before disconnected, for instance, may have just sent a request to create nodes, after the request is sent off, the weight of the very short time again for another server, this time as the creation of the node and sent a request, the request at this time the same thing may be performed many times. Therefore, since Zookeeper3.2, we have the concept of session transfer and encapsulated a SessionMovedExection exception. Before processing a client request, we will check whether the requested session is the current server. If there is no current server session, The SessionMovedExection exception is thrown directly, of course, at this point the client is disconnected and cannot receive the abnormal response from the server.

Public number: [Android old skin] hope to write things can help you 🤣🤣