こんにちは。
バックエンドエンジニアのまさくにです。
時間の経つのは早いもの。いつの間にか初夏ですし、令和ですし、2020もすぐそこに来ているのですね。そりゃ歳も取るわけですわ、ということでNTP(Network Time Protocol)について調べました。
白状すると、NTPについては長い間、雰囲気で設定していたと言わざるを得ません。何となく設定しておけば、ネットワーク経由で正確な時刻を設定してくれた縁の下の力持ち的ないいやつでしょう? みんなそうじゃない? そうじゃない? そうですか……。そのように考えの浅い僕でしたが、少し前で困ったのが、うるう秒です。そこで少し興味をもち、NTPのことについて調べました。今回は具体的な設定項目ではなく、NTPの仕組みを書こうと思います。
コンピュータにとって時間とは何か
考えてみるとコンピュータというものが、時間の概念を知っているのは少し不思議ですよね。
例えばJavaScriptで言うところの` setTimeout は指定期間後に任意の処理を実行します。……指定期間後? 当たり前すぎてあまり疑問に思えませんが、コンピュータは、この「指定された期間」をなぜ計ることができるのでしょうか。
友人と渋谷ハチ公前15時に集合と言われたら僕らは時刻を基にします。僕らにとって時刻を知ることはとても容易なことです。スマホを見る、腕時計を見る。それで15時までの時間経過を知ることができるでしょう。
僕らはそれぞれその「指定された期間」を暗黙のうちに同期させることによって、15時に友人と集合することができます。
もっと昔でいえば、日時計を使う、水時計を使う、星の満ち欠け、動きを観察する、植物の成長を観察する、などで僕らは時間をなんとなく気づくことができました。それを昔の人は計算して、年や月という考え方にしたのでしょうね。
僕らの時間経過の感覚なんてあてにならないので、要するに時間を知るためには、一定期間で正確に変化していく観察対象が必要になります。ですが、コンピュータはそのように世界を観察する目を持っていません。なので時間の経過を知ることができないはずなのです。
ですが現代、身近なところで正確な時間を教えてくれるのはコンピュータです。今ではハチ公前の皆さんは、ほぼ全員がスマホで時間を確認しているのではないでしょうか。全員がたぶん間違いなく、同じ時間を見ています。不思議ですよね。
水晶振動子というものがあります。素子の一つでクォーツ時計にも利用されています。水晶(クォーツ)を利用して時間を得る技術ですね。
水晶には不思議な性質があって、結晶に電圧を加えると、一定の振動が起きます。これが規則正しい波(周波数)を生み、その波長が時間を計る約束事となって、コンピュータは時間が経っていることを知ることができるのです。
この水晶振動子を利用したものが、ハードウェアとしてマザーボードに組み込まれているRTC(Real Time Clock)です。RTCがあるのでコンピュータは電源を切っても、時刻を見失わずにいられます。
じゃあそれがコンピュータに組み込まれているならそれでOKですよね。あれ? NTPの話でてきた? それぞれのコンピュータで正確な時間がわかるなら、NTPなんて必要なかったんだ。クォーツ時計は狂いのない時間の象徴、それが入っているならもうそれで足りているんだ。これで世界は正確な時刻を手に入れたんだ。めでたし、めでたし。はい解散!
……というわけにもいかない。
実は水晶振動子は、残念ながらそれほど正確ではありません。だいたい10の6乗(100万)の精度で一秒ずれていきます。一見、100万秒なんて永遠の時間に感じられますが、一日が86400秒なので、100万秒で1秒ずれるとすると、12日目には1036800で、ずれ始めてしまう計算です。思いのほか早い。あのクォーツ時計は狂わないという神話はなんだったんだ……。
そんなに頻繁にずれるとなると、サーバーはログとかに出す時刻に困るよ、って話になりますよね。マジ困るよ。ログの時間狂うと、バグ追えなくなったりしますし、ユーザーのサポートもできなくなってしまいますし。じゃあ正しい時刻をどうにか取得して、どうにか設定できるようにして、時刻を合わせていきましょう、という考え方が必要で、それがNTPなんです。
NTPってなに?
それぞれのコンピュータだけだと時刻がずれてしまうのはOK。もっと正確な時刻を取得していきましょうという方法論がNTPなんですね。でも水晶をもってしても時間がかなりずれるっていうのに、もっと正確な時間を知るものなんてあるのかっていうと、出てくるのが原子時計なんです。
「秒」の定義というのが昔は地球の自転の長さをもとに算出されていたのですが、あんまり正確じゃないってのがわかって、セシウム原子時計が用いられるようになりました。
計量標準総合センターによると「秒」の定義は下記の通り。
秒の定義: 秒は、セシウム 133 の原子の基底状態の二つの超微細構造準位の間の遷移に対応する放射の周期の9 192 631 770 倍の継続時間である。
(第13回CGPM, 1967-1968)
秒の定義の補則: この定義は温度0 Kのもとで静止した状態にあるセシウム原子に基準を置いている。(CIPM,1997)
……ということで、もうよくわからないんですけど、SI基本単位のひとつとして定義されています。ほかにも一般相対性理論とかの考え方も加味されるみたいですが。要するに現代において、人類が限界の精度で実用可能な1秒を計る定義が決められているということですね。
で、NTPはその原子時計をもとに算出される「正確な時間」を世界中に配信しているんです。NTP以前、もともとTP(Time Protocol)というものがありました。しかしTPは与えられた時刻をそのまま鵜呑みにし、正しい時間だとして設定してしまうので、ネットワークの経路にかかった時間のぶん、誤差が出てしまっていました。この誤差を計算で修正したものがNTP(Netowork Time Protocol)です。
NTPの仕組み
NTPでは公開されているNTPサーバーから時刻を取得し、それを正しい時刻として自身のRTCにフィードバックします。なので、NTPが動いていれば、原子時計をもとにした時刻が与えられるため、水晶から得られる時刻がずれても安心なのですね。凄い。
しかし原子時計は皆さんの身近にはないはずです。僕も見たことがないです。日本の標準時は国立研究開発法人情報通信研究機構(NICT)が持っている原子時計をもとに定められています。
NTPサーバーを立てると、基本的に「どのサーバーから時刻を受け取るか」を設定します。上記のことからNICTが提供しているNTPサーバー(ntp.nict.jp)を設定してしまいたくなるのですが、それはNTP本来の考え方からすると推奨されません。
NTPはStratumと呼ばれる階層構造を持ち、負荷分散が考えられています。Stratum0はいまは原子時計、つまり一番正確な時刻ですね。でも原子時計はNTPとして直結できないので、原子時計から時刻を生成しているStratum1が実質的に時刻を配信している最初のエントリーポイントになります。Stratumは0から15まであります。
そのStratum1の一つがNICTのサーバー(ntp.nict.jp)となります。Stratum2以降は、Stratum1からの時刻を受け取って配信しているので、数が離れれば離れるほど当然誤差が大きくなっていきます。その誤差がどこまで許容できるかは、どこまでシビアな時間が必要かによるでしょう。
そう言われるとStratum1を設定したいのが人情なのですが、みんながStratum1のサーバーを設定したらどうなるでしょう。せっかく考えられているのに、負荷分散の仕組みを持っている意味がありません。なので、NTPとしては、みんなStratum1じゃなくて、Stratum2以降のサーバーに接続しましょう、と言っています。そのためのプロジェクトが「NTP POOL PROJECT」であったりします。
しかし、NICTのFAQを読むとわかるのですが、NICTは大幅なNTPサーバー増強の結果、個人ユーザーでもあっても直接接続しても問題ない、と言っています。男気。毎秒100万リクエスト以上をさばききるそうです。惚れる。
つまりNTPとは、原子時計をもとにしたStratum1以降のサーバーから正確な時刻を取得し、さらにその取得した時刻を自身のRTCにフィードバックし、時刻のずれをなくしていく仕組み、ということになります。
まとめ
NTPの仕組みについて話しましたが、これはntpdなどのミドルウェアで実装されています。CentOS7ではntpdは標準採用から外れ、代わりにchronyがNTPを利用し、時刻の調整をしています。
ゾーンとか、時刻の調整方式とか、他にも時刻関連で面倒なことが色々あるんですけど、NTPの基本概念は以上です。ぶっちゃけインスタンス作ったらもう起動していると思うし、インストールすればだいたいそのまま雰囲気で使えちゃうと思うんですけれど。NTPはただのいいやつではなく、サーバーにとっての時間の流れを書き換え、正確な時間を刻む、神なのでした。
それでは。最近異世界に召喚されたいまさくにでした。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。