メインフレームと分散システムを統合して監視する製品を使おうとする中で、深刻な問題に遭遇しました。
それは、私が生まれるはるか以前から連綿と稼働し続けてきたメインフレームシステムの中には、世界協定時刻(UTC)ではなく、日本ローカル時刻(JST)で動いているものがあったことです。
統合監視を行う中で、これは大変な事象を引き起こします。今時の監視製品(世界中のシステムを監視することを考えるとUTCをベースに動作していることは自明でしょう)でメインフレーム上のアプリケーションを監視すると、なんと、データが「9時間未来」から届いている(ように見える)のです。時空を超えるメインフレーム・・・
まあ、製品は改善されていきますので、いつまでもこのような状態ではありませんが、現在のメインフレームはUTC+TIMEZONEを設定して稼働させることが前提で、社内の検証システムもそのように設定されて動いています。共用システムなので勝手に時刻を変更するわけにもいきません。これではお客様環境を想定した検証ができません。どうすればよいでしょう。
そうです。自分の自由になる分散システム(想定のPCサーバー)の時刻を9時間遅らせればよいのです。
というわけで、9時間遅れた時刻を返すSNTPサーバーを作成してメインフレーム上で稼働し、分散システムを9時間過去に飛ばしました。
SNTPサーバーには、Apache Commons Netのサンプルとして公開されているJavaのSNTPサーバーを利用しました。
改修点のdiffを以下に記します。
TransmitTimeとReceiveTimeをそれぞれ、9時間(9L * 60L * 60L * 1000L ms)オフセットします。
【補足】
SNTPクライアントは、サーバーとの通信遅延を計算するためにReceiveTime(サーバーがリクエストを受信した時刻)も利用します。そのため、時刻を正しくずらして同期させるには、TransmitTimeだけでなくReceiveTimeも同様に9時間オフセットする必要があります。TransmitTimeだけオフセットすると、4.5時間だけ時刻が補正されました。
131c131
< response.setTransmitTime(TimeStamp.getNtpTime(System.currentTimeMillis()));
---
> response.setTransmitTime(TimeStamp.getNtpTime(System.currentTimeMillis() - (9L * 60L * 60L * 1000L)));
170c170
< final long rcvTime = System.currentTimeMillis();
---
> final long rcvTime = System.currentTimeMillis() - (9L * 60L * 60L * 1000L);
修正したJavaプログラムを、Gradleを用いてCLIアプリケーションとしてビルドします。
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/7.5.1/userguide/building_java_projects.html
*/
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
id 'com.gradleup.shadow' version '8.3.3'
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// https://mvnrepository.com/artifact/commons-net/commons-net
implementation 'commons-net:commons-net:3.11.1'
}
application {
// Define the main class for the application.
mainClass = 'org.apache.commons.net.examples.ntp.SimpleNTPServer'
}
メインフレーム側
以下の設定とコマンドで、SNTPDをスターテッド・タスク(STC)として稼働させます。
- スタート・プロシージャー
//SNTPD PROC
//SNTPD EXEC PGM=BPXBATSL,REGION=0M,TIME=NOLIMIT
//STDPARM DD *
PGM /usr/lpp/java/J8.0_64/bin/java -jar (配置したパス)/sntp.jar
- TCPIP PROFILE
123 UDP SNTPD ; Simple Network Time Protocol Server
- スタート・コマンド
S SNTPD
分散システム側
上記SNTPDと分散システムを同期させます。
(以下はLinuxサーバーの場合の設定とコマンドのサンプルです)
- /etc/systemd/timesyncd.conf
以下の一行を追加して、SNTPクライアントを再起動します。
NTP=(SNTPDが稼働するメインフレームのIPアドレス)
- SNTPクライアント・サービスの状態確認
systemctl status systemd-timesyncd
- SNTPクライアント・サービスの再起動
systemctl restart systemd-timesyncd
結果
9時間過去に飛んだ分散システムには、(分散システムから見て)9時間未来からメインフレーム・アプリケーションの監視データが飛んでくるようになりました。
これで、監視製品の新機能である時刻補正機能を、UTC+TIMEZONEで正しく設定されたメインフレームシステムと9時間ずれの分散システムを用いて、お客様環境想定で無事検証を完了することができました。