こんにちは。サーバエンジニアの山口です。
このタイトルの意味を説明する前に、 NTP、NICTについて簡単に説明します。
NTPは、ネットワークを通じて時間同期を行うプロトコルでそのNTPサービスを提供している国内最大の組織が NICT です。
そのNICTではNTP以外の HTTP / HTTPS 経由でも時刻提供サービスを提供していますが、2020/7/14のニュースリリース 「ネットワークを利用した時刻配信におけるNTPへの一元化~ http/httpsを利用した時刻配信の停止に向けた取組み~」とあるように、近い将来NICTではHTTP/HTTPS経由での時間配信が停止されようとしています。
(※ HTTP/HTTPS経由での時間配信が停止されるだけであり、NTP経由で時間配信を受けている人は特に影響ありません。)
私は、趣味でWebブラウザ Google Chrome 拡張(Extension 以下、単に拡張)作成を1つの趣味にしていますが、作成している拡張の中に、正確な時刻(1/1000秒程度の精度)を必要とする拡張を作っていて、NICTからHTTPS経由の JSON 形式で時間取得(具体的には unixtime)していました。
さて、もうお分かりの通り、拡張内で利用しているHTTPS経由での時間取得が行えなくなるため対処をしなければらなくなり、今回どう対処したかというのが今回の話になります。
(拡張ではJavaScriptでコードを記述するため、NTP引いてはUPDでの通信は基本的には行うことが出来ません。)
対策案
今回私が考えた解決方法として、
- NICT以外でHTTP/HTTPS経由で提供されているところ探す
- ローカル上にNICTの代わりとなるサーバを立てる
- AWSのEC2 サーバ上にNTP的なサーバを立てる
と3つ考えました。
1つずつ軽く試してたり、考察していきたいと思います。
1. NICT 以外で HTTP/HTTPS 経由で提供されているところ探す
拡張側で指定している通信先を変え、返ってくる JSON 形式に合わせるというだけなので修正が楽です。
Webを探し回り良さそうなのを、1つ World Time API を見つけました。
一見して良さそうに見え試してみると NICT と比べると不満がありました。
- 返ってくるJSONデータの容量が、 NICTに比べて多い
- 1Kbyte未満とはいえ、NITCが400byteに対して、 WTAは950byteと2倍以上。データ量減らしたいが調整が不可
- レスポンスタイムが、 NICTに比べて約10倍かかる
- 家で計測したところ平均30msに対して、平均300ms 。サーバが海外なので仕方ない…
- Heroku上にあり、1回だけHerokuの問題でレスポンスが返ってこないことが合った
- 頻繁に起こるようなら考えることに
2. ローカル上にNICTの代わりとなるサーバを立てる
拡張側はローカルに通信先を向けるだけで修正が楽です。
更にサーバが自分でコントロールできるので、JSONで返す内容を調整でき、ローカルなのでレイテンシ的にはかなり期待できます。
ローカルといえども、CORS、TLS、ホスト名の問題があるので、こちらも考えなければなりません。
不満点というより難しい点として、サーバの時間を常に正確に合わせる手間が発生しこれが難易度が高いと思われるので、一旦2の案はスルーしました。
3. AWSのEC2サーバ上にNTP的なサーバを立てる
サーバ側も拡張側も自由に調整できると柔軟に対応できる方法です。
しかし、拡張内から呼び出すためにCORS対応、TLS対応、IPアドレスやAWSホスト名では駄目なのでドメイン名割り振りの手間が発生しました。
それでも、サーバがある程度自分でコントロールできるので、JSONで返す内容を調整出来ます。
サーバの場所は東京リージョンに置くので、ローカルほどではないにしろある程度レイテンシは悪くありませんでした。
また、EC2上のサーバ時間は(セットアップが必要ですが)Amazon Time Sync Serviceで正確な時間が保たれて(「Amazon Time Sync Service で時間を維持する」)いて、正確な時間取得において安定していると思われます。
この方法では、特筆する不満点は見当たりませんでした。
実際に試してみた
NICTをベースとして、ローカルタイム、1、3を試した結果を見てみましょう。
計測は、1つHTMLファイル内に、JQueryを使用して並列でAJAXが行われるように作成して、計測しました。
簡単ながらも計測に使用したJSコードを下記に載せておきます。
var req = [
{ url: "https://ntp-b1.nict.go.jp/cgi-bin/json" }, // NICT
{ url: "http://worldtimeapi.org/api/timezone/Asia/Tokyo" }, // WTA
{ url: "https://(aws-ec2)/ut" }, // AWS
];
var jqXHRList = [];
for (var i = 0; i < req.length; i++) {
jqXHRList.push($.ajax({
type: "GET",
dataType: 'json',
url: req[i].url,
}));
}
$.when.apply($, jqXHRList).done(function(){
var nict = arguments[0][0];
var wt = arguments[1][0];
var aws = arguments[2][0];
/*
レスポンス表示部分
*/
}).fail(function(e){
alert("Error: Ajax failure.");
});
このコードを5回実行した結果が、下記画像になります。
NTP | unixtime | diff | diff(ms) | slow/early |
---|---|---|---|---|
Local | 1597232943.553 | -0.107 | -107ms | early |
NICT | 1597232943.446 | 0 | 0 | - |
WAT | 1597232943.441 | 0.035 | 35ms | slow |
AWS | 1597232943.294677 | 0.151 | 151ms | slow |
NTP | unixtime | diff | diff(ms) | slow/early |
---|---|---|---|---|
Local | 1597232911.529 | -0.111 | -111ms | early |
NICT | 1597232911.419 | 0 | 0 | - |
WAT | 1597232911.392 | 0.026 | 26ms | slow |
AWS | 1597232911.271675 | 0.147 | 147ms | slow |
NTP | unixtime | diff | diff(ms) | slow/early |
---|---|---|---|---|
Local | 1597232858.195 | -0.195 | -195ms | early |
NICT | 1597232858 | 0 | 0 | - |
WAT | 1597232858.058 | -0.059 | -59ms | early |
AWS | 1597232857.936454 | 0.063 | 63ms | slow |
NTP | unixtime | diff | diff(ms) | slow/early |
---|---|---|---|---|
Local | 1597232837.496 | -0.359 | -359ms | early |
NICT | 1597232837.138 | 0 | 0 | - |
WAT | 1597232837.246 | -0.109 | -109ms | early |
AWS | 1597232837.133585 | 0.004 | 4ms | slow |
NTP | unixtime | diff | diff(ms) | slow/early |
---|---|---|---|---|
Local | 1597232783.97 | -0.195 | -195ms | early |
NICT | 1597232783.776 | 0 | 0 | - |
WAT | 1597232783.832 | -0.056 | -56ms | early |
AWS | 1597232783.715794 | 0.06 | 60ms | slow |
平均してみると、
NTP | diff | diff(ms) | slow/early |
---|---|---|---|
Local | -0.1934 | -193.4ms | early |
NICT | - | - | - |
WAT | -0.0325 | -32.6ms | early |
AWS | 0.85 | 85ms | slow |
という結果になりました。
まとめ
ローカルPCの時間が平均で200ms近く早く狂っているのがまず問題なのが見えたので、せめて±50msくらいの狂いに抑えたいと思いました。
他に、予想に反してWATの方がレイテンシー(平均で200〜300ms)が大きく自作したAWSのレイテンシー(平均で20〜50ms)が小さいため、狂いが大きいと予想していたのですが、WATの方が良い数値を記録しました。因みに、NICTのレイテンシーは平均で50〜80msでした。
(計測する直前には、EC2上で手動操作で時間合わせ行いました)
あと、気になったのは、ローカルPCとWATは時間が早い傾向にあり、AWSだけ遅れる傾向にあるのが気になりましたが、何故この傾向になるか原因解明にまでは至りませんでした。
この結果を受け、拡張内のNICTから時間取得している部分をWATで取得するように切り替え、しばらくの間様子を見てみたいと思います。
他、これ以外の良い方法ご存じの方いらっしゃいましたら、是非教えて頂きたいです!
ここまで読んで頂き、ありがとうございました。