34

約1年間機能した次のコードがあります。

import urllib2

req = urllib2.Request('https://somewhere.com','<Request></Request>')
data = urllib2.urlopen(req)
print data.read()

最近、いくつかのランダムなエラーが発生しました:

  • urllib2.URLError: <urlopen error [Errno 111] Connection refused>
  • <urlopen error [Errno 110] Connection timed out>

障害のトレースは次のとおりです。

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    data = urllib2.urlopen(req).read()
  File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/lib/python2.7/urllib2.py", line 400, in open
    response = self._open(req, data)
  File "/usr/lib/python2.7/urllib2.py", line 418, in _open
    '_open', req)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 1215, in https_open
    return self.do_open(httplib.HTTPSConnection, req)
  File "/usr/lib/python2.7/urllib2.py", line 1177, in do_open
    raise URLError(err)
urllib2.URLError: <urlopen error [Errno 111] Connection refused>

上記のエラーはランダムに発生します。スクリプトは最初は正常に実行できますが、2 回目の実行では失敗し、その逆も同様です。

問題の原因をデバッグして把握するにはどうすればよいですか? エンドポイントが私の要求を消費して応答を返したが、私に到達しなかったかどうかを確認するにはどうすればよいですか?

telnetあり

私は telnet でテストしたところ、私の Python と同じように成功することもあれば、失敗することもあります。

成功時:

$ telnet somewhere.com 443
Trying XXX.YY.ZZZ.WWW...
Connected to somewhere.com.
Escape character is '^]'.
Connection closed by foreign host.

接続が拒否された場合:

$ telnet somewhere.com 443
Trying XXX.YY.ZZZ.WWW...
telnet: Unable to connect to remote host: Connection refused

タイムアウト時:

$ telnet somewhere.com 443
Trying XXX.YY.ZZZ.WWW...
telnet: Unable to connect to remote host: Connection timed out
4

2 に答える 2

50

問題

問題はネットワーク層にあります。説明されているステータス コードは次のとおりです。

  • Connection refused: ピアは、接続しようとしているそれぞれのネットワーク ポートをリッスンしていません。これは通常、ファイアウォールがアクティブに接続を拒否しているか、該当するサービスが他のサイトで開始されていないか、過負荷になっていることを意味します。

  • Connection timed out: TCP 接続を確立しようとしている間、指定された制限時間内に反対側から応答がありませんでした。urllib のコンテキストでは、これは HTTP 応答が時間内に到着しなかったことを意味する場合もあります。これは、ファイアウォールが原因である場合もあり、ネットワークの輻輳やリモート (またはローカル) サイトの負荷が高い場合もあります。

コンテキストで

とはいえ、おそらくスクリプトの問題ではなく、リモート サイトの問題です。時々発生する場合は、他のサイトに負荷の問題があるか、他のサイトへのネットワーク パスが信頼できないことを示しています。

また、ネットワークの問題ですので、相手側で何が起こったのかわかりません。パケットが一方の方向では正常に移動しても、他方の方向ではドロップされる (または誤ってルーティングされる) 可能性があります。

また、(直接の) DNS の問題ではなく、別のエラー (名前またはサービスが不明、または同様のもの) を引き起こす可能性があります。ただし、要求ごとに異なる IP アドレスを返すように DNS が構成されている可能性があります。これにより、接続の試行ごとに (DNS キャッシングは別として) 異なるアドレスのホストに接続されます。これらのホストの一部が誤って構成されているか、過負荷になっているために、前述の問題が発生している可能性があります。

これをデバッグする

別の回答で示唆されているように、パケット アナライザーを使用すると、問題のデバッグに役立ちます。ただし、エラー メッセージの内容を正確に反映しているパケット以外は、あまり表示されません。

ネットワークの輻輳を問題として除外するには、またはのようなツールを使用してmtr、パケットがリモート サイトで失われるかどうtraceroutepingを確認します (以下を参照)。

ネットワークの輻輳が問題にならない場合 (つまり、失われるパケットが 1% 以下である場合)、リモート サーバーの管理者に連絡して、何が問題なのかを確認する必要があります。彼は、システム ログで関連情報を確認できる可能性があります。リモート サイトでパケット アナライザーを実行すると、ローカル サイトよりも明らかになる可能性があります。を使用してポートが開いているかどうかを確認することをnetstat -tlpお勧めします。

traceroute の結果の解釈

これにはある程度の練習が必要です。中間ホップでの高レイテンシーまたは損失がすべてを意味するか、または何も意味しない可能性があるためです。

中間ホップは通常、大量のパケットを処理するインターネットまたは ISP ネットワーク内の大きなルーターです。彼らはあなたの traceroute に返信するよりも良いことをしているかもしれません。そのため、現在非常に忙しい場合は、リクエストの 10% にのみ返信することを選択する可能性があります。または、まったく返信しないことを選択します。最後のホップで損失が見られない場合は、おそらく損失に関しては問題ありません。

ただし、最後のホップで損失が見られる場合は、最後のホップでパケットが本当に失われたかどうかを確認できません。中間ホップのいずれかが原因である可能性があります。通常、それ以前のホップでも損失が見られます。これは、実際のソースを示している可能性があります。

さらに厄介なことに、表示されるルートが実際のルートではない可能性があります。実際のルートは非対称である可能性があります。これは、目的地 (traceroute で表示されるもの) への経路が応答とは異なる経路をたどることを意味します(これは、traceroute の仕組みにより表示できません)。

要約する:

  • traceroute で観測された損失は、表示されているホップと同じかそれより前のホップによってのみ発生する可能性があります。
  • エンドツーエンドの損失のない中間ホップでの損失は、単にホップが応答しないことを意味する場合があります。
  • フォワード パス (traceroute で表示されるもの) は、リバース パスと異なる場合があります。ロスと遅延がリバース パスで発生する可能性があります。
  • ルートの途中で始まる部分的な損失 (1% ~ 90%) は、通常、ネットワークの輻輳を示します。通常、それについては何もできません。
于 2012-08-27T16:23:26.917 に答える
1

パケット アナライザを使用して、 との間のパケットを傍受しますsomewhere.com。これらのパケットを調べると、何が起こっているかがわかります。

タイムアウトまたは接続の拒否は、リモート ホストがビジー状態であることを意味している可能性があります。

于 2012-08-27T16:16:34.750 に答える