さて前回は、予想外にOrderSend()で「ERR_NO_RESULT」が返却されたため、原因調査と対処方法を検討したところまで書きました。今回は、前回の対処方法を反映した共通部品「ahfw」のリリースのお知らせと、「サーバ障害」と「プロセス障害」の対応方法について検討している様子を書いてみたいと思います。
【共通部品「ahfw」ベータ版バージョンアップ(Ver1.02)のお知らせ】
---------------------------------
●ダウンロード
以下の共通部品「ahfw」ダウンロード用HPから、ダウンロードしてください。
●Ver1.02(前回リリースからの差分)
・修正内容は、OrderSend()/OrderClose()/OrderDelete()で「ERR_NO_RESULT」を検出した
際のエラー制御。
・今回EA開発にあたって、ソース修正が必要な箇所はありません。
際のエラー制御。
・今回EA開発にあたって、ソース修正が必要な箇所はありません。
新しい[ahfw.mqh」を「include」フォルダにコピーし、リコンパイルするだけでOKです。
・ドキュメントは、仕様変更に伴うメール通知メッセージが主な変更点です。
・その他のドキュメント修正箇所は、上記HPで参照ください。
---------------------------------
さて、本題。
【障害対策でダメだった理由/見直す方向の方式】(再掲)
------------------------
1.MT4プロセス障害
まず、複数のMT4を起動していたら、どのMT4が落ちたのかわからない。
なので、どのMT4を再起動していいのかわからない。。
あと落ち方も、ダイアログが出て停止してしまったら、プロセス自身は生きてるので、
「tasklist」を使ったやり方だとわからない。
2.トレードサーバ長時間通信障害
これも、上記「1.」と同様の事が言えて、「netstat -b」だと結局デモ用MTで
障害が発生したのか、ライブ用MT4で障害が発生したのかわからない。
#わかったところで、自宅にいなければ対処できないけど。。
3.ネットワーク障害
そもそもトレードサーバとの通信以前に、インターネットに接続できなくなったケース。
これは以前の通り、Messengerを起動しておいて、携帯から確認する方法。
考慮漏れは無かったけど、方式自体が今一歩。
------------------------
今回の記事では、上記「1.」と「2.」に対する対策についてです。
まず打開策のきっかけとなったのは、以下の2つのブログ記事
【参考ブログ記事】
---------------------------
---------------------------
まずは前述「1.MT4プロセス障害」に関する検討から。
【MT4プロセス障害への対応】
--------------------------------
そもそも、前述参考ブログ「2.」に書かれていた、異常発生時にダイアログが出るというパターン
を実は全く想定していなかった。#なので記事を見つけれて良かった。。。
改めて、MT4プロセス障害のパターンを洗い出して見ると。を実は全く想定していなかった。#なので記事を見つけれて良かった。。。
1.プロセス障害パターンの洗い出し
A.MT4が固まってしまう
B.MT4が勝手に異常終了してしまう
C.前述の通り、異常ダイアログが表示される
次に、MT4プロセス障害が発生したらどうする予定かというと。
2.MT4プロセス障害発生時の動作
基本的にMT4のプロセス障害検出時は、MT4を再起動。
でも、MT4が落ちたことには理由があるはずで、MT4再起動が延々を続いてしまう
可能性がある。もしそうなった場合、同じPCに同居している他のMT4にも悪影響を
与えかねないので、再起動回数の上限値を決めて、それ以上になったら再起動をしない
様にする事で対処。今のところ3回を予定。
●パターン毎の動作
・MT4が異常終了しないパターン(上記「A.」/「C.」の場合)
検出時にMT4を強制終了させて、MT4を再起動
・MT4が異常終了するパターン(上記「B.」の場合)
検出時にMT4を起動
・共通次項
異常検出後のMT4起動は最大回数を決めて、それ以上発生したら、
MT4起動はさせない。ただし、手動で意図的にMT4を停止させた場合も、
MT4は起動させない。
3.MT4プロセス異常検出方式の検討
そもそもの大方針は、前述参考ブログ「1.」を参考にすることにした。
つまり、start()関数内で定期的にループして、基本的にはstart()関数を抜けない。
そして、ループの中で障害対応用ロジックを動かすというもの。
うーん。これは思いつかなかった!
それでは、上記プロセス障害のパターン毎に対応策
4.プロセス障害パターン毎の処理方式
A.「MT4が固まってしまう」
実際発生したことないので、よくわかんないんだけど以下の方式にしてみることにした。
1.MT4の監視用EAで定期的に監視用のファイルを更新する
2.上記監視用ファイルのタイムスタンプを定期的にチェックする監視用プログラムを
別に作って、一定時間更新されなければ、MT4が固まったという判断をする
3.MT4が固まったと判定されれば、監視用プログラムから強制終了させる
4.強制終了させた場合は、MT4を起動する。
B.「MT4が勝手に異常終了」
これも実は未体験。だけど、Windowsコマンドの「taskkill /F -PID [プロセスID]」で
発生させることができる。 これへの対策は、以下の様な感じ。
1.監視用EAで、MT4終了時は監視用ファイルの中身を消す。
2.上記「A.」で登場する監視用プログラムから、MT4を起動する。
→WindowsAPIの「CreateProcess」を使用
3.上記「CreateProcess」で取得したハンドルを元に、「WaitForSingleObject」
を実行し、結果がプロセス終了となるまで待つ。
4.プロセス終了を検出したら、監視用ファイルのサイズを確認し、サイズがゼロ
でなければ、異常終了と判定し、MT4を起動する。
C.「異常ダイアログが表示」
正直、このパターンが一番苦労した。事象を発生させるのは、参考ブログ「2.」で
書いてある方法。最初このブログ記事を見た時は、ダイアログ表示後、MT4が固まって
しまうだろうから、前述「A.」の方式で大丈夫と思ってた。
でも、実際やってみると違ってて、監視用EAは動き続けてた。なので前述「A.」の
方式では検出できない。
で色々考えた挙句、ちょっと汚いけど、MT4ルートウィンドウを親に持つポップアップ
ウィンドウを取得し、そのウィンドウのタイトルに、"システム異常の詳細"という
文字列が含まれていた場合は異常と見なす事にした。
そして、異常と判断した場合は、監視ファイルの更新を止める事により、前述「A.」
の仕組みで強制終了される事になって、その後の流れは同じ。
4.その他
ここまでの方式は実際やってみて、とりあえず動作確認まではいった。
それでも課題はまだ残ってるので、検討してみた。
1.スレッド障害に対応できない
要は、上記「C.異常ダイアログが表示」の通り、1つのスレッドで障害が発生しても、
他のスレッドには影響が及ばない様になっているっぽい。裏を返すと、スレッド個別の
障害が発生した場合は、検出できない。以下、対策案。
・各EAでティックデータ受信した時に、時刻を大域変数に格納する。
ティックデータ受信後処理に成功したら大域変数をゼロにする。
監視用EAで、該当時刻から一定時間経っているのを検出したら、スレッド障害と判断する。
2.メール通知してない
本当はコマンドラインベースのメール送信フリーソフトを使って、通知しようと
して、2つのメールソフトを見繕ったけど、SMTP認証ロジックが入ってな
かった。でも、次に試した以下のソフトだと上手くいった。
なので、プロセス障害時はこれを使ってメール通知する事に。
--------------------------------
次は、サーバ長時間障害に関して。
【サーバ長時間障害検出の検討】
------------------------------
まず想定している障害は、サーバが長時間(5分程度?)ダウンしている状態。この場合、ティックデータ受信されないので、普通にしているとEAでは気付かない。なので、サーバ長時間障害が発生した場合は、メール通知したい。
異常検出メールを受信しても、FX業者に電話
するぐらいしかないんですけど。。。
検出方法は、これも基本的には参考ブログ「1.」のアイデアを流用して、start()開始後(つまり最初にティックデータ受信後)IsConnected()チェックをループするという方式。なので、前述の【MT4プロセス障害への対応】で登場する監視EAで、IsConnected()をチェックし、N秒間隔で連続何回IsConnected()がFALSEであれば、メール通知するという仕組み。
該当ブログには、同じ目的の以下の記事があるけど、違う方式を取ることにした。
根性がねじ曲がってるから
それもあるけど、本当はIsConnected()だけで十分じゃないかなぁぐらいの理由。
時刻差をチェックしない場合のデメリットは、ティックデータ受信用セッションは死んでて、
オーダ操作用セッションは生きている場合に検出できないかもしれない点。
#2つのセッションの使い分けはあくまで仮説。。
オーダ操作用セッションは生きている場合に検出できないかもしれない点。
#2つのセッションの使い分けはあくまで仮説。。
でも、「netstat -b」で見てると、MT4からの接続先IPアドレスとポート番号は
同じなので、ことセッションという観点では、トレードサーバ側が長時間停止した場合は、
2つのセッションがどっちも切れてると思うから大丈夫じゃないかなと。
#間欠障害だと片方だけってのもあると思うんですけど。。
------------------------------------
そして今回の記事を実現する為に、具体的にどういう構造にしようとしているかという話
【プロセス障害/サーバ障害監視部品構成図】
---------------------------------
今作ってるこの部品を絵にしてみると以下の様な感じ。
※青色の部分が作ったところ。
※青色の部分が作ったところ。
●補足説明
・MT4を起動する時は、バッチファイルから、MT4起動用プロセスを起動して、そこからさらに
MT4を起動する。MT4には、監視用EAをトレードで使わないチャートに貼り付けておく。
・MT4を起動する時は、バッチファイルから、MT4起動用プロセスを起動して、そこからさらに
MT4を起動する。MT4には、監視用EAをトレードで使わないチャートに貼り付けておく。
・今回わざわざ起動バッチファイルを分離したかと言うと、メール送信はフリーソフトを使う
予定だけど、人(むしろ環境?)によって好みが分かれるはずなので、バッチファイルにした方が
汎用性が高い様な気がしたから。
予定だけど、人(むしろ環境?)によって好みが分かれるはずなので、バッチファイルにした方が
汎用性が高い様な気がしたから。
・「MT4起動/監視プロセス」はVC++2010Expressで作ったコマンドタイプ
のプログラムなので画面なし。画面を用意してないのは、2つ理由がある。
→ 今回使ったVC++2010はExpress版という無償バージョンを使ってる。これで
画面付のアプリを作ると、利用者は別途2つのMSのモジュールをインストールしないといけ
ないっぽい。配布するにはちょっと不適切。
→ ここ10数年VC++使った事なくて、画面制御するプログラム組むのに時間がかかる。
#また勉強しなきゃいけないし。。大体、Windowsのプログラミング自体が久しぶり。。
これに、スレッド障害検出機能と、メール通知機能を追加したら、方式もまたちょっと変わるかもしれないし、本格的にはまだ動作させてないので、方式も動かしてるうちに変わってくるかも。
----------------------------------
今日のブログは結局、
他人のフンドシで
相撲を取ってる状態。。
許してくださいm(__)m
そして、許しを請いながら「FXシステムトレード初心者奮闘記」の「MT4用EA開発時代」は、今回記事のプログラムを作りながら、どこかに向かうのでした。
#まだデモ口座上EAのstart()排他処理したままの状態や。。。ぼちぼち外さないと。。。
こんにちは。
返信削除> C.「異常ダイアログが表示」
> で色々考えた挙句、ちょっと汚いけど、MT4ルートウィンドウを親に持つポップアップ
> ウィンドウを取得し、そのウィンドウのタイトルに、"システム異常の詳細"という
> 文字列が含まれていた場合は異常と見なす事にした。
クラッシュ・ダイアログが出現すると同時に、
MT4フォルダ\logs\crashlog.log ができます。
内容はダイアログと同じです。ご参考まで。
【旧ブログから転記】
※ このコメントは、旧ブログで頂いたコメントを、ブログ筆者が転記したものです。
kartz様
返信削除いつもありがとうございます!
以下の方法の方が本質的且つ確実ですね!!!
実際確認したところ、次に起動した時に該当ファイルは削除されたので、
利用しやすいです。
アドバイス内容の方式を使う事にします!
#やっぱダイアログ方式は汚いし、本質的じゃないから嫌だったんですよ。。。
ありがとうございます!
> こんにちは。
>
> > C.「異常ダイアログが表示」
> > で色々考えた挙句、ちょっと汚いけど、MT4ルートウィンドウを親に持つポップアップ
> > ウィンドウを取得し、そのウィンドウのタイトルに、"システム異常の詳細"という
> > 文字列が含まれていた場合は異常と見なす事にした。
>
> クラッシュ・ダイアログが出現すると同時に、
> MT4フォルダ\logs\crashlog.log ができます。
> 内容はダイアログと同じです。ご参考まで。
【旧ブログから転記】
※ このコメントは、旧ブログのコメントを、ブログ筆者が転記したものです。