Occasionally, we found that there are too many TCP connections with state CLOSE_WAIT on DataNode when our daily MapReduce tasks are running in Hadoop. At some time, the amount can be approximately up to 20000.
Firstly, we should be familiar with the process of TCP three-way handshake as well as four-way termination, which is well illustrated in the following graph.
Let's explain more detail on four-way termination process which is related to our problem.
When data transfer between client and server is done, whoever calls close method first, it, as the 'active' end, will send a 'FIN M' to the other one, and transit to FIN_WAIT_1 state.
The 'passive' end sends a 'ACK M+1', after receiving which the 'active' end goes into state 'FIN_WAIT_2', back to the 'active' one and transits into state CLOSE_WAIT right after it receives the 'FIN M' signal.
When the 'passive' end invokes close method and sends 'FIN N' to the 'active' one again, the 'active' one transits to 'TIME_WAIT' state. After waiting for tcp_time_wait_interval amount of time to ensure that there are no leftover segments, the 'active' end send 'ACK N+1' back to the 'passive' one, and a TCP connection terminates.
After getting some general understanding of TCP four-way termination, I did an experiment to simulate the above process by reading file from HDFS. The code snippet is as below:
Run it with command:
At the same time, monitor TCP connection for this java process on every phase, which is printed out in my code, via command:
Result:
The result shows that it will transit to CLOSE_WAIT state right after it has read to EOF. In this scenario, the HDFS server is the 'active' end.
It will stay at CLOSE_WAIT state no matter we call close() method or not. However, the TCP connection in CLOSE_WAIT will disappear after some time, which is before the java process dies, whereas it will last to the time the java process dies if we do not call close() method after reading the file.
Thus, it is just a normal TCP connection no matter how many CLOSE_WAIT TCP connections there are provided we remember to call close() method every time.
© 2014-2017 jason4zhu.blogspot.com All Rights Reserved
If transfering, please annotate the origin: Jason4Zhu
/usr/sbin/lsof -i tcp | grep -E 'CLOSE_WAIT|COMMAND'
Firstly, we should be familiar with the process of TCP three-way handshake as well as four-way termination, which is well illustrated in the following graph.
Let's explain more detail on four-way termination process which is related to our problem.
When data transfer between client and server is done, whoever calls close method first, it, as the 'active' end, will send a 'FIN M' to the other one, and transit to FIN_WAIT_1 state.
The 'passive' end sends a 'ACK M+1', after receiving which the 'active' end goes into state 'FIN_WAIT_2', back to the 'active' one and transits into state CLOSE_WAIT right after it receives the 'FIN M' signal.
When the 'passive' end invokes close method and sends 'FIN N' to the 'active' one again, the 'active' one transits to 'TIME_WAIT' state. After waiting for tcp_time_wait_interval amount of time to ensure that there are no leftover segments, the 'active' end send 'ACK N+1' back to the 'passive' one, and a TCP connection terminates.
After getting some general understanding of TCP four-way termination, I did an experiment to simulate the above process by reading file from HDFS. The code snippet is as below:
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * Created by jasonzhu on 20/11/14. */ public class HdfsCloseWait { public static void main(String[] args) throws IOException, InterruptedException { Path pt=new Path("hdfs://ns1/user/supertool/zhudi/input/blk_1073752163"); FileSystem fs = FileSystem.get(new Configuration()); BufferedReader br=new BufferedReader(new InputStreamReader(fs.open(pt))); String line; line=br.readLine(); System.out.println("sleep at phase 1"); Thread.sleep(1*30*1000); while (line != null) { System.out.println(line); line = br.readLine(); } System.out.println("sleep at phase 2"); Thread.sleep(1*30*1000); IOUtils.closeStream(br); fs.close(); System.out.println("sleep at phase 3"); Thread.sleep(10*30*1000); System.out.println("done=["+pt.toString()+"]"); } }
Run it with command:
hadoop jar com.judking.mr-1.0-SNAPSHOT-jar-with-dependencies.jar HdfsCloseWait
At the same time, monitor TCP connection for this java process on every phase, which is printed out in my code, via command:
#get the PID of this java process /usr/java/jdk1.7.0_11/bin/jps #either of the following command will work for monitoring TCP connection /usr/sbin/lsof -i tcp | grep PID netstat -anp | grep PID
Result:
Phase | TCP connection state |
phase 1 | ESTABLISHED |
phase 2 | CLOSE_WAIT |
phase 3 | CLOSE_WAIT |
The result shows that it will transit to CLOSE_WAIT state right after it has read to EOF. In this scenario, the HDFS server is the 'active' end.
It will stay at CLOSE_WAIT state no matter we call close() method or not. However, the TCP connection in CLOSE_WAIT will disappear after some time, which is before the java process dies, whereas it will last to the time the java process dies if we do not call close() method after reading the file.
Thus, it is just a normal TCP connection no matter how many CLOSE_WAIT TCP connections there are provided we remember to call close() method every time.
© 2014-2017 jason4zhu.blogspot.com All Rights Reserved
If transfering, please annotate the origin: Jason4Zhu
it's a bug : see
ReplyDeletehttps://issues.apache.org/jira/browse/HDFS-1836
post by miaozhener
The article provided by you is very nice and it is very helpful to know the more information.keep update with your blogs. Big Data Hadoop Online Training Hyderabad
ReplyDeleteI have a question recently we have nodes in Hadoop cluster we are seeing more close wait on new nodes
ReplyDelete