Я довольно часто пишу о том, что использую self-hosted сервисы. Они помогают мне хотя бы попытаться создать иллюзию независимости от всех этих Корпораций Добра, Зла и прочая и прочая. К тому же, такое у меня хобби - возиться с разнообразным железом (hardware) и софтом (software).

Сервисы - сервисами, но надо признать, они у меня не очень-то и нагружены, пользуюсь ими я и... Ну, в общем, не нагружены. Это одна из причин, почему мне не нужно супер-пупер железа для сервера, хотя файловые хранилища и сам сервер я все-таки подключил к роутеру кабелем - WiFi штука хорошая, но не всегда стабильно быстрая.

Конечно, что мой блог (развернут на платформе Ghost), что облачное хранилище (используется Nextcloud), что служба закладок (простой, а потому быстрый Shaarli) особых скоростей и не требуют. Но есть, все же, один сервис, для которого скорость важна - это медиасервис, в качестве которого, на текущий момент, у меня трудится Emby.

Это и не удивительно (не то, что сервисом выступает Emby, а то, что ему скорость важна) - ведь с помощью него я не только слушаю музыку, но также смотрю фильмы и сериалы из своей видео коллекции. И, что очень важно, не только дома по локальной сети, но и через интернет, где бы, собственно говоря, не находился. И если с музыкой все не так критично - ну не балуюсь я lossless форматами, то с видео требования становятся значительно строже.

На самом деле, существуют многочисленные рекомендации по поводу того, какой должна быть пропускная способность, чтобы можно было смотреть видео в том или ином разрешении. В частности, небезызвестный Netflix предлагает такую вот таблицу (приведу ее тут немного в сокращенном виде, оригинал можно посмотреть по ссылке):

  • просмотр видеоконтента в SD качестве - 3 мегабит в секунду
  • просмотр видеоконтента в HD качестве - 5 мегабит в секунду
  • просмотр видеоконтента в Ultra HD качестве - 25 мегабит в секунду

Некоторые источники советуют увеличивать эти цифры в полтора-два раза, чтобы уж наверняка ничего не тормозило.

Казалось бы, какие проблемы? Домашние поставщики интернета уже практически все обеспечивают скорости, превосходящие эти значения. Например, мой домашний провайдер предоставляет на давно уже архивном тарифе 71 мегабит в секунду и на вход и на выход, при этом, я не перехожу на 100 мегабитный новый тариф только потому, что для начала придется разорвать старый контракт, и только потом подключить новый тарифный план, что приведет к смене моего белого IP.

Да и мобильные операторы тоже стараются держать планку, и хотя, конечно, отстают, тем не менее уж 5 мегабит худо-бедно, но предоставляют.

Конечно, одно дело - декларация скорости провайдером, и другое - реальное положение вещей. Но тут надо сказать, что, к чести продавцов интернета, быль не сильно отличается от сказки. Вот несколько примеров замера скорости при работе через разных провайдеров:

Скорость от Virgin Connect
Скорость от Yota
Скорость от Skylink

Однако, в этих результатах есть определенная доля лукавства. Почему? Потому, что вы замеряете скорость между своим устройством и каким-то центром, который может находиться где-то далеко или, наоборот, близко - в принципе, можно даже указать его расположение. Но какой центр надо выбрать для замера, чтобы прикинуть скорость получения данных с домашнего сервера при просмотре видео из номера гостиницы где-то на просторах нашей необъятной Родины или в путешествиях по миру?

Безусловно, можно выбрать какой-нибудь, находящийся относительно недалеко от вашего дома, но вот только это никак не поможет оценить нужную вам скорость. Оборудование, канал, нагрузка - все будет отличаться от параметров домашнего сервера, соответственно, полученные цифры не будут иметь никакого отношения к действительности. Неужели все безнадежно? На самом деле - нет.

Существует такая программа, как iperf. Эта программа специально создана для того, чтобы измерять производительность сети. Является кросс-платформенным ПО, существуют реализации под Windows, Linux, Mac OS, Android, iOS, Unix и так далее. В настоящее время широко используются ее вторая и третья версия: iperf2 и iperf3. Конечно, существует и первая версия, iperf1, но, на данный момент, она распространена не очень широко. Версии не совместимы друг с другом и имеют достаточно серьезные отличия.

Любая версия может использоваться в качестве как сервера, так и клиента. Пропускная способность замеряется между двумя точками в одном или обоих направлениях. Может генерироваться как TCP, так и UDP трафик. Обычно, вывод iperf содержит временной отчет с информацией о размере переданного количества информации и измеренной пропускной способности.

На самом деле, я не хочу сейчас проводить мастер класс по использованию этой утилиты (тем более, что не очень-то и смогу), детально описывать ключи и параметры, а также отличия версий друг от друга. Все это можно, при желании, прочесть в документации. Моя задача (которую я сам себе и поставил 😉) заключается в том, чтобы рассказать о существовании этой программы и показать, как я ее использую у себя. С первой частью я закончил, перехожу ко второй.

Самым очевидным сценарием использования iperf для измерения скорости до собственного хоста является "поднятие" на нужном хосте сервера этого самого iperf. Тогда для замера пропускной способности останется запустить на каком-нибудь устройстве клиента и указать ему адрес сервера.

Как я уже упоминал, iperf можно запустить в качестве сервера, более того, его можно заставить работать в фоновом режиме - как демон в Linux или как сервис в Windows. Но я решил пойти другим путем - поднять на одной из своих серверных виртуалок контейнер с iperf, работающим в качестве сервера. Сказано - сделано. Но следует учитывать несколько нюансов.

Первое - версия iperf. В интернете идут споры о том, какая версия лучше. В одних местах предпочитают третью версию (она новее, разрабатывалась с нуля, поэтому лишена недостатков второй), в других - фаворитом выступает вторая, особенно после возобновления ее разработки (имеет ряд функций, отсутствующих в третьей). Мне убедительными кажутся обе точки зрения, поэтому я решил, что не буду выбирать, а буду использовать и вторую и третью версии одновременно.

Второе - используемый протокол. iperf умеет работать как по TCP, так и по UDP. Но если для третьей версии используемый протокол полностью контролируется клиентом, то для второй он определяется при запуске сервера. Так что, придется запускать, как минимум, еще один контейнер для проверки скорости по UDP.

В общем, стал я искать подготовленные образы на docker hub и, из предложенных, выбрал следующие:

Далее осталось дело за малым - загрузить, настроить и запустить образы. Для автоматизации этого процесса, я создал примерно такой файл docker-compose.yml:

# iperf 2/3 client web application
web-client:
  image: iitgdocker/iperf-web:latest
  restart: unless-stopped
  ports:
    - "80:80"
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - /host/dir/web/css:/var/www/html/css
    - /host/dir/web/images:/var/www/html/images
    - /host/dir/web/logs:/var/log/httpd
# iperf2 server on tcp port 5001
iperf2-tcp-5001:
  image: iitgdocker/iperf-server:latest
  restart: unless-stopped
  ports:
    - "5001:5001"
  volumes:
    - /host/dir/server/tcp-5001/logs:/data
  #environment:
    #- ARGS="--format m --print_mss --nodelay"
    #- TCP_WINDOW_SIZE="43K"
# iperf2 server on udp port 5001
iperf2-udp-5001:
  image: iitgdocker/iperf-server:latest
  restart: unless-stopped
  ports:
    - "5001:5001/udp"
  volumes:
    - /host/dir/server/udp-5001/logs:/data
  environment:
    - ARGS=-u
    #- ARGS="--format m --print_mss --nodelay"
    #- TCP_WINDOW_SIZE="43K"
# iperf3 server on udp/tcp port 5201
iperf3-tcp-udp-5201:
  image: networkstatic/iperf3
  restart: unless-stopped
  ports:
    - "5201:5201"
    - "5201:5201/udp"
  command: -s
  #volumes:
    #- /home/iperf/vol/server-tcp-5001/logs:/data
  #environment:
    #- ARGS="--format m --print_mss --nodelay"
    #- TCP_WINDOW_SIZE="43K"

Как водится, небольшие пояснения. Этот compose файл описывает четыре сервиса. Все - стартуют автоматически, если только не были остановлены явным образом (опция restart: unless-stopped).

Первый сервис (web-client) - web-приложение, управляющее клиентом iperf, для него описан маппинг порта (80), на котором приложение "слушает", а так же различных каталогов - для журналов, картинок (позволяет задать логотип) и стилей (дает возможность настаивать внешний вид приложения). Кроме того, прописан маппинг для /var/run/docker.sock. Это сделано для того, чтобы приложение смогло запускать нужные контейнеры[2].

Второй сервис (iperf2-tcp-5001) - сервер iperf2, который "слушает" tcp порт 5001. В описании все достаточно стандартно: прописан маппинг порта и каталога для журнала. Обратите внимание на закомментированные строки environment - если их раскомментировать (и, при необходимости, отредактировать), то можно указать параметры запуска сервера[3].

Третий сервис (iperf2-udp-5001) - сервер iperf2, который "слушает" udp порт 5001. Описание очень похоже на описание сервиса iperf2-tcp-5001, с той лишь разницей, что на этот раз указано значение ключа ARGS для окружения (environment): -u, что, собственно, и определяет использование протокола UDP.

Ну и последний, четвертый, сервис (iperf3-tcp-udp-5201) - сервер iperf3, который слушает порт 5201 и по протоколу TCP и по протоколу UDP. Этот контейнер поднимается из образа другого автора, поэтому передача параметров ранее описанным методом не предусмотрена, Docker файл совершенно другой. Однако, обратите внимание на строку command: -s. Это стандартный метод передать параметры в ENTRYPOINT, в качестве которого в этом образе выступает сам iperf3.

Еще один момент. В файле указаны каталоги, которые, при реальной работе, следует заменить на что-то, что существует в рамках системы, на которой все это хозяйство разворачивается. Речь про /host/dir/web/... и /host/dir/server/.... Я, обычно, создаю пользователя под сервис, в его домашнем каталоге делаю подкаталог и уже там произвожу монтирование каталогов из контейнера. Главное, не оставляйте эти фейковые каталоги.

Теперь, дело за малым - "поднимаем" контейнеры и в пределах локальной сети можем мерить скорость хоть так, хоть этак.

docker-compose up -d
Старт сервисов в контейнерах

А вот чтобы выйти за пределы домашней сети, надо выполнить еще небольшую работу: "пробросить" порты на роутере, чтобы трафик "дошел" до нужных серверов.
Проброс портов

Осталось потерпеть совсем немного 😉. Сервисы мы подняли, теперь можно ими воспользоваться, то есть, измерить пропускную способность. Начнем с мобильных клиентов. Пусть первым из них будет PingTools Pro[4].
Выбираем нужный инструмент

Надо отметить, что для нормальной работы нужен сервер iperf3, по крайней мере, когда у меня был поднят только сервер второй версии, проверка скорости не проходила. Итак, вбиваем нужный адрес, жмем Startи наслаждаемся результатами:
Результат замера пропускной способности канала

Второй программой, заслуживающей упоминания, является Magic iPerf. Использовать ее несколько сложнее - надо разбираться в параметрах командной строки iperf2и iperf3, но, по крайней мере, она работает с обеими версиями:
Проверка при помощи Magic iPerf (iperf2)

Ну и, напоследок, пример того, как выглядит web-приложение, которое может при помощи iperf (в режиме клиента) измерять скорость до указанного сервера (это наш первый сервис в compose файле):
Измерение скорости при помощи web-приложения

Про это приложение надо сказать следующее: оно ориентировано на использование Dockerобразов от того же автора. Но в нашем compose файле используется только один нужный образ - с iperf2, а для iperf3 исрользуется образ другого авторства, так как не получилось у меня заставить работать образ iitgdocker/iperf-server:3.1.3. Поэтому, не смотря на то, что в выпадающем списке можно выбрать Iperf3, работать в этом режиме приложение будет не совсем корректно. Исправить это можно, включив в compose файл еще один сервис, построенный на базе упоминавшегося образа версии 3.1.3, если, конечно, он у вас заработает.

Вот теперь, пожалуй, тему с использованием iperf для измерения пропускной способности канала можно считать закрытой (хотя, и весьма поверхностно). Но к теме измерения скорости я еще вернусь, всенепременно...


  1. Несмотря на то, что в описании упоминается возможность запуска контейнера с iperf3 в качестве сервера (при использовании определенного тэга), добиться работоспособности такой конфигурации не удалось. ↩︎

  2. Более подробное описание доступно на docker hub-е ↩︎

  3. Не удивляйтесь отсутствию ключа -s (запуск сервера) - он прописан в командном файле run.sh, который задан в качестве ENTRYPOINT в Docker файле ↩︎

  4. У меня установлена версия Pro, но думаю, что и в обычной версии есть нужный инструментарий. ↩︎