リトライ処理を設計段階から明文化していこう!

  • 13
    いいね
  • 0
    コメント

はじめに

これは、システムエンジニア Advent Calendar 2016 の5日の記事です。

みなさーん、リトライ処理を書いてますか?
え、書いたことすらないって。私も10数年SEをやっていて幾つものプロジェクトを経験していますが、リトライ処理を書いたのは数回程度です。
もしかしたら、ライブラリー側にリトライ処理が書かれていて意識されてないってこともありえますけどね。

その数回のリトライ処理も改善対応による後付けのもので、設計段階からリトライ処理を組み入れたことはありません。

リトライ処理とは

リトライ処理は、ある処理で何らかのエラーが発生した際、処理が成功するまで無条件かリトライ回数だけ、一定秒数待機するなどしてから繰り返す。
また、エラーに特定のコードや文字列が含まれていた場合のみリトライすることもある。
リトライ処理されたらログ出力し、リトライさせた原因が分かるようにしておくとよい。

臭い物に蓋をするな

とあるお客さまからリトライ処理で解決しようとしたら「臭い物に蓋をするな」と言われました。
これまでの経緯で何かあると安易にリトライ処理で解決させようとして、エラーが発生する原因を特定せずにいるという姿勢を正された形です。
この言葉は非常に印象に残っており、今回この記事を書く理由になっています。

確かに原因が特定できることが一番いいわけですが、複雑化した現在のコンピューターではエラー内容を見ても原因を特定すら出来ないこともあるわけで、調査するコストもばかにならなく、頻度が多く業務に支障が出ては意味はないのでリトライ処理は入れさせて頂き、調査は追い追いで対応となることも。

調査中の案件

現在、CreateProcessを使用して外部プロセスを起動している処理があり、何かのプログラムが外部プロセスを掴んでいるため、エラーが発生しており再度繰り返せば処理が正常に動作することが分かっています。
リトライ処理を組み込めばいいのですが、何が外部プロセスを掴んでいるのが調査してからということになり、エラーが発生したら開いているプロセスを特定する「Handleツール」をバッチ実行するようにしています。

マーフィーの法則では無いですが、調査しようとするとエラーが出なくなるということで、数ヶ月してもまだ1回しか発生していません。
その1回では「System pid 4」という結果が出て、密かにウィルス駆除ソフトを疑っていたわけですが、プロセスIDの4番はNT kernel & Systemであり調査難航確実で、これはこれで困ったものです。

リトライ処理が出来ない

サーバー管理している30拠点に対して、Windows Server 2003がサポート終了に伴いWindows Server 2008R2にサーバーバージョンアップしたわけですが、レガシーASP+Oracle11gを使用しているシステムにて、月に数回は30拠点あるどこかのサーバーでセッション切れが発生するようになりました。

発生したサーバーでも数ヶ月期間が開くこともあり、アクセス多いことが原因でもなく、作業していない時間帯でも発生することもあり、原因の特定が難航していました。
セッション切れが発生するのは「oracore10.dll」のクラッシュが原因で、IIS内のプロセスがクラッシュすることでアプリケーションプール単位で再起動され、その際にワーカープロセスがもう1つ起動してアプリケーションプールを引き継ぐ仕組みとなっている。ただ引き継いだらプロセスは切れるため、前のプロセスに紐付いていたセッション情報が消えてしまう。
セッション情報が消えてしまうと、このシステムではリトライ処理しても意味がない状態になってしまい、場合によってはデータに不整合が生じてしまう。そのため、セッション切れが発生するとデータに不整合が発生していないか確認する必要がありました。

「oracore10.dll」がクラッシュが原因が何か分からないですが、Oracleのlistener.logには「TNS-12547: TNS: 接続を失いました。64-bit Windows Error: 54: Unknown error」が残っています。
Oracleサポート側から提案されたのは、sqlnet.ora 内を(NTS)から(NONE)にしてはどうかで、設定変更後から半年ほど経過しましたがセッション切れが発生しなくなりました。ただ、listener.logをみると「Windows Error: 54: Unknown error」はたまに発生しているようです。
sqlnet.ora を(NTS)にしていたのではデフォルトの設定だからです。

sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES=(NONE)

最後に

リトライ処理について書いたのですが、後半は皆さんにはあまり関係ない記事になってしまいましたがどうしても書きたかったのです、すみません。

コンピューターの性能向上やHDD容量とメモリの増加、ネットが普及したことにより、セキュリティ面がより強化されてOSやデータベースでも監視という名目でいろいろな処理が裏側で動作するようになりました。またウィルス駆除ソフトが導入されていることが前提になったりとコンピューターの処理内部はより複雑化してきています。

有能な開発者であればプログラム作成で暗黙の了解でリトライ処理がされているようになっているかも知れませんが、もはやシステム設計の段階からリトライ処理を考慮して明文化するようにしていきましょう。
また、リトライ処理されたらログ出力し、リトライさせた原因が分かるようにしておくといいですね。