要約
- 監視ダッシュボードで、あるサービスへのヘルスチェックだけ毎回 2,800ms かかっていた
- 犯人は HTTP ではなく
.local(mDNS)のホスト名解決。Windows からraspi-ir.localを引くのに約 4.2 秒 - 接続先を IP 直指定にしたら 302ms に短縮
- 教訓: 「特定の宛先だけ遅い」「
.localを使っている」ならまず名前解決の時間を疑う
環境
- 名前解決する側: Windows サーバー(Node.js 24 / Express)
- 宛先: Raspberry Pi 上の HTTP ゲートウェイ(
raspi-ir.local:8080) - LAN 内、Pi の IP は DHCP 予約で固定
症状
監視ダッシュボードに各サービスの実機ヘルスチェック(HTTP GET で疎通確認)を実装したところ、1サービスだけ latency が突出していた。
| サービス | latency |
|---|---|
| voicevox (IP指定) | 27ms |
| pi-gateway (IP指定) | 77ms |
ir-gateway (.local指定) |
2,823ms |
同じ Raspberry Pi 上の別ポートのサービスは速いのに、.local ホスト名で叩いている ir-gateway だけ遅い。ここで「HTTPサーバーが遅い」ではなく「宛先指定の仕方が違う」ことに気づけるかが分かれ目。
調査手順
名前解決と HTTP 応答を切り分けて、それぞれの時間を測る。
名前解決の時間:
powershell -Command "Measure-Command { Resolve-DnsName raspi-ir.local } | Select TotalMilliseconds"
結果:
4240.9236
raspi-ir.local -> 192.168.68.xxx
名前解決だけで 4.2 秒。さらに、解決された IP に直接 HTTP リクエストすると:
powershell -Command "Measure-Command { Invoke-WebRequest 'http://192.168.68.xxx:8080/ir' -TimeoutSec 5 -UseBasicParsing } | Select TotalMilliseconds"
302.4456
HTTP 自体は 302ms。つまり遅延のほぼ全部が mDNS 解決だった。
原因
.local ドメインは mDNS(マルチキャストDNS)で解決される。Windows 環境ではこの解決が状況によって数秒かかることがある。タイムアウトとフォールバックの積み重ねで、1リクエストごとに固定で数秒の税金がかかっていた。
ポイントは「サーバーが遅い」のではなく「名前を引くのが遅い」こと。HTTP のレスポンスタイムだけ見ていると永遠に見つからない。
解決方法
接続先のホスト名をやめて IP 直指定にする。Pi の IP は DHCP 予約で固定済みなので安全。
設定は環境変数1行:
LIGHTS_IR_BASE_URL=http://192.168.68.xxx:8080/ir
これで再起動後、当該サービスの latency は 2,800ms → 約 300ms に。
横展開でハマらないために
今回env値を参照していたのはヘルスチェックだけではなかった。同じ .local 宛先を、
- 実機制御(IR コマンド送信)
- 別機能のフォールバック処理(派生した別の env 変数経由)
も使っていた。つまり1行の修正で「実際の操作の体感速度」まで一緒に速くなった。
当たり前だがエンドポイントを変えるときは「その env 値を読んでいる全箇所」を必ず洗う。派生変数(ある env から文字列結合で生成している別の URL)も見落としやすい。
grep -rn "\.local" --include="*.js" src | grep -i "http\|host"
.local を grep して、参照箇所と派生変数を一括で確認しておくと漏れない。
まとめ
- 「特定の宛先だけ遅い」ときは HTTP ではなく名前解決を疑う
-
.local(mDNS)は Windows で数秒かかることがある -
Measure-Commandで「解決」と「HTTP」を分けて測ると一発で切り分けられる - 固定 IP があるならホスト名をやめて IP 直指定にする
- env を変えるときは同じ値を読む全消費者と派生変数を grep で洗う