10月 182017
※TCP は詳しくないので間違いあるかも
発生していた問題
- 2017/10/17のDMMメンテ後、Nekoxy を通した通信で osapi.dmm.com サーバーだけが応答しなくなった
- 他のサーバーは問題ない
- Nekoxy が利用している TrotiNet 単体でも発生する
- 上流に Fiddler 等のプロキシを挟むと発生しない
影響
- Nekoxy を利用していたアプリケーション全般で DMM のゲーム等ができなくなっていたかと
- 提督業も忙しい!
- 七四式電子観測儀
- 回転母港
など
何故発生するのか
- osapi.dmm.com が複数の TCP パケットに分割された HTTP リクエストを正常に受け取ってくれないため
- 上流に別のプロキシを挟むと、上流プロキシが Nekoxy に代わってサーバーと TCP おしゃべりするため、その実装がこの問題に触れていなければ通信障害は発生しない
初期実装
- Nekoxy および TrotiNet は、HTTP リクエストを以下のように小出しに TCP 送信する(
微妙な実装)- HTTP リクエストライン (GET /index.html とか)
- ↑末尾の改行 (CRLF)
- HTTP リクエストヘッダ (Host: osapi.dmm.com とか)
- ヘッダ後の空白行 (CRLF。リクエストヘッダはここまでと伝えるもの)
初期実装時の挙動
- osapi.dmm.com は何故か最後の改行パケットに ACK を返してくれない
- おまけに Dup ACK からの再送も発生するのでパケロスしている
No | Source | |
---|---|---|
36 | クライアント | 「もしもし」 |
37 | サーバー | 「はい?」 |
38 | クライアント | 「データ送ります (ここまで 3 ウェイ・ハンドシェイク)」 |
39 | クライアント | 「パケット 1 送信 (HTTP リクエストライン)」 |
40 | クライアント | 「パケット 2 送信 (CRLF)」 |
41 | クライアント | 「パケット 3 送信 (HTTP リクエストヘッダ 1 パケ目)」 |
42 | クライアント | 「パケット 4 送信 (HTTP リクエストヘッダ 2 パケ目)」 |
43 | クライアント | 「パケット 5 送信 (CRLF)」 |
53 | サーバー | 「パケット1は受け取った」 |
54-55 | サーバー | 「だがその次のデータがないぞ!」 |
65 | クライアント | 「応答遅いから最後のパケット 5 再送してみよ」 |
93 | クライアント | 「(おっと反応あった) OK パケット 2 再送したよ」 |
94 | サーバー | 「パケット 4 までは受け取った!」 |
95-152 | クライアント | 「パケット 5 の完了報告がないな……再送しよ(パケット 5 再送)」× 5 ※Windows は既定値では 5 回再送する |
168 | クライアント | 「へんじがない。 ただの しかばね のようだ。(切断)」 |
osapi.dmm.com の挙動
- どうやらリクエストヘッダ後の CRLF を分割しなければ一応は届く
- しかしこれでもパケロスが出るらしく再送が発生するので結構怪しい
対応
- 分割しなければ発生しないという事がわかったので、1つにまとめて送るようにした
- パケロスも発生しなくなった
まとめ
- 無駄に HTTP を分割して TCP 送信するのはプロトコル的には問題無いはずではあるがイマイチ
- パフォーマンス的にも問題が出そう
- イマイチなデータ送信をしてたとしても正常に応答しなくなる osapi.dmm.com もイマイチ
- なんでこんなことになるのか謎。知ってる人いたら教えてほしい。