シナプス技術者ブログ

シナプスの技術者公式ブログ。インターネットで、鹿児島の毎日を笑顔にします。

インターネットの速度測定の自動化

中野です。今回は、インターネットサービスプロバイダー(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アドレスに設定し、対象回線の速度測定を行う
  • 回線
  • speedtest.netのサーバ
    • 世界中のあちこちに設置されているサーバ
  • Amazon CloudWatch
    • 速度測定した結果の保存に使用
    • ダッシュボードにてグラフ表示し、複数回線の結果の比較や、トレンド分析を行う

速度測定ライブラリ

今回作った速度測定システムのうち、実際に「Speedtest by Ookla」の速度測定を行うプログラムは、Rubyで開発しgem(Rubyのライブラリ)として公開しています。

rubygems.org

その速度測定は、下記のような流れで行っています。

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」自体が、開発者向けのコマンドラインツールを公開しているようでした。

www.speedtest.net

今後、自社開発のライブラリと、Ooklaが作ったこのコマンドラインツールについて、速度測定の結果や、リソース使用量の比較などをしてみたいと思います。