web-dev-qa-db-ja.com

接続の拒否または接続タイムアウトの原因をデバッグするにはどうすればよいですか?

私は約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
28
Thierry Lam

問題

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

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

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

コンテキストで

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

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

また、別のエラー(Nameまたはサービスが不明または同様のエラー)を引き起こす(直接の)DNS問題ではありません。ただし、各リクエストで異なるIPアドレスを返すようにDNSが構成されている場合があります。これにより、各接続試行で異なるアドレスホストに接続されます(DNSキャッシュは残されます)。これらのホストの一部が誤って設定されているか、過負荷であるため、前述の問題が発生する可能性があります。

これをデバッグする

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

ネットワークの輻輳を問題として除外するには、 mtr または traceroute または ping は、パケットがリモートサイトで失われるかどうかを確認します。 mtr(およびそれに関するtracerouteツール)で損失が発生した場合、損失が発生する最初のホスト(あなたからリモートへのルートで)を、パケットがドロップするものとして常に考慮する必要があることに注意してください- [〜#〜] icmp [〜#〜] は機能します。パケットが長時間にわたって最後のホップでのみ失われる場合(100パケットなど)、そのホストには明確に問題があります。この動作が永続的である(数日にわたって)場合は、管理者に連絡することをお勧めします。

ルートの途中での損失は通常、ネットワークの輻輳に対応しており(おそらくメンテナンスが原因)、それに対してできることは何もありません(ISPに冗長性の欠如について泣き叫ぶことを除く)。

ネットワークの混雑が問題でない場合(つまり、パケットの5%以上が失われるなど)、リモートサーバーの管理者に連絡して、問題の原因を突き止めてください。彼はシステムログで関連情報を見ることができるかもしれません。リモートサイトでパケットアナライザーを実行すると、ローカルサイトでよりも明らかになる場合があります。その場合、netstat -tlpを使用してポートが開いているかどうかを確認することをお勧めします。

47
Jonas Schäfer

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

タイムアウトまたは接続拒否は、リモートホストが混雑していることを意味する場合があります。

1
Roland Smith