⚠️
WARNING
3つのキーを持っているのに、1つ目だけを定数として再定義しているのはレガシー対応の名残りです。消しても動くのに、手が震えて消せませんでした。静かに震えた。
一時ディレクトリに置いたカウンターファイルを読み書きするだけの仕組みですが、実際にボタンを押してみると気持ちが落ち着きます。いつ誰がどのキーを使ったか、感覚で理解できるからです。
✅
SUCCESS
この4行を入れた瞬間、ブラウザのネットワークタブから余計なログが消えました。「特定の誰かに閉じる」のではなく「メソッド単位で閉じる」。そのほうが気持ちが穏やかです。
429/403 の階段を降りた日
Search Grounding を有効にしている midori301(
観光情報を最新化した記事)から大量リクエストが来た夜、3回連続で429を踏みました。フォールバックのラダーが自動で降りていくのを見ながら、心臓はもっと激しく上下していました。救われた。
試行上限を3回に決めているので、キーが5枚あっても3枚で止まります。走らせすぎて逆にロックされるほうが怖いからです。
最初は、すべてのキーを試すようにしていました。でも、キーが5枚ある場合、5回すべて試すと、API側でロックされる可能性がありました。次に、試行上限を2回にしましたが、今度は有効なキーがあるのに諦めてしまうことがありました。最終的に、試行上限を3回にすることで、ロックを避けつつ、有効なキーを見つけられるようになりました。
走らせすぎて逆にロックされるほうが怖いからです。API側のレート制限を考慮し、3回の試行で止めることで、過度なリクエストを防ぎます。これにより、キー全体がロックされるリスクを最小化します。
待機72秒という覚悟
Grounding付きのリクエストは平均72秒。短い。と感じた人は demo6 を覗いてください。
タイムアウトを90秒に延ばす前は45秒で切っていました。結果、Search Groundingのレスポンスを待たずにタイムアウトを返してしまい、ユーザーの文章も途中で宙に浮きました。諦めるには早すぎたと痛感しました。
最初は、タイムアウトを30秒に設定していました。でも、通常のリクエストでも30秒を超えることがあり、タイムアウトが頻発しました。次に、45秒に延ばしましたが、Search Grounding付きのリクエストでは、まだ足りませんでした。最終的に、90秒に延ばすことで、Search Grounding付きのリクエストでも、ほとんどの場合にレスポンスが返ってくるようになりました。ただし、90秒を超えるリクエストも稀にあるため、完全ではありませんが、実用的なバランスになりました。
90秒という値は、Search Grounding付きのリクエストの平均処理時間(72秒)を考慮して設定しました。これにより、ほとんどのリクエストがタイムアウトせずに完了できるようになりました。ただし、90秒を超えるリクエストも稀にあるため、完全ではありませんが、実用的なバランスです。
エラーメッセージを感情で読む
エラーメッセージを取得する関数が空文字列ならOK、何か入ったらすべて赤文字でログに残す。たったそれだけなのに、波形で見ると鼓動が聞こえてきます。
429で波形が跳ね、SSLエラーで平坦になる様子は、midori227(
MorphFoundryで辞書を抱えた記事)の解析ログを見返すような懐かしさがあります。ログを読むのではなく、感じる。そう意識すると1本1本のトレースに温度が宿ります。
最初は、エラーログを単純にテキストで出力していました。でも、エラーが発生した時に、すぐに気づけないことがありました。次に、エラーメッセージを赤文字で出力するようにしましたが、大量のログの中では見落とすことがありました。最終的に、波形で可視化することで、エラーのパターンが一目で分かるようになりました。
波形で可視化することで、エラーのパターンが一目で分かるようになりました。429エラーでは波形が跳ね、SSLエラーでは平坦になるなど、エラーの種類によって波形の特徴が異なります。これにより、ログを読むのではなく、感じることで、エラーの状況を直感的に把握できるようになりました。
セキュリティフローを俯瞰する
最後に、Webサーバーの設定ファイル → 設定ファイル → APIプロキシ → Gemini本体という流れを俯瞰できるマップを残しました。
ノードをクリックするたびに、当時の決断と失敗が蘇ります。URL書き換えで守れた夜。設定ファイルをうっかりブラウザに晒してしまった朝。短文。もう二度と同じミスはしたくない。
実際に試した例
- Search Grounding × 旅行記事生成
APIプロキシに 2,400文字の観光ガイドをPOST。72秒待機してもレスポンスが返ってくるように、事前にタイムアウトを90秒に設定していることを確認し、429時の体験もデモで可視化した。
midori304 のアラート履歴を JSON で丸ごと POST。ラウンドロビンでキーを分散しつつ、12秒で返る通常モードの安定感を再確認した。
急ぎの翻訳をブラウザから叩いた際、GETでアクセスして405を受け取る失敗を経験。CORSゲートの意味を改めて体で理解した。
使ってみて
使用時の注意点
1. APIプロキシに対して、POSTメソッドでJSONデータを送信する形で必ずPOSTにする
2. 429/403が連続したら、数秒 sleep を挟んで呼び直す。ラダーが3段で止まる仕様を思い出す
3. 公開記事にキーを書きたくなったら、必ず * に置き換えてから commit する
デモ6を全画面で開き、待機時間を確認する
CORSゲートのシミュレーションを試す
まとめ
- Webサーバーの設定ファイルでファイルアクセスとURL書き換えを分け、暗室の入り口を二重化した
- 設定ファイルの複数キーをラウンドロビンし、429/403が来ても3回だけ挑戦するようにした
- タイムアウトを90秒に設定するという覚悟を持ち、Search Groundingの72秒待機を受け入れた
- エラーメッセージを中心にした監視をデモ化し、感情でログを読む仕組みを用意した
- 3つのAPIキーをラウンドロビンで分散
- 試行上限は3回に設定(ロック回避のため)
- タイムアウトは90秒(Search Grounding対応)
- エラーログは波形で可視化
さらに深く学ぶには
最後まで読んでくださり、ありがとうございました。記事に出てくる *** の奥には、夜中に震えながら守った値があります。どうかあなたのAPIキーも温かい暗室にしまってください。いつかまた、暗室談義で会いましょう。