中野です。今回は、インターネットサービスプロバイダー(ISP)を運営する中でも、重要な指標の1つである通信速度/回線速度を自動測定するシステムを構築したお話です。
この内容は「鹿児島Ruby会議01」、「SAKURAJIMA HOUSE 2020」のLTにて発表したもので、イベント時には触れられなかった部分や、その後の状況などを追加したものです。
ISPをとりまく課題
シナプスは、鹿児島県を主要な営業エリアとするISPで、1995年の創業以来、安定した高速なインターネット接続環境を提供すべく、時流にあわせて様々な接続サービスを提供してきました。
その安定・高速なインターネットを提供するために、自社ネットワーク内のルータ・スイッチ等の機器状態やトラフィックをモニタリングし、異常があれば24時間365日対応する体制で運用しています。
ただ、そういった体制で運用していても、稀にお客様より「光が遅いです!」といったお声をいただくこともあります。
その場合、技術部門にて外部接続インターフェースの輻輳や、内部の輻輳など状況確認などを行いますが、原因の特定にいたらない事も少なくありません。
これらの原因特定を難しくしている要因としては、下記のようなものがあります。
- 環境がそれぞれ異なる
- PCのスペック、OS、有線接続/無線接続、場所、距離
- 再現性に乏しい
- 昨日は遅かったけど、今日は速かったり・・・
- 輻輳している場所が分からない
- PC、ISP内、インターネット、サーバ
特に輻輳している場所の特定は困難で、下図のとおり、End-to-Endの通信に関わる全ての箇所が原因となり得ます。
お客様からの問合せに対し、原因特定も大切な事ですが、普段からインターネットの回線速度を把握しておく事も、安定した高速なインターネット接続環境を提供する上で大切な事となっています。
ただ、回線速度を正確に測定するのは難しく、また独自に測定をしていても、その結果がお客様の体感と差があるのは望ましくないので、お客様に近い状況を把握する事を目的に、インターネットの速度測定を自動化するシステムを作ってみました。
インターネットの速度を自動測定するシステム
インターネットの帯域/速度を測定するには、「Netperf」や「iperf」等でも可能ですが、お客様が一般的に利用されるものは、「Google社のインターネット速度テスト」や「Speedtest by Ookla」や「Fast.com」、「Cloudflare社のSpeed」だったりしています。
今回作った自動測定システムは、「Speedtest by Ookla」を用いることにしました。
環境
構築した環境は、このような構成となっています。 それぞれ、下記の機能を担っています。
- 速度測定マシン
- 実際に速度測定するマシン
- デフォルトゲートウェイを、測定対象回線のルータのIPアドレスに設定し、対象回線の速度測定を行う
- 回線
- 速度測定の対象となるインターネット接続回線
- 2020年7月1日時点では3つ
- シナプスの「シナプス光」
- シナプスの「ヒカリ・デラックスオプション」
- 他社のインターネット接続回線
- speedtest.netのサーバ
- 世界中のあちこちに設置されているサーバ
- Amazon CloudWatch
- 速度測定した結果の保存に使用
- ダッシュボードにてグラフ表示し、複数回線の結果の比較や、トレンド分析を行う
速度測定ライブラリ
今回作った速度測定システムのうち、実際に「Speedtest by Ookla」の速度測定を行うプログラムは、Rubyで開発しgem(Rubyのライブラリ)として公開しています。
その速度測定は、下記のような流れで行っています。
module SpeedtestNet def self.run(id = nil) # speedtest.netより、自身のパブリックIP、そのIPの緯度/経度を取得 config = SpeedtestNet::Config.fetch # speedtest.netより、速度測定サーバの一覧を受信 # 自身のパブリックIPに対する緯度/経度、測定サーバの緯度/経度より # 物理的な距離が近いもののうち、遅延が最小なサーバを選択 server = SpeedtestNet::Server.select_server(id) # サーバを指定して、ダウンロード速度の測定 download_results = SpeedtestNet::Download.measure(server) # サーバを指定して、アップロード速度の測定 upload_results = SpeedtestNet::Upload.measure(server) SpeedtestNet::Config.clear_cache # 測定結果を返す SpeedtestNet::Result.new(config.client, server, download_results, upload_results) end def self.list_server SpeedtestNet::Server.list end end
使い方
このライブラリでは速度測定のみを行っているため、Rubyでプログラムを書くことで、データベースに保存する事も可能ですし、Zabbix等の別のメトリクス監視ツールに送信する事も可能となっています。
シナプスでは、この測定結果をAmazon CloudWatchにメトリクスとして送信し管理しています。
このライブラリの簡単な利用方法は、下記のとおりです。
irb(main):001:0> require 'speedtest_net' irb(main):002:0> result = SpeedtestNet.run irb(main):003:0> result.download => 511615528.0 irb(main):004:0> result.pretty_download => "511.62 Mbps" irb(main):005:0> result.upload => 647852285.33333334 irb(main):006:0> result.pretty_upload => "647.85 Mbps" irb(main):007:0> result.latency => 0.028251 irb(main):008:0> result.pretty_latency => "28.251000 millisecond"
速度測定の結果
速度測定の結果は、Amazon CloudWatchにて、このような形でグラフ化しています。
このシステムの構築当初、グラフ表示部分は自社開発を検討していましたが、1から開発しなくても、他社のサービスを利用しても実現可能だったため、検討した結果Amazon CloudWatchを採用しました。
このシステムの使用目的は、直近の結果を確認するだけでなく、お客様からの問合せに合わせて、過去に遡って確認する必要があり、Amazon CloudWatchではそういった用途にも合致しています。
まとめ
シナプスではインターネット接続サービスを高速に安定して提供するために、自社ネットワーク内の様々な箇所をモニタリングしていますが、そのモニタリングだけでは見えづらい部分が、速度測定を継続的に行う事で見えてきつつあります。
今後も、バックボーンネットワークの利用状況や、この速度測定の結果を元に、シナプスでは設備増強・帯域増強を進めてまいります。
おまけ
今回の速度測定システムは2019年10月頃に作ったもので、できあがった頃に気付いたのですが「Speedtest by Ookla」自体が、開発者向けのコマンドラインツールを公開しているようでした。
今後、自社開発のライブラリと、Ooklaが作ったこのコマンドラインツールについて、速度測定の結果や、リソース使用量の比較などをしてみたいと思います。