天天看點

套接字檔案描述符消耗小細節分析

      套接字是通信端點的抽象。正如使用檔案描述符通路檔案,應用程式用套接字描述符通路套接字。套接字描述符在UNIX系統中被當作是一種檔案描述符。事實上,許多處理檔案描述符的函數(read和write)可以用于處理套接字描述符。 ——《unix環境進階程式設計》

      WEB應用用戶端(浏覽器或APP等)與服務端的通信大多數是通過HTTP或HTTPS協定進行的。而套接字(Socket)應該算是OSI七層網絡模型中應用層與傳輸層直接的抽象層,它是面向應用層的一個程式設計接口。而HTTP/HTTPS則位于應用層,就是通過套接字(Socket)進行資訊通信的。是以,WEB應用的每個HTTP連結都與套接字(Socket)息息相關,特别是并發量大的應用,套接字(Socket)的使用至關重要。畢竟,它是應用出入的一個“口”。處理不當,則成為應用系統瓶頸。

      套接字(Socket)的瓶頸,大多數情況,還是套接字描述符的一個瓶頸(檔案打開數過多)。正如開頭所說:套接字是通信端點的抽象,應用對網際網路的通訊就是通過對這個抽象進行讀寫,就像讀寫普通檔案一樣。在unix作業系統中,讀寫檔案,就需要系統配置設定檔案辨別:檔案描述符。套接字(Socket)也不例外。

      Talk is cheap,show code:

我在本地(window)用Java寫了Socket服務端代碼,并啟動服務:

public class SocketServer{
    public static void main(String[] args) {
        try{
            ServerSocket server=null;
            server = new ServerSocket(8000);
            Socket socket=null;
            while(true){
                socket=server.accept();
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter pw = new PrintWriter(socket.getOutputStream());
                System.out.println(br.readLine());
                pw.println("ok");
                pw.flush();
                pw.close();
                br.close();
            }
        }catch(Exception e){e.printStackTrace();}
    
    }
}      

另外也用Java寫了一個Socket的用戶端,用打包成jar放到測試機(SUSE Linux)下進行測試,并觀察其對套接字描述符的一個消耗情況:

public class SocketClient{
    public static void main(String[] args) throws Exception {
        Socket socket=new Socket("192.168.22.15",8000);
        Socket socket2=new Socket("192.168.22.15",8000);
        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedReader br2=new BufferedReader(new InputStreamReader(socket2.getInputStream()));
        PrintWriter pw = new PrintWriter(socket.getOutputStream());
        PrintWriter pw2 = new PrintWriter(socket2.getOutputStream());
        pw.println("hello");
        pw2.println("hello2");
        pw.flush();
        pw2.flush();
        System.out.println(br.readLine());
        System.out.println(br2.readLine());
        Thread.sleep(20000);
        br.close();
        br2.close();
        pw.close();
        pw2.close();
        socket.close();
        socket2.close();
        System.out.println("socket close");
        Thread.sleep(20000);
        System.out.println("function close");
    }
}      

以上代碼運作期間,我會通過lsof -p <SocketClient程序号>|wc –l指令觀察此SocketClient程序消耗的檔案描述符數量。

啟動SocketClient.jar20秒前(OK):

結果:101

啟動SocketClient.jar20秒到40秒之間(socket close):

結果:99

啟動SocketClient.jar40秒後(function close):

結果:0

啟動SocketClient.jar20秒前lsof -p <SocketClient程序号>詳情:

COMMAND  PID USER   FD   TYPE  DEVICE SIZE/OFF    NODE NAME

java    5920 root  cwd    DIR     8,3     4096  486764 /usr/local/test

java    5920 root  rtd    DIR     8,3     4096       2 /

java    5920 root  txt    REG     8,3    59141  878312 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/bin/java

java    5920 root  mem    REG     8,3   116348  878486 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/libnet.so

java    5920 root  mem    REG     8,3    88544   90416 /lib64/libgcc_s.so.1

java    5920 root  mem    REG     8,3    84914  878492 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/libzip.so

java    5920 root  mem    REG     8,3     9975  878465 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/libdbgwrapper.so

java    5920 root  mem    REG     8,3   108248   90308 /lib64/libnsl-2.11.3.so

java    5920 root  mem    REG     8,3   224723  878477 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/libjava.so

java    5920 root  mem    REG     8,3   140261  878396 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libj9ute24.so

java    5920 root  DEL    REG     8,3          2183413 /var/run/nscd/dbZxaX8m

java    5920 root  mem    REG     8,3    90320  878429 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libiverel24.so

java    5920 root  mem    REG     8,3   629488  878451 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libjclscar_24.so

java    5920 root  mem    REG     8,3   225264  878449 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9vrb24.so

java    5920 root  mem    REG     8,3   316148  878441 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9jvmti24.so

java    5920 root  mem    REG     8,3   187277  878433 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9dyn24.so

java    5920 root  mem    REG     8,3   841499  878434 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9gc24.so

java    5920 root  mem    REG     8,3   109715  878430 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9bcv24.so

java    5920 root  mem    REG     8,3  6235544  878438 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9jit24.so

java    5920 root  mem    REG     8,3    93053  878446 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9trc24.so

java    5920 root  mem    REG     8,3    74373  878399 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libj9zlib24.so

java    5920 root  mem    REG     8,3   205374  878432 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9dmp24.so

java    5920 root  mem    REG     8,3    35728  436315 /usr/lib64/libnuma.so.1

java    5920 root  mem    REG     8,3    15691  878377 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libhythr.so

java    5920 root  mem    REG     8,3    46239  878376 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libhyprtshim24.so

java    5920 root  mem    REG     8,3     6957  878403 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libvmi.so

java    5920 root  mem    REG     8,3    47241   90327 /lib64/librt-2.11.3.so

java    5920 root  mem    REG     8,3   259675  878391 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libj9prt24.so

java    5920 root  mem    REG     8,3    22489  878385 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libj9hookable24.so

java    5920 root  mem    REG     8,3    70975  878394 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libj9thr24.so

java    5920 root  mem    REG     8,3   712429  878448 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libj9vm24.so

java    5920 root  mem    REG     8,3   164469  878453 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/libjvm.so

java    5920 root  mem    REG     8,3    86110  878311 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/bin/j9vm/libjvm.so

java    5920 root  mem    REG     8,3   541821   90305 /lib64/libm-2.11.3.so

java    5920 root  mem    REG     8,3  1754140   90297 /lib64/libc-2.11.3.so

java    5920 root  mem    REG     8,3    19149   90303 /lib64/libdl-2.11.3.so

java    5920 root  mem    REG     8,3    42772  878460 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/jli/libjli.so

java    5920 root  mem    REG     8,3   135690   90323 /lib64/libpthread-2.11.3.so

java    5920 root  mem    REG     8,3   151051   90290 /lib64/ld-2.11.3.so

java    5920 root  mem    REG     8,3   217016 2906402 /var/run/nscd/passwd

java    5920 root  mem    REG     8,3    26050  576479 /usr/lib64/gconv/gconv-modules.cache

java    5920 root  mem    REG     8,3   257156  576144 /usr/lib/locale/zh_CN.utf8/LC_CTYPE

java    5920 root  mem    REG     8,3    14684  878401 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/compressedrefs/libjsig.so

java    5920 root    0u   CHR   136,0      0t0       3 /dev/pts/0

java    5920 root    1u   CHR   136,0      0t0       3 /dev/pts/0

java    5920 root    2u   CHR   136,0      0t0       3 /dev/pts/0

java    5920 root    3r   REG     8,3   416697  878426 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/amd64/default/jclSC160/vm.jar

java    5920 root    4r   REG     8,3    10160  878493 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/annotation.jar

java    5920 root    5r   REG     8,3   189574  878494 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/beans.jar

java    5920 root    6r   REG     8,3   435869  878550 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/java.util.jar

java    5920 root    7r   REG     8,3   216671  878556 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/jndi.jar

java    5920 root    8r   REG     8,3    54586  878558 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/logging.jar

java    5920 root    9r   REG     8,3   287085  878567 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/security.jar

java    5920 root   10r   REG     8,3   128157  878569 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/sql.jar

java    5920 root   11r   REG     8,3  1198418  878542 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmorb.jar

java    5920 root   12r   REG     8,3   426065  878543 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmorbapi.jar

java    5920 root   13r   REG     8,3   536255  878536 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmcfw.jar

java    5920 root   14r   REG     8,3 20511988  878566 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/rt.jar

java    5920 root   15r   REG     8,3  9601775  878496 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/charsets.jar

java    5920 root   16r   REG     8,3   501898  878565 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/resources.jar

java    5920 root   17r   REG     8,3  1161371  878544 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmpkcs.jar

java    5920 root   18r   REG     8,3   133770  878534 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmcertpathfw.jar

java    5920 root   19r   REG     8,3    27626  878538 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmjgssfw.jar

java    5920 root   20r   REG     8,3    60208  878540 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmjssefw.jar

java    5920 root   21r   REG     8,3    10966  878545 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmsaslfw.jar

java    5920 root   22r   REG     8,3    97697  878537 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmjcefw.jar

java    5920 root   23r   REG     8,3   932373  878539 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmjgssprovider.jar

java    5920 root   24r   REG     8,3   442208  878541 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmjsseprovider2.jar

java    5920 root   25r   REG     8,3   357168  878535 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmcertpathprovider.jar

java    5920 root   26r   REG     8,3   152611  878546 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ibmxmlcrypto.jar

java    5920 root   27r   REG     8,3      375  878560 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/management-agent.jar

java    5920 root   28r   REG     8,3  8915002  878575 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/xml.jar

java    5920 root   29r   REG     8,3    91126  878555 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/jlm.jar

java    5920 root   30r   REG     8,3   363834  878551 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/javascript.jar

java    5920 root   31r   REG     8,3   240130  886599 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/ibmjcefips.jar

java    5920 root   32r   REG     8,3     1273  486857 /usr/local/test/socketClient.jar

java    5920 root   33r   REG     8,3   554639  886594 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/dtfj.jar

java    5920 root   34r   REG     8,3   153450  886604 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/ibmxmlencprovider.jar

java    5920 root   35r   REG     8,3   277912  886606 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/jdmpview.jar

java    5920 root   36r   REG     8,3   481038  886589 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/IBMKeyManagementServer.jar

java    5920 root   37r   REG     8,3   232590  886601 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/ibmkeycert.jar

java    5920 root   38r   REG     8,3   183719  886588 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/CmpCrmf.jar

java    5920 root   39r   REG     8,3   206636  886598 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/ibmcmsprovider.jar

java    5920 root   40r   REG     8,3    17081  886593 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/dtfj-interface.jar

java    5920 root   41r   REG     8,3    50129  886605 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/jaccess.jar

java    5920 root   42r   REG     8,3    20228  886590 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/IBMSecureRandom.jar

java    5920 root   43r   REG     8,3    23831  886608 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/xmlencfw.jar

java    5920 root   44r   REG     8,3   353513  886602 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/ibmpkcs11impl.jar

java    5920 root   45r   REG     8,3  1202552  886596 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/gskikm.jar

java    5920 root   46r   REG     8,3   148480  886595 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/dtfjview.jar

java    5920 root   47r   REG     8,3     8230  886592 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/dnsns.jar

java    5920 root   48r   REG     8,3   112283  886597 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/healthcenter.jar

java    5920 root   49r   REG     8,3    67395  886603 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/ibmsaslprovider.jar

java    5920 root   50r   REG     8,3   992455  886600 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/ibmjceprovider.jar

java    5920 root   51r   REG     8,3    67801  886591 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/JavaDiagnosticsCollector.jar

java    5920 root   52r   REG     8,3   468772  886607 /usr/lib64/jvm/java-1_6_0-ibm-1.6.0/jre/lib/ext/localedata.jar

java    5920 root   53r   REG     8,3     1273  486857 /usr/local/test/socketClient.jar

java    5920 root   54u  IPv6 1565663      0t0     TCP node1:48707->192.168.22.15:irdmi (CLOSE_WAIT)

java    5920 root   55u  sock     0,7      0t0 1565661 can't identify protocol

java    5920 root   56u  IPv6 1571368      0t0     TCP node1:48708->192.168.22.15:irdmi (CLOSE_WAIT)

      node為TCP的就是兩個SocketClient産生的套接字描述符的消耗,其它的99檔案描述符,是跟套接字功能相關的檔案打開。當Socket關閉的時候,node為TCP的套接字描述符就會别系統回收。是以,如果萬一使用套接字的時候忘記關閉套接字(Scoket),不但消耗記憶體,更容易把系統對使用者的最大檔案打開數所消耗完,就會影響應用的正常運作。

轉載于:https://www.cnblogs.com/wcd144140/p/4511135.html