接続トラブルシューティング · Clash 技術ブログ

Mihomo再読み込み後も高CPU:SSインバウンド修正

Mihomoの再読み込み後、通信がなくてもCPU使用率が高いままですか。従来のストリーム暗号を使うSSインバウンドと通常のアウトバウンドを見分け、v1.19.33の修正を確認します。実際のコアを完全に再起動し、アイドル時の負荷、再読み込み、実通信を検証。戻せる設定も残します。

  • Mihomo
  • Shadowsocks
  • SSインバウンド
  • CPU使用率
  • v1.19.33
目次

インバウンドの設定を変え、接続は止まっているのに、MihomoのCPU使用率が下がらない。もう一度変更すると、アイドル時の負荷がさらに上がることもあります。この場合は、設定の読み込み中だけ負荷が上がる現象と、リスナーを閉じた後もループが空回りする現象を分けます。まず、どのプロセスが高負荷なのか、直前にどの受信口を閉じたのかを確認してください。

通信がないのに、再読み込み後もCPU使用率が下がらないのはなぜ?

公式の#3314が扱うのは、従来のストリーム暗号を使うShadowsocksインバウンドを閉じる際の不具合です。該当するlistenersの項目を変更・削除したり、ss-configを変更したりすると、以前のリスナーの受け入れループが終了しない場合があります。通信がなくてもCPUを消費し続け、同じ終了処理を繰り返すと負荷が積み重なることもあり、エラーログが出るとは限りません。

ノードの速度低下、通常のSSアウトバウンドの接続失敗、再読み込み全般の遅さとは区別してください。v1.19.33にはこの修正が含まれますが、該当するインバウンドを使っていない場合や、通常の通信中だけ負荷が高い場合に、そのまま当てはめることはできません。

プロセスと発生のタイミングで切り分ける

確認できた現象次に確認すること
該当するSSインバウンドを閉じた後、実際のMihomoプロセスのアイドル時CPU使用率が高いままになるインバウンドの種類、暗号方式、実行中のコア、閉じた時刻を確認します。
大きな設定の読み込み中だけ一時的に負荷が上がり、完了すると下がる設定検証の処理負荷を調べます。リスナーを閉じた後の空回りと同一視しないでください。
クライアントの画面は重いが、Mihomoプロセスの負荷は正常画面、トレイ、ログの処理を調べます。
該当するインバウンドがない、または大量の通信を転送するときだけ負荷が上がる該当する処理や別の実行要因を記録してください。この記事の条件だけでは原因を確定できません。

まずインバウンド設定を探す。サブスクリプション内のSSノードとは区別する

インバウンドは、別のアプリや端末がこのMihomoインスタンスに接続するための受信口です。アウトバウンドは、Mihomoが外部サービスへ接続するためのプロキシノードを指します。

クライアントが最終的にコアへ渡す設定を開き、listeners内のtype: shadowsocksと、そのcipherを確認します。旧形式の簡易設定を使っている場合は、最上位のss-configを見ます。proxiesにtype: ssがあるだけでは、この記事の条件に該当しません。

対象のストリーム暗号には、aes-128-ctr、aes-256-cfb、rc4-md5、chacha20、chacha20-ietf、xchacha20などがあります。

v1.19.33の固定ソースでは、これらの互換用暗号を内蔵リスナーで処理します。none、AEAD、2022の暗号は別の実装を通るため、この終了処理の不具合の対象外です。chacha20-ietfとchacha20-ietf-poly1305は、名前が似ていても同じ種類として扱わないでください。

現在のWikiの一般的なインバウンド暗号一覧には、上記の従来型ストリーム暗号は新規設定の選択肢として載っていません。この記事では、固定バージョンのソースに基づいて既存設定の互換処理を説明しています。再現のために古い暗号のインバウンドを新設することは勧めません。cipherだけを一方的に変更するのも避けてください。この受信口へ接続する相手側と設定を合わせる必要があります。

いまの障害から残しておく情報

  • Mihomoと画面側のプロセスを分けて観察し、どの実インスタンスでCPU使用率が高いのかを記録します。
  • 「最新版」だけで済ませず、クライアントのバージョン、実行中のコアのバージョン、起動方法を記録します。
  • 該当するlistenersまたはss-configの変更前後のコピーを残し、元のインバウンドの種類、cipher、閉じた時刻を記録します。
  • 障害が該当インバウンドの変更・削除・終了の直後に起きたかを確認します。無関係な再読み込みとまとめないでください。
  • 元の設定は手元に保存します。公開する報告からは、インバウンドのパスワード、サブスクリプショントークン、秘密鍵、サーバー情報を取り除いてください。

使える設定を保存し、ホットリロードの繰り返しを止める

使用中の設定一式、上書き設定、外部リソース、クライアント設定を別の場所にバックアップし、現在のコアのバージョン、システムプロキシ、TUNの状態を記録します。このインバウンドを他の端末も使っている場合は、接続を中断できる時間を確保し、それに依存しない管理経路を残してください。調査と同時にサブスクリプションを更新したり、DNSを変えたり、データディレクトリ全体を消したりしないでください。

すでに空回りしている場合、インバウンドの削除と追加を繰り返して「片付けよう」としないでください。旧版の不具合はリスナーを閉じた後に起こるため、ホットリロードを続けると再び発生する可能性があります。応急復旧には、アプリやサービスが用意した通常の停止方法を使い、該当する旧インスタンスが確実に終了したことを確認してから、事前に動作確認した設定で起動します。ウィンドウを閉じること、TUNを無効にすること、接続が見えないことは、プロセス終了の確認にはなりません。

この記事のために旧版で障害を繰り返し再現する必要はありません。external-controllerを開放したり、公式の再現・再読み込みスクリプトをコピーしたりする必要もありません。設定テストの-tが通っても、対応する設定検査が完了したことしか示せず、実行中のリスナーを閉じた際のループの不具合が直ったかまでは確認できません。

修正を入手したら、実際に動くコアを完全に再起動する

Mihomo v1.19.33の正式リリースノートには、修正コミット349af19が載っています。固定タグのlistener/shadowsocks/tcp.goでは、Close()の冒頭でclosedを設定してからリスナーを閉じます。これにより、受け入れループは終了に伴うエラーが発生したときに抜けられます。リスナーの終了処理の修正であり、CPU使用率の上限設定やノードの速度測定の変更ではありません。

修正を実際の稼働インスタンスに反映する

  1. 元のプロジェクトがサポートする安定版への更新方法を使う

    単独でコアを使う場合は、MetaCubeX/mihomoの正式リリースからOSとアーキテクチャに合う版を選びます。GUIクライアントでは、そのプロジェクトがサポートするアプリまたはコアの更新手順に従ってください。サービスのディレクトリにある実行ファイルを勝手に上書きしないでください。

  2. 更新に349af19が含まれることを確認する

    v1.19.33は、この記事で確認した正式な修正版です。FlClash v0.9.2の変更履歴にはMihomo v1.19.33を含むことが明記されており、根拠を追える例として挙げられます。他のクライアントやコアの派生版では、それぞれの記録を別途確認してください。画面に表示されるアプリのバージョン番号だけでは判断できません。

  3. 旧インスタンスを正常に停止してから、更新済みのインスタンスを起動する

    設定とリソースのコピーを残し、アプリやサービスの手順で正常に再起動します。旧インスタンスが終了し、新インスタンスの起動ログに想定したコアが表示されることを確認してください。旧プロセスに残ったループは、設定を取り替えただけで消えたと判断できません。ファイルを更新しても旧プロセスが終了していなければ、修正が実行中とはいえません。

確認済みの単独コマンドラインコアに限る
mihomo -v

mihomo -vが表示するのは、いま呼び出した実行ファイルの情報です。PATH上にある別の同名ファイルかもしれません。実際のサービスやクライアントが使うコアと一致する必要があります。管理されたコアでは、プロジェクトが提供するバージョン情報と起動ログを優先し、確認のために内部の実行ファイルを無理に取り出さないでください。

アイドル時の負荷、次の再読み込み、実通信を確認する

同じ端末、同じ設定、バックグラウンド処理が近い条件で、完全な再起動の前後にMihomoプロセスの負荷を比べます。まず、このインスタンスを通るテスト通信を一時停止してアイドル状態をしばらく観察し、その後で実際の処理を再開します。起動直後や実通信中のピークを、リスナーを閉じた後の継続的な空回りと同一視しないでください。

修正が実際に動いており、短時間の通信断が許される環境でのみ、もともと必要だったインバウンドの変更・削除と復元を行います。運用上こうした再読み込みが複数回必要なら、その都度アイドル時のCPU使用率を記録し、該当リスナーを閉じる回数とともに上がり続けないか確認してください。回数を増やすために旧版を何度も起動・終了したり、高負荷を作ったりする必要はありません。

確認する結果

  • 実際に動くコアに349af19が含まれ、旧インスタンスが終了している。
  • テスト通信を止めると、コアの負荷が以前の正常なアイドル状態に近い水準へ戻り、空回りが続かない。他者のCPU使用率を一律の基準にしない。
  • その後、必要に応じてインバウンドを閉じたり変更したりしても、同じ継続的な負荷や、繰り返すたびの負荷増加が起きない。
  • 必要なインバウンドを復元すると、許可された既存クライアントが再接続し、実際のHTTPSリクエストを完了できる。ルール、アウトバウンド、接続記録も元の設計どおりである。
  • システムプロキシやTUNは元の用途に沿ってのみ復元する。終了・無効化後も、端末が事前に記録したネットワーク状態へ戻れる。

当サイトでは、実際のクライアント、ルーター、サーバーでこの再現手順を実行していません。特定の性能倍率やCPU使用率がゼロになることも約束しません。ここで示すのは、公式の不具合報告、固定ソース、修正記録に基づく確認手順です。実際のネットワーク、別の高負荷要因、クライアントへの組み込み状況は、それぞれ検証する必要があります。

異常が続く場合は、使える構成へ戻して必要最小限の報告を残す

更新後に起動しない、インバウンドへ接続できない、設定が互換でない場合は、最初のエラーと現在のコピーを保存し、それ以上の再読み込みを止めます。プロジェクトがサポートする方法で、事前に動作確認したプログラムのバージョン、対応する設定、外部リソースを復元してください。新旧プログラムで唯一のデータディレクトリを共用せず、システムプロキシとTUNも元の記録に従って使える状態へ戻します。

旧版には同じ不具合が残っている可能性があります。ロールバックは応急処置であり、修正とは別です。問題のあるインバウンドを一時的に止める場合は、それに依存する接続と管理経路を確認し、該当インスタンスを正常に停止してから、動作確認済みの構成を使ってください。空回りしている旧プロセスから項目だけを削除し、そのままホットリロードを続けないでください。

再発する場合は、OSとアーキテクチャ、実際に動くコア、インバウンドの種類とcipher、閉じるきっかけになった具体的な操作、同条件でのアイドル時CPU使用率の推移、完全な再起動とその後の再読み込みの違いをプロジェクトに伝えます。これらの前提がなければ原因は未確定とし、高CPUのすべてを#3314に帰さないでください。公開する資料は、再現に必要な最小限の関係と機密情報を除いたエラーに絞り、サブスクリプション全体やパスワードはアップロードしないでください。

参考資料