[解決済み] 接続拒否や接続タイムアウトの原因をデバッグするにはどうすればよいですか?
質問内容
私は約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>
上記のエラーはランダムに発生し、1回目の実行は成功しても、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
解決方法は?
問題点
問題はネットワーク層にあります。以下はステータスコードの説明です。
-
Connection refused
: ピアは、それぞれでリッスンしていません ネットワークポート に接続しようとしている。これは通常、ファイアウォールが積極的に接続を拒否しているか、相手側のサイトでそれぞれのサービスが起動していないか、過負荷になっていることを意味します。 -
Connection timed out
: TCP接続の確立を試みている間、相手側から与えられた制限時間内に応答が来なかった。urllibの文脈では、これは かもしれない は、HTTPレスポンスが時間内に到着しなかったことを意味します。これはファイアウォールが原因のこともありますし、ネットワークの混雑やリモート (あるいはローカル) サイトの高負荷が原因のこともあります。
コンテキスト
つまり、あなたのスクリプトに問題があるのではなく、リモートサイトに問題があるのだろうということです。時々発生するようであれば、相手サイトの負荷に問題があるか、相手サイトへのネットワーク経路が不安定であることを示しています。
また、ネットワークの問題なので、相手側で何が起こったかはわかりません。一方向には問題なくパケットが飛んでいるのに、もう一方では落とされている(あるいは経路がずれている)可能性があります。
また、(直接の)DNSの問題でもなく、その場合は別のエラー( 名前またはサービスがわからない またはそれに類するもの)。しかし、DNSがリクエストごとに異なるIPアドレスを返すように設定されている場合、接続を試みるたびに異なるアドレスのホストに接続してしまう(DNSキャッシュは別として)可能性があります。また、これらのホストが誤って設定されていたり、過負荷になっているために、前述のような問題が発生することもあります。
このデバッグ
他の回答で提案されているように、パケットアナライザを使用すると、問題をデバッグするのに役立ちます。しかし、エラーメッセージの内容を正確に反映したパケット以外、あまり見ることはできません。
ネットワークの輻輳を問題として除外するには、次のようなツールを使用することができます。
mtr
または
traceroute
あるいは
ping
を使用して、リモートサイトへのパケットが失われるかどうかを確認します(以下を参照してください)。
ネットワークの混雑が問題でない場合(つまり、パケットの1%以上が失われない場合)、リモートサーバーの管理者に連絡して、何が問題なのかを把握する必要があります。管理者は、システムログから関連情報を得ることができるかもしれません。また、リモートサーバーでパケットアナライザーを実行すると、ローカルサイトよりも明らかになるかもしれません。ポートが開いているかどうかを確認するには
netstat -tlp
をお勧めします。
tracerouteの結果を解釈する
中間ホップでの高いレイテンシや損失は、すべてを意味することもあれば、何も意味しないこともあるため、これにはある程度の練習が必要です。
中間ホップは通常、インターネットやISPのネットワークにある大きなルーターで、多くのパケットを処理します。彼らはあなたのtracerouteに返信するよりも良いことを持っているかもしれませんので、彼らは現在非常に忙しい場合は、リクエストの10%にのみ返信することを選択するかもしれません。あるいは、全く返信しないことを選ぶかもしれません。もし、あなたの最終ホップでロスが見られないのであれば、おそらくロスに関しては問題ないでしょう。
しかし、もしあなたが する 最後のホップで損失が発生した場合、そのパケットが本当に最後のホップで損失したのかどうか、確認することはできません。中間ホップのいずれかが原因である可能性があります。一般的に、それ以前のホップでも損失が見られるので、本当の送信元を示すかもしれません。
さらに追い打ちをかけるように、表示されているルートが本当のルートでない可能性もあります。本当のルートは、非対称である可能性があります。 から 目的地(tracerouteで表示されるもの)と返信(tracerouteの動作により表示されないもの)とは異なる経路をとります。
まとめると
- tracerouteで観察される損失は、あなたが見ているホップと同じかそれ以前のホップによってのみ引き起こされる可能性があります。
- エンドツーエンドの損失がない中間ホップでの損失は、単にそのホップが返信するのを面倒くさがったということかもしれません。
- フォワードパス(tracerouteで見るもの)がリバースパスと不等間隔である場合があります。
- ルートの途中から始まる部分的な損失(1%~90%)は、通常、ネットワークの輻輳を示します。通常、これに対して何かをすることはできません。
関連
-
Pythonの非常に便利な2つのデコレーターを解説
-
ピローによる動的キャプチャ認識のためのPythonサンプルコード
-
pythonを使ったオフィス自動化コード例
-
Python入門 openを使ったファイルの読み書きの方法
-
[解決済み】Python: OverflowError: 数学の範囲エラー
-
[解決済み] リストのリストからフラットなリストを作るには?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで辞書に新しいキーを追加するにはどうすればよいですか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】WindowsでTCPまたはUDPポートをリッスンしているプロセスを見つけるにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonの非常に便利な2つのデコレーターを解説
-
pythonを使ったオフィス自動化コード例
-
Python 人工知能 人間学習 描画 機械学習モデル作成
-
PythonによるExcelファイルの一括操作の説明
-
PythonでECDSAを実装する方法 知っていますか?
-
[解決済み】DataFrameのコンストラクタが正しく呼び出されない!エラー
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み】Python elifの構文が無効です【終了しました
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。
-
[解決済み】django インポートエラー - core.managementという名前のモジュールがない