マネージドサービス部 佐竹です。
本ブログでは、AWS Gateway Load Balancer の仕様により Oracle の DBLink (データベースリンク)が切断されてしまう場合の対処法について記載します。
結論
最初にざっくりと結論を記載しておきます。
結論はパラメータグループの sqlnetora.sqlnet.expire_time
に「5」を設定してください、となります。また、実際に本設定変更で DBLink の意図しない切断が回避されたという実績もございます。
それでは、以下本文です。
はじめに
仮想ネットワークアプライアンスの冗長化に適切なロードバランサーである「AWS Gateway Load Balancer」は2020年11月11日に発表されました。以後、Gateway Load Balancer は GWLB と省略します。
本機能のリリースにより、AWS 上に仮想ネットワークアプライアンスを冗長構成で実装する例も少しずつ増えてきています。
ただし、この GWLB の導入には「ハマりポイント」がいくつかあります。
GWLB 導入におけるハマりポイント
1つ目が、私が過去にブログにまとめました「Appliance Mode」です。
GWLB 導入に関わる TGW の重要な設定「アプライアンスモード」について
詳しくは上記ブログに記載しておりますが、本設定は「非対称ルーティング」を回避するためのオプションです。また、今現在はマネジメントコンソールからも設定が可能となっています。
基本的には、GWLB をご利用される場合は合わせて AWS Transit Gateway の appliance mode を有効化する必要があります。
AWS Gateway Load Balancer の TCP フローのアイドルタイムアウト対策
そして2つ目が上記ブログで弊社手塚が記載している「TCP フローのアイドルタイムアウト」であり、これは以下の AWS 公式ブログにおいても記載されております通り GWLB の仕様です。
抜粋してご紹介すると以下の通りです。
Some applications or API requests, such as synchronous API calls to databases, have long periods of inactivity. GWLB has a fixed idle timeout of 350 seconds for TCP flows and 120 seconds for non-TCP flows. Once the idle timeout is reached or a TCP connection is closed for a flow, it is removed from GWLB’s connection state table.
データベースへの同期 API 呼び出しなど、一部のアプリケーションまたは API リクエストは、非アクティブな状態が長時間続きます。 GWLB のアイドル タイムアウトは、TCP フローの場合は 350 秒、非 TCP フローの場合は 120 秒に固定されています。 アイドル タイムアウトに達するか、フローの TCP 接続が閉じられると、そのフローは GWLB の接続状態テーブルから削除されます。
太字の通り、TCP では350秒でタイムアウトが発生します。これに対応するため、弊社ブログでは以下の通りベストプラクティスをご紹介しています。
AWS Gateway Load Balancer の TCP フローのアイドルタイムアウト影響を回避するためのベストプラクティスは、「クライアントもしくサーバ」の「アプリケーションもしくはOS」設定により、TCP 通信を 350 秒未満の間隔で発生させること、です。
本ブログでは、この350秒のタイムアウトと Oracle データベースにおける DBLink について、その切断が起きるようになる背景と具体的な回避策を解説していきます。
2024年9月6日 Gateway Load Balancer で TCP アイドル タイムアウトの設定変更が可能に
上記のアップデートの通り、AWS Gateway Load Balancer で TCP アイドル タイムアウトの設定変更が可能となりました。
AWS 公式ブログから引用及び翻訳します。
これまで、GWLB は 350 秒の固定 TCP アイドル タイマーをサポートしていました。アイドル タイムアウトの期限が切れた後に GWLB に到着したパケットは、新しいフローとみなされ、別のターゲットに転送できます。
ただし、レガシー データベースなどの多くのファイアウォールやアプリケーションでは、デフォルトの TCP アイドル タイムアウトが長くなっています。GWLB とアプリケーションのタイムアウト値が一致しないため、これらのアプリケーションからの長時間アイドル フローがアイドル時間後に GWLB によって別のターゲットに転送されると、トラフィック フローが中断される可能性があります。
GWLB の設定可能な TCP アイドル タイムアウト機能を使用すると、ファイアウォールとアプリケーションの TCP アイドル タイムアウト値を GWLB に合わせることができるため、トラフィック フローの継続性が確保され、トラフィックの中断が軽減されます。
よって、本アップデート以後は「350秒の固定で変更が不可能」ではなく、「デフォルト350秒で、60秒から6000秒の値に設定変更が可能」というようになりました。ただし、これによって Oracle DB の Keep Alive 設定が不要となるわけではありません。
設定がデフォルトの350秒のままであれば「クライアント側の設定等で Keep Alive を350秒未満に設定」するというこれまでの設定通りで問題はありませんが、もし TCP アイドル タイムアウト値を任意の値に変更した場合「Keep Alive を変更したタイムアウトの秒数未満に設定」する必要があることになります。
また、ここから先の本文は TCP アイドル タイムアウトが「デフォルトの350秒」である前提で記載されたものとなります。
Oracle データベースで350秒のタイムアウトに対応する
さて本題です。まずはどのような場合に GWLB の影響で DBLink が切断されてしまうのか説明するため、構成例を図示します。
AWS 環境構成図例
上記が構成例です。本構成図について少し解説を挟んでおきます。
左端にオンプレミス環境があり、AWS とは専用線(Direct Connect)で接続されています。各コンポーネントは Transit Gateway で接続されており、右端に RDS for Oracle が構築された VPC があります。中央には仮想ネットワークアプライアンスが導入された VPC があり、これが Inspection を行っています。この構成においては、Transit Gateway を通過する全ての通信が GWLB と仮想ネットワークアプライアンスを通過します。
上記の構成においては、AWS 内に構築された RDS for Oracle がオンプレミスもしくは、オンプレミスの先にある別のクラウドサービス(例:MS Azure)などと通信する場合に GWLB 及び仮想ネットワークアプライアンスを通過します。図示すると以下の通りです。
赤色の矢印は GWLB に入るまでの通信を表しており、青色の矢印は GWLB に入った後(つまり Inspection 後)の通信を表しています。
GWLB の影響で DBLink が切断されはじめる理由
これまで長らくの間、仮想ネットワークアプライアンスを通過しない構成で DBLink が利用されてきたとします。
このような利用シーンにおいて、後からネットワークの要件変更等により、仮想ネットワークアプライアンスが導入されるような場合、それと同時に GWLB が導入される場合があります。
この場合に DBLink は GWLB の350秒タイムアウトの影響を受け始めます。
つまりは「仮想ネットワークアプライアンスを導入した直後から、DBLink が切断されるエラーが頻発するようになった」という事象に悩まされる場合があります。
Oracle で DBLink 切断時に発生するエラー
一例としてですが、Oracle DB において DBLink が切断される場合に以下のエラーが発生する場合があるという報告例があります。以下、参考までに記載します。
- ORA-03150: データベース・リンクの通信チャネルでend-of-fileが検出されました
Oracle 公式ページは以下となります。
エラーコード: ORA-03150
詳細: データベース・リンクの通信チャネルでend-of-fileが検出されました
原因: クライアントとリモート・サーバー・プロセス間の接続が切断されました。
アクション: リモート・サーバーのalert.logファイルでエラーが発生していないか調べてください。また、サーバー・プロセスが停止しているかどうかと、障害時にトレース・ファイルが生成されたかどうかを確認してください。Oracle 12cR1 ORA-03150 データベース・リンクの通信チャネルでend-of-fileが検出されました
Keep Alive の具体的な設定方法
Oracle データベースで350秒のタイムアウトに対応するには、ベストプラクティスの通り「クライアント側の設定等で Keep Alive を350秒未満に設定」すればよいとなります。
そして、DBLink を RDS for Oracle から実行する場合は、RDS 側がクライアントとして動作します。
つまりは OS に設置されている「sqlnet.ora」の中の「SQLNET.EXPIRE_TIME」を設定することになるのですが、RDS for Oracle は OS にアクセスすることが(基本的には)できません。
このため、RDS for Oracle ではその代替としてパラメータグループで「sqlnet.ora」の設定が可能となっています。
上記ドキュメントに記載のある通り sqlnetora.sqlnet.expire_time
をパラメータグループで設定します。
パラメータグループの設定を行うにあたっての考慮事項
RDS for Oracle のパラメータグループで sqlnetora.sqlnet.expire_time
を変更すれば良いとなりますが、変更前にいくつか注意事項等を記載しておきます。
設定値の推奨は「5」
AWS 公式ドキュメントに「チェックを送信してクライアントサーバー接続がアクティブであることを確認する時間間隔 (分単位)。」と記載されている通り、本パラメータの単位は「分」です。
このため、設定値としては 350 秒未満で最大の値である「5」分(300秒)を推奨します。
本画像は実際にマネジメントコンソールから値を変更する際の画面キャプチャーとなっております。
設定値の反映は Dynamic
こちらも AWS 公式ドキュメントに掲載されている通りですが「動的(Dynamic)」の設定であるため、パラメータグループに設定を行えば RDS DB インスタンスの再起動なしにすぐさま適用されます。
よって、このパラメータの反映のための再起動は不要です。
設定変更の影響範囲の確認
パラメータグループは複数の RDS DB インスタンスに共通設定として利用できます。このため、1つのパラメータグループの変更が複数の DB インスタンスに影響する場合があります。
本設定が何らかの悪影響を与えることは考えにくい状況ではありますが、念のため設定変更を行うパラメータグループを利用している DB インスタンスは把握しておく方が良いでしょう。
まとめ
本ブログでは、AWS Gateway Load Balancer の仕様により Oracle の DBLink (データベースリンク)が切断されてしまう場合の対処法について記載しました。
また対処方法だけではなく、その理由や AWS 環境構成図を使った経路の説明、そして GWLB の仕様について可能な限り詳細に記載させて頂きました。以下は経路図の再掲です。
同事象にお困りの方は、RDS for Oracle のパラメータグループで sqlnetora.sqlnet.expire_time
を「5」として設定し、回避が可能か試みてください。
本ブログが障害対応の助けに少しでもなれば幸いです。
最後に補足ですが、途中本文で「クライアントとして動作する側で Keep Alive の設定が必要」と記載しました。
このため、もしオンプレミスから AWS に構築された RDS for Oracle に DBLink で接続するような場合では、RDS for Oracle 側の設定では本事象の回避ができません。このような場合は、RDS for Oracle に接続を行っているクライアントとして動作するサーバにおいて Keep Alive を設定する必要がある点に注意してください。
それでは、またお会いしましょう。
佐竹 陽一 (Yoichi Satake) エンジニアブログの記事一覧はコチラ
マネージドサービス部所属。AWS資格全冠。2010年1月からAWSを利用してきています。2021-2022 AWS Ambassadors/2023-2024 Japan AWS Top Engineers/2020-2024 All Certifications Engineers。AWSのコスト削減、最適化を得意としています。