Сетевой уровень часть 1. Слабонервным не читать!

Недавно я столкнулся с проблемой, нетривиальной для моего текущего проекта. Суть в следующем. Два приложения, расположенных физически на одном сервере, общаются друг с другом по принципу “PRODUCER -> CONSUMER” и все хорошо. Приложения обмениваются данными не по сети, а через файловую систему сервера, опять же из-за удобства и расположения приложений на оном(одном сервере). Как мы знаем приложение – это живой организм, функционал которого расширяется с появлением новых требований, а так же улучшается производительность уже разработанных. Как раз одну из задач оптимизации мне предоставилась возможность решить. Она состояла в сокращении пути доставки данных до конечной базы, минуя промежуточный, или, другими словами, интеграционный слой. Совсем незначительным нюансом оказался новый способ общения приложений. Consumer постоянно слушал один из портов сервелет-контейнера, на котором работает приложение Producer, которое время от времени передает данные на прослушиваемый порт. Consumer получает данные, обрабатывает и передает дальше в интеграционный слой. Как раз в этом месте требовалось незначительное улучшение, по сути просто изменений способа передачи обработанных данных. Эту часть задачи я реализовал достаточно быстро. Проблемы начались дальше – с тестированием изменений.  Для подобного рода общения через сеть unit-тестов будет недостаточно, в обязательном порядке нужно делать интеграционные тесты, причем с реализацией поведения реальной системы. Вот несколько ЗА для использования подобных тестов, даже если вы уверены, что ваш код работает:

  • Проверка крайних случаев. Помните, что обмен между приложения происходит в сети, пусть даже локальной. Возможны разного рода крайние случаи, связанные с потерей пакетов, большой нагрузкой порта, резкое увеличение посылаемых сообщений и так далее. Любого рода крайние случаи – тестируем.
  • Проверка работы в многопоточном режиме. Если несколько потоков слушает порт, то нужно проверить и исключить все возможные коллизии, связанные с последовательным потреблением данных.
  • Проверка переполнения очереди на строне Producer-приложения. Consumer может прекратить работу, тогда Producer должен каким-то образом реализовывать постановку данных в очередь, и при этом избежать ее переполнения.

Для проведения таких тестов необходимо создать подходящее тестовое окружение, имитирующее работу приложения через сеть. На бумаге все казалось просто:  реальная среда работы приложений в сети – локальная, значит достаточно организовать работы тестовой среды так же локально. Сделав это и послав первый поток байт принимающему приложения, я столкнулся с ошибкой 400 ( ошибка на стороне клиента). Полное непонимание. В чем проблема простой передачи потока байт внутри ЛОКАЛЬНОЙ СЕТИ!?

Длинная получилась подводка к главной теме статьи. Для формирования правильного представления работы в сети нужно знать принципы работы трех уровней сетевой архитектуры ISO/OSI: сетевого, транспортного и прикладного.  Последовательно начнем разбираться с работой каждого уровня, начиная с сетевого.

Сетевой уровень

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

Система работает следующим образом. Хост, у которого есть пакет для передачи. посылает его ближайшему маршрутизатору, либо в своей локальной сети, либо по двухточечному соединению интернет-провайдеру. На маршрутизаторе пакет хранится до тех пор, пока не будет получен целиком и не пройдет все проверки, включающие в себя верификацию контрольной суммы, проверку размера, заголовков пакета и т.п. После пакет передается по цепочке маршрутизаторов, пока не придет к получателю. Такой способ передачи называется store-and-forward.

Сетевой уровень для транспортного

Наверняка вам знаком следующий набор символов – TCP/IP.  Очевидно, что сетевой и транспортный уровень тесно связаны между собой. В частности, сетевой уровень предоставляет транспортному интерфейс  для использования своих собственных сервисов. Они должны удовлетворять следующим критериям:

  • Сервисы не должны зависеть от технологии маршрутизатора.
  • Транспортный уровень должен не зависеть от топологии сети
  • Сетевые адреса, доступные транспротному уровню, обязаны использовать единую систему нумерации между локальными и глобальными сетями

Типы сервисов сетевого уровня

Из-за не столь большого количества ограничений, разработчики сервисов имеют большую свободу в разработки сервисов сетевого уровня для транспортного.

Глобально сервисы можно разделить на две категории:

  • Сервис без установки соединения. Знаменитый протокол IP (Internet Protocol) является ярким примером сервиса без установки соединения. Он подразумевает, что сеть – не надежна. Маршрутизаторы могут выходить из строя, пакеты теряться на пути к адресату, поэтому вся ответственность за работу возлагается на хост. Основными функциями является SEND и RECIVE PACKET, т.е. отправка и получения пакета.
  • Сервис с установкой соединения. Этот подход пришел к нам из среды телефонных компаний. Прежде чем осуществлять операции отправки/приема пакетов, между отправителем и получателем устанавливается соединение. Минусом является накладные расходы, которые возникают в результате установки соединения, а так же проверки того, что соединение до сих пор установлено. Для этого хост отправителя время от времени отправляет контрольный пакет хосту получателя. Плюсом же такого подхода оказывается большее качество обслуживания, особенно важно это для объемного трафика реального времени – видео и аудио передача.

Сравнение сервисов с устанокой соединения и без

Углубимся в реализацию каждого сервиса для более детального сравнения.  Сервис сетевого уровня без установки соединения отправляет пакеты по отдельности, причем маршрут каждого пакета заранее не известен, он рассчитывается различными алгоритмами, которые в первую очередь направлены на решения проблем перегрузки сети и максимально приемлемого качества сервиса. Очевидно, что для больших сетей таких как интернет данный подход является более гибким, чем другой, предоставляемый сервисом с установкой соединения. Для него весь маршрут пакета должен быть установлен заранее. Сети с установкой соединения так же называются virtual-circuit network (сеть виртуального канала), без установки соединения – datagram network (дейтаграммные сети). Так же для дейтаграммных сетей существует требования к содержанию каждого пакета – он должен содержать полный адрес отправителя и получателя, это существенно утяжеляет пакет. Например, в IPv4, адрес имеет длину 32 бита, а в IPv6 уже 128 бит. Умножьте на два. Получается немало. В сети, основанной на установки соединения, каждый пакет содержит только короткий номер виртуального канала, размером 20 бит. Выше мы уже говорили о том, что маршрутизаторы дейтаграммных сетей не содержат никакой информации о состоянии сети, в отличии от виртуального канала – каждый такой канал требует место в таблице маршрутизатора. Безусловно, сервисы с установкой соединения является более качественным, хотя как вы понимаете организация такой сети очень и очень дорого обходится в финансовом плане. Качество в первую очередь достигается за счет полного контроля над сетью и хостами, это позволяет избегать заторов в сети, выделяя заранее ресурсы буфера, пропускной способности, времени центрального процессора, и когда будет начинаться передача пакетов, все эти ресурсы будут выделены. В дейтаграммных сетях избежать заторов гораздо сложнее, для этого применяются не всегда простые алгоритмы маршрутизации. Однако, не для каждых операций подходит сервис виртуальных каналов. Ярким примером является обработка коротких транзакций, которые должны выполняться максимально быстро, например, запрос магазина на верификацию кредитной карты. Одним из главных минусов сетей с установкой соединения является их низкая отказоустойчивость. В случае выхода из строя одного из маршрутизаторов или обрыва сети последствия будут фатальными. Даже если машины быстро восстановят, все виртуальные каналы, проходящие через данный маршрутизатор, будут потеряны. Сети без установки соединения продолжат работать, просто выбрав другой маршрутизатор или линию для передачи пакетов. Будут потеряны только пакеты, которые были в пути во время выхода и строя оборудования. Хотя даже они дойдут до адресата, потому что будут отправлены повторно. Какую сервис выбрать? Для корпоративной сети в случае достаточного количества ресурсов более предпочтительной будет сеть, основанная на установки соединения. Для внешних и масштабных сетей, отлично подойдёт сервис без установки соединения. Интернет, где вы сейчас читаете эту статью как раз такой.

Подходы к борьбе с перегрузкой на сетевом уровне

Перегрузка сети – это состояние, когда количество пакетов, передаваемых в сети одновременно, превышает пороговый уровень для данной сети. Так как перегрузка явна связана с пакетами, которые передает сетевой уровень, именно он должен в первую очередь решать эти проблемы. Хотя наиболее эффективным способом решения проблем, связанных с перегрузкой, оказываются действия на транспортном уровне. Получается, что сетевой и транспортный должны отрабатывать вместе. Обычно методы борьбы с перегрузкой на сетевом уровне классифицирует по временной школе, которая означает быстроту реакции после начала действий. Если перечислять от превентивных (медленных) до реагирующих (быстрых), то методы борьбы будут располагаться в следующем порядке:

  1. Обеспечение сети. Наиболее превентивная мера. Лучший способ избежать перегрузки – это правильно сконструировать сеть. Утопия, но не всегда. Там где высокий трафик и низкая пропускная способность обязательно возникнет затор. Для решени этой проблемы нужно просто добавить ресурсов или приобрести дополнительной пропускной способности. Это и называется обеспечением сети. Можно сказать, вовремя подносить снаряды.
  2. Маршрутизация с учетом состояния трафика. Для максимально полезного использования пропускной способности, маршруты строятся в соотвествии со специальными схемами трафика, которые меняются в течении суток по мере того, как пользователи в одной часовой зоне легли спать, а в другой просыпаются. Как один из способов отведения трафика с нагруженного маршрутизатора – изменение весового коэффициента кратчайшего пути.
  3. Управление доступом. Зачастую увеличение пропускной способности непозволительная роскошь. Тогда следующем методом на пути борьбы с перегрузкой будет простая блокировка новых соединений к сети, если она перегружена или приближается к перегрузке.
  4. Регулирование трафика. Более сложный способ в сравнении с предыдущим. Мы не блокируем подключения к сети, но выясняем кто из пользователей нагружает ее больше всего и просим его уменьшить трафик. Две сложности. Первая, это найти этого отправителя. Вторая, оповестить отправителя.
  5. Сброс нагрузки. Если ни один из способов не помогает, применяется самый кардинальный. В простом случае: туши свет! В более сложном, выбираются пакеты, которые будут попросту удалены из сети.

Статья получилась хардкорной и достаточно объемной. Это не все что я хотел рассказать о сетевом уровне. Во второй части мы поговорим о более простых вещах: качество обслуживания, требования приложений к сетевому уровню, аспектах сетей, способах объединения.

Оставить комментарий:

Ваш email не будет опубликован.