記録のConnectionTimeoutトラブルシューティング記録[問題]

最近、パフォーマンステストをやって、我々は、サードパーティのシステムを接続する場合は、取引の約1%が次のエラーを示唆していることがわかりました

nested
exception is org.apache.commons.httpclient.ConnectTimeoutException: The host did
not accept the connection within timeout of 10000 ms

最初に保留中のアイデアは、Googleの行くグーグルことができ、その結果は、調査へのステップによって、私たちの唯一のステップは、以下のレコードの下で調査プロセスを解決策を見つけることができませんでした。

キャプチャサイトの問題

第1バッグをつかむ、ネットワークに関連する問題は、波を行くのtcpdump。

tcpdump -i eth0 host xxx.xxx.xxx.xxx > tcp.dmp

3ウェイハンドシェイクパケットからTCP接続の全体の内容の抜粋は、3つの部分で説明されるニュースレターを振って4倍に送信します

説明するためにパケットフォーマット
时间戳 协议类型 请求方地址>接收方地址 Flags [xxx], seq xxx,......,length 

プロトコルの種類:ここにIPのためのTCP / IPプロトコルの

国旗共通の価値観と意味

マーク 意味
S すなわちSYN、接続を確立するための
すなわち、SYN ACKの受信の他の[S.]代表と組み合わせて使用​​することができるような、ACKであります
P すなわちPSHは、直ちに上位層にデータを受信したことを示し
F すなわちFIN、切断に
スリーウェイハンドシェイク
09:23:00.038908 IP 192.168.1.100.51777 > 192.168.1.200.39045: Flags [S], seq 2590465106, win 29200, options [mss 1460,sackOK,TS val 1752507811 ecr 0,nop,wscale 7], length 0
09:23:00.039329 IP 192.168.1.200.39045 > 192.168.1.100.51777: Flags [S.], seq 148046299, ack 2590465107, win 14480, options [mss 1460,sackOK,TS val 2174555693 ecr 1752507811,nop,wscale 7], length 0
09:23:00.039341 IP 192.168.1.100.51777 > 192.168.1.200.39045: Flags [.], ack 1, win 229, options [nop,nop,TS val 1752507811 ecr 2174555693], length 0

画像-20200322180642831

  1. クライアントが送信するSYN=1,seq=随机生成的序号サーバーに、コンテンツは、最初のパケットに対応します

  2. サーバーの応答SYN=1,seq=服务端随机序号,ack=第一步中的seq+1第2のパッケージの内容に対応したクライアントに、

  3. クライアントが送信しSYN=0,seq=第一步中的seq+2,ack=服务端的随机序号+1、サーバに、第3のパケットがに対応します

    この時点で接続が確立されます

    TCP接続は全二重である、いずれかのC-> S、缶S-> C

リクエスト送信/受信応答
09:23:00.039406 IP 192.168.1.100.51777 > 192.168.1.200.39045: Flags [P.], seq 1:167, ack 1, win 229, options [nop,nop,TS val 1752507811 ecr 2174555693], length 166
09:23:00.039426 IP 192.168.1.100.51777 > 192.168.1.200.39045: Flags [P.], seq 167:2259, ack 1, win 229, options [nop,nop,TS val 1752507811 ecr 2174555693], length 2092
09:23:00.039778 IP 192.168.1.200.39045 > 192.168.1.100.51777: Flags [.], ack 167, win 122, options [nop,nop,TS val 2174555693 ecr 1752507811], length 0
09:23:00.039784 IP 192.168.1.200.39045 > 192.168.1.100.51777: Flags [.], ack 2259, win 155, options [nop,nop,TS val 2174555693 ecr 1752507811], length 0
09:23:00.533102 IP 192.168.1.200.39045 > 192.168.1.100.51777: Flags [P.], seq 1:972, ack 2259, win 155, options [nop,nop,TS val 2174555817 ecr 1752507811], length 971
09:23:00.533114 IP 192.168.1.100.51777 > 192.168.1.200.39045: Flags [.], ack 972, win 244, options [nop,nop,TS val 1752507935 ecr 2174555817], length 0

画像-20200322180941689

  1. の信頼性の高い伝送を確保するために、レシートACK、TCPを終了するために行われるために、すべてのメッセージのニーズ回送信
  2. パッケージ1パッケージ2とサーバへのクライアント要求、パケット3、パケット4は、レシート・サーバであり、コンテンツサーバ5パケットの応答パケットをクライアント6に行う受信に応答しています。
手を振っ四
09:23:00.533121 IP 192.168.1.200.39045 > 192.168.1.100.51777: Flags [F.], seq 972, ack 2259, win 155, options [nop,nop,TS val 2174555817 ecr 1752507811], length 0
09:23:00.533166 IP 192.168.1.100.51777 > 192.168.1.200.39045: Flags [F.], seq 2259, ack 973, win 244, options [nop,nop,TS val 1752507935 ecr 2174555817], length 0
09:23:00.533479 IP 192.168.1.200.39045 > 192.168.1.100.51777: Flags [.], ack 2260, win 155, options [nop,nop,TS val 2174555817 ecr 1752507935], length 0

画像-20200322181001461

ここでは、HTTPプロトコル、およびシステムは、ヘッドに設けられているため、Connection=close要求が処理された後に、サーバーが接続を閉じますのでこと、。

  1. 最初のステップ:サーバーに送信FINクライアントに対して、対応するパッケージ1。
  2. ステップ:クライアントの領収書ACKサーバーに、対応するパケット2。
  3. 第三段階:クライアントが送信FINサーバー、対応するパケット2へ。

第二と第三のステップは、クライアントからサーバに送信されるため、TCPプロトコルは、ここで一緒にFINとACKと、合併を行うことをピアに送信するとき、それはネットワークの消費量を削減します。

  1. ステップ4:領収書サーバーACKクライアントに、対応するパック3、完全な接続解除。

分析

パッケージがキャッチされていますが、この問題は要求があるため、パフォーマンスのテスト中に、我々は単に手で分析する場合、恐怖、特に大企業のボリュームは、tcpdumpのパッケージを分析するために、いくつかのPythonコードを書いているため、時間の終わりを見つけることです接続の問題は、それが問題スリーウェイハンドシェイクなので、次のコードは、3ウェイハンドシェイクを分析する場合です。

Packet.py

分析パッケージの内容

import re


class Packet(object):
    '分组'

    timestamp = '00:00:00.000000'  # 时间戳
    from_addr = '0.0.0.0'  # 源地址
    to_addr = '0.0.0.0'  # 目的地址
    protocol_type = 'IP'  # 协议类型

    flags = '[S]'  
    seq = '0'
    ack = '0'
    length = 0  # 数据包长度

    def __init__(self, packet_str):
        hb = re.split(': ', packet_str)
        header = hb[0]
        body = hb[1]

        hs = re.split('[\s]', header)
        self.timestamp = hs[0]
        self.protocol_type = hs[1]
        self.from_addr = hs[2]
        self.to_addr = hs[4]

        bs = re.split(',\s', body)
        for b in bs:
            kv = re.split('\s', b, 1)
            k = kv[0]
            v = kv[1]
            if 'Flags' == k:
                self.flags = v
            elif 'seq' == k:
                if self.flags != '[P.]':
                    self.seq = v
            elif 'length' == k:
                self.length = int(v)
            elif 'ack' == k:
                self.ack = v

    def __str__(self):
        return self.timestamp + self.protocol_type + self.from_addr + '==>' + self.to_addr + self.flags + str(
            self.seq) + str(self.ack) + str(self.length)

ConnectionTimeoutAnalyze.py

分析DMPパッケージの内容

from tcpdump.Packet import Packet

client_addr = '192.168.1.100'
server_addr = '192.168.1.200.39045'

packet_times = {}  # 连接ID:时间
first_packets = [] #三次握手第一次的包

'''
第一步:syn=1,seq=xxx
第二步:syn=1,seq=yyy,ack=xxx+1
第三步:syn=0,seq=xxx+1,ack=yyy+1
'''
with open('C:\\Users\\xxx\\Desktop\\39045.dmp') as dmp:
    for line in dmp.readlines():
        line = str(line.strip())
        packet = Packet(line)
        if packet.from_addr.startswith(client_addr) and packet.flags == '[S]':
            first_packets.append(packet)

        id = packet.from_addr + packet.to_addr + packet.flags + 'ack=' + packet.ack
        if packet.flags != '[S.]':
            id = id + 'seq=' + packet.seq

        packet_times[id] = packet.timestamp

print('请求ID(客户端IP.端口\\请求序号)\t第一步时间\t\t第二步时间\t\t第三步时间')
for fpack in first_packets:
    sync_time = fpack.timestamp  # 第一步的时间
    id = fpack.to_addr + fpack.from_addr + '[S.]' + 'ack=' + str(int(fpack.seq) + 1)  # 第二步:ack=第一步的seq+1
    ack_time = packet_times.get(id)
    conn_time = None
    if ack_time is not None:
        conn_time = packet_times.get(fpack.from_addr + fpack.to_addr + '[.]ack=1seq=0')  # 第三步:ack=1,seq无值
    print(
        '[' + fpack.from_addr + '\\' + fpack.seq + ']\t' + sync_time + '\t\t' + str(ack_time) + '\t\t' + str(conn_time))

コード解析することにより、接続時間は、ネットワーク/第三者に正直Shuaiguoではないと、サーバーへのレシート要求SYNパケットを発行することなしと結論することはできませんされたときに作成した2番目のステップ部分で発見![ ]

おすすめ

転載: www.cnblogs.com/itaot/p/12547656.html