В этом сообщении мы расскажем о пограничной сетевой части инфраструктуры трафика Dropbox. Это расширенная расшифровка нашей презентации NginxConf 2018. Примерно в то же время в прошлом году мы описали низкоуровневые аспекты нашей инфраструктуры в Оптимизирующих веб-серверах для высокой пропускной способности и низкой задержки. На этот раз мы рассмотрим такие вещи, как наши точки присутствия по всему миру, GSLB, RUM DNS, L4 loadbalancers, настройка nginx и его динамическая конфигурация и немного проксирования gRPC.
Содержание статьи
Шкала Dropbox
Dropbox имеет более полумиллиона зарегистрированных пользователей, которые доверяют нам экзабайты данных и петабайт соответствующих метаданных. Для команды Traffic это означает миллионы HTTP-запросов и терабайтов трафика. Чтобы поддержать все это, мы создали обширную сеть точек присутствия (PoP) по всему миру, которые мы называем Edge.
Зачем нам нужен Edge?
Многие из читателей знают основную идею CDN: прекращение соединений TCP и TLS ближе к пользователю приводит к улучшению пользовательского интерфейса из-за значительно уменьшенных латентностей. Вот краткое напоминание: сравнение задержки HTTP-запроса, сделанной непосредственно в центре обработки данных, и тот же запрос, сделанный через PoP:
Числа приведены на основе:
20 мс латентности PoP↔user, латентности 150 мс PoP↔DC, времени выполнения сервера 100 мс
Как вы можете видеть, просто положив PoP близко к пользователю, можно улучшить латентность более чем на два.
Но это еще не все. Наши пользователи значительно выигрывают от более быстрой загрузки и загрузки файлов. Давайте посмотрим, как латентность влияет на рост TCP-перегрузки (CWND) при загрузке файлов:
Здесь мы видим сравнение соединений с низкой и высокой задержкой, которое представляет собой соединение с PoP и без него:
- Клиент с более низкой задержкой прогрессирует медленным запуском быстрее, потому что это процесс, связанный с RTT
- Этот клиент также оседает на более высоком пороге для предотвращения перегрузки, из-за более низкого уровня потери пакетов. Это происходит потому, что этим пакетам нужно тратить меньше времени на публичные и, возможно, перегруженные интернет-ссылки — как только они попадают в PoP, мы берем их в свою собственную магистральную сеть
. Помимо всех показателей производительности, связанных с задержкой, построение собственной сети Edge дает нам (инженерам трафика) большую свободу: например, мы можем легко экспериментировать с новыми протоколами низкого и высокого уровня, внешние и внутренние алгоритмы балансировки нагрузки, а также более тесно интегрированы с остальной инфраструктурой.
Мы можем делать такие вещи, как исследования эффектов контроля перегрузки BBR на скорости загрузки файлов, задержки и потери пакетов.Выбор местоположений PoP
На сегодняшний день Dropbox имеет 20 PoP по всему миру:
Мы только что анонсировали наш PoP в Торонто, и к концу года он получит еще два в Скандинавии.
В 2019 году мы планируем посмотреть на увеличение нашего края, исследуя жизнеспособность PoP в LATAM, Middle East и APAC.
Процесс выбора PoP, который был легким вначале, теперь становится все более сложным: нам нужно учитывать мощность магистрали, пиринговую связь, подводные кабели, но, самое главное, расположение по отношению ко всем другим PoP, которые у нас есть.
Текущая процедура выбора PoP ориентирована на человека, но с алгоритмом. Даже с небольшим количеством PoP без вспомогательного программного обеспечения может быть сложно выбрать, например, PoP в Бразилии и PoP в Австралии. Проблема сохраняется, поскольку число PoP растет: например, какое место лучше всего понравится пользователям Dropbox, в Вене или Варшаве?
Мы пытаемся изменить новое размещение PoP между выбором наиболее выгодного PoP для существующих и потенциальных пользователей Dropbox.
Крошечный сценарий помогает нам устранить проблему:
- Разделение Земли на 7-й уровень s2-областей
- Размещение всех существующих PoP
- Вычисление расстояния до ближайшего PoP для всех регионов, взвешенных по «населению»
- Выполняя исчерпывающий поиск, чтобы найти «лучшее» место для нового PoP
- Добавление его на карту
- Переход к шагу 3 и т. Д.
Под «населением» можно использовать практически любую метрику, которую мы хотим оптимизировать, например общее количество людей в этой области или количество существующих / потенциальных пользователей. Что касается функции потерь для определения оценки каждого места размещения, можно использовать что-то стандартное, например, как L1 или L2. В нашем случае мы пытаемся перекомпенсировать эффекты латентности по пропускной способности TCP.
Некоторые из вас могут видеть, что проблема здесь может быть решена с помощью более сложных методов, таких как Gradient Descent или Bayesian Optimization. Это действительно так, но поскольку наше проблемное пространство настолько мало (есть ячейки размером менее 100 К 7-го уровня s2), мы можем просто переборщить с ним и получить окончательно оптимальный результат, а не тот, который может застрять на локальном оптимальном .
GSLB
Начнем с самой важной части Edge-GSLB. GSLB отвечает за загрузку пользователей через PoP. Обычно это означает, что каждый пользователь должен подключиться к ближайшему PoP, если он не имеет пропускную способность или не поддерживается.
GSLB называется «самой важной частью» здесь, потому что, если он часто меняет пользователей на субоптимальные PoP, то это делает сеть Edge бесполезной и потенциально даже вредит производительности.
Ниже приводится обсуждение широко используемых методов GSLB, их плюсов и минусов и того, как мы используем их в Dropbox.
BGP anycast
Anycast — самый простой метод балансировки нагрузки, основанный на протоколе базовой интернет-маршрутизации, BGP. Чтобы начать использовать anycast, достаточно просто начать рекламировать одну и ту же подсеть от всех PoP, и интернет будет автоматически доставлять пакет в «оптимальный».
Несмотря на то, что мы получаем автоматический переход на другой ресурс и простоту настройки, у anycast есть много недостатков, поэтому давайте перейдем к ним один за другим.
Anycast performance
Выше мы упоминали, что BGP выбирает «оптимальный» маршрут, и по большей части это правда. Проблема в том, что BGP ничего не знает о задержке связи, пропускной способности, потери пакетов и т. Д. Как правило, при наличии нескольких маршрутов к месту назначения он просто выбирает номер с наименьшим количеством перелетов.
. Балансировка на основе Anycast в основном оптимальна, но ведет себя плохо на высоких процентилях.
Это справедливо для небольшого и среднего числа PoP. Но есть гипотеза о том, что «критическая» вероятность пропуски (например, вероятность маршрутизации пользователя на другой континент) в сети anycasted резко падает с количеством PoP. Поэтому возможно, что с увеличением числа PoP, anycast может в конечном итоге начать превосходить GeoDNS. Мы продолжим работу над тем, как наша производительность в исполнении anycast масштабируется с количеством PoP.
Движение руля
С помощью anycast у нас очень ограниченный контроль над трафиком. Трудно явно перемещать трафик с одного PoP на другой. Мы можем осуществлять управление трафиком с использованием атрибутов MED, добавляя AS_PATH к нашим анонсам и путем прямой связи с провайдерами трафика, но это не масштабируется.
Также обратите внимание, что в N-WLLA OMNI мнемоника
AS_PATH
находится где-то посередине. Это фактически означает, что его можно легко переопределить администратором, и на практике это делает BGP anycast выбранным «самым дешевым» маршрутом, а не «ближайшим» или «самым быстрым».
Еще одно свойство anycast заключается в том, что изящная утечка PoP невозможна, поскольку BGP балансирует пакеты, а не соединения. После изменения таблицы маршрутизации все всплывающие сеансы TCP сразу будут перенаправлены на следующий лучший PoP, и пользователи получат RST оттуда.
Устранение сбоев в работе
. Обоснование маршрутизации трафика с помощью anycast становится очень нетривиальным, поскольку оно связано с состоянием интернет-маршрутизации в данный момент времени. Устранение проблем с производительностью с помощью anycast сложно и обычно связано с большим количеством трассировок, очков и обратной связи с провайдерами на этом пути.
Обратите внимание, что, как и в случае утечки PoP, любое изменение связи в Интернете может нарушать подключения пользователей к любым IP-адресам. Устранение неполадок, связанных с прерывистым подключением из-за изменений маршрутизации в Интернете или неисправного / неправильно сконфигурированного оборудования, может быть сложным.
Ниже приведен пример эпического устранения неполадок Anycast от Fastly NOC из списка рассылки NANOG: рассказ поставщика услуг об отслеживании TCP RST.
TL; DR SYN, проходящие через маршрутизатор, имели разные TTL и в то же время это поле IP использовалось для хэширования потока ECMP.
Инструменты
Вот несколько трюков, которые вы можете использовать, чтобы упростить поиск неисправностей (особенно в случае anycast).
Конечно, наличие случайного идентификатора запроса, связанного с каждым запросом, который проходит через систему и может быть прослежен в журналах, является обязательным. В случае Edge также полезно откликнуть заголовок с именем PoP, к которому вы подключены (или встроить его в уникальный идентификатор запроса).
Другой полезной вещью, которая обычно используется, является создание «отладочных» сайтов, которые могут предварительно собрать все данные об устранении неполадок для пользователя, чтобы они могли прикреплять их к билету поддержки, например: github-debug.com, быстро отлаживать .com, и, конечно, dropbox-debug.com, который был сильно вдохновлен ими.
Проекты команды трафика, такие как dropbox-debug, статическое предварительное сжатие Brotli, оценка и развертывание BBR, RUM DNS и многие другие, вышли из Hack Week: событие всей компании, которое вдохновляет нас попробовать что-то новое и захватывающее!
Anycast at Dropbox
При всем этом мы все еще используем anycast для наших доменов APEX, таких как dropbox.com (без www) и как резерв в случае крупных атак DDoS.
GeoDNS
Давайте поговорим о другом распространенном решении для внедрения GSLB: GeoDNS. В этом подходе каждый PoP имеет свое уникальное одноадресное IP-адрес, а DNS отвечает за передачу разных IP-адресов различным пользователям в зависимости от их географического местоположения.
Это дает нам контроль над рулевым управлением и обеспечивает изящный сток. Стоит отметить, что любые рассуждения о настройке на основе одноадресной передачи намного проще, поэтому устранение неполадок становится проще.
Как вы можете видеть, существует много переменных: мы полагаемся на поставщика DNS, угадывающего IP-адрес пользователя их DNS-преобразователем (или доверяем данным CSN EDNS), затем угадывая местоположение пользователя по их IP-адресу, а затем приближаем физическую близость к задержке.
Обратите внимание, что различные поставщики DNS, скорее всего, получат различные решения, основанные на их алгоритмах и качестве своей базы данных GeoIP, поэтому мониторинг производительности настройки DNS с несколькими провайдерами намного сложнее.
Кроме того, у DNS также есть серьезная проблема с устаревшими данными. Короче говоря: DNS TTL — ложь. Несмотря на то, что у нас есть TTL на одну минуту на www.dropbox.com, для истощения 90% трафика все еще требуется 15 минут, и может потребоваться полный час, чтобы слить 95% трафика:
Здесь мы также должны упомянуть множество встроенных устройств, использующих Dropbox API, которые варьируются от видеокамер до интеллектуальных холодильников, которые имеют тенденцию к разрешению DNS-адресов только во время включения питания.
GeoDNS на Dropbox
. Наша система DNS немного изменилась за последние несколько лет: мы начали с простых сопоставлений по континенту → PoP, затем переключились на страну → PoP с данными сопоставления состояний для обслуживания сетевого трафика в больших странах, таких как США, Канада и т. д. На данный момент мы жонглируем относительно сложной маршрутизацией на основе LatLong с переопределениями на основе AS, чтобы обойти причуды в подключении к Интернету и пиринге.
Гибридная одноадресная передача / anycast GSLB
Давайте вкратце рассмотрим один из составных подходов к GSLB: гибридная одноадресная / мелочная настройка. Объединение одноадресных и анонсированных анонсов наряду с отображением GeoDNS позволяет получить все преимущества одноадресной передачи, а также возможность быстрого отключения PoP в случае сбоя.
Можно включить этот гибридный GSLB, объявив как одноадресную подсеть PoP (например, / 24), так и одну из своих суперсетей (например, / 19) от всех PoP (включая себя).
Это означает, что каждый PoP должен быть настроен для обработки трафика, предназначенного для любого PoP: у него есть все VIP-персоны от всех PoP в конфигурациях прокси-серверов BGP-демонов / L4-балансиров / L7.
Такой подход дает нам возможность быстро переключаться между одноадресными и anycast-адресами и, следовательно, мгновенный резерв, не дожидаясь истечения срока действия DNS TTL. Это также позволяет изнашивать PoP и все другие преимущества управления DNS-трафиком. Все это связано с относительно небольшими эксплуатационными расходами более сложной настройки и может вызвать проблемы с масштабируемостью, когда вы достигнете высоких тысяч VIP-персон. С яркой стороны все конфигурации PoP теперь становятся более равномерными.
Показатели реального пользователя
Все рассмотренные до сих пор методы GSLB имеют одну критическую проблему: ни одна из них не использует фактическую воспринимаемую пользователем производительность в качестве сигнала, а вместо этого полагается на некоторые приближения: BGP использует количество переходов в качестве сигнала, в то время как GeoIP использует физическую близость , Мы хотим это исправить, используя конвейер коллекции Real User Metrics (RUM) на основе данных о производительности наших настольных клиентов.
Компании, у которых нет приложения, обычно делают измерения латентности с помощью prober на основе JS на своем веб-сайте.
Несколько лет назад мы вложили средства в систему измерения доступности в наших настольных клиентах, чтобы помочь нам оценить достоверную надежность нашей сети Edge. Система довольно проста: время от времени образец клиентов проводит измерения доступности для всех наших PoP и отчитывается о результатах. Мы расширили эту систему, чтобы также регистрировать информацию о задержках, которая дала нам достаточные данные, чтобы начать строить нашу собственную карту Интернета.
Мы также создали отдельную подменю resolver_ip → client_ip, объединив журналы DNS и HTTP-сервера для HTTP-запросов к случайному субдомену подстановочной DNS-записи. В дополнение к этому мы применяем крошечный бит пост-обработки для EDNS ClientSubnet-совместимых преобразователей.
Мы объединяем агрегированные задержки, resolver_ip → client_ip map, BGP fullview, информацию о пирингах и данные о емкости из нашей системы мониторинга для создания окончательной карты client_subnet → PoP.
Мы также рассматриваем возможность добавления сигнала из журналов веб-сервера, поскольку у нас уже есть данные TCP_INFO, включая количество повторных передач, cwnd / rwnd и rtt.
После этого мы упаковываем эту карту в дерево radix и загружаем ее на DNS-сервер, после чего сравниваем ее с решениями anycast и GeoIP.
Особенности создания карт сейчас находятся в прямом эфире: мы пробовали (и продолжаем проверять) разные подходы: от простого запроса HiveQL, который делает сборку данных на основе ML, например, Random Forests , стопки XGBoosts и DNN. Сложные решения дают немного лучшие, но в конечном итоге сопоставимые результаты за счет более длительной подготовки и сложной инженерной сложности.
По крайней мере, на данный момент мы придерживаемся решения, которое легче рассуждать и проще устранять.
Анонимность и агрегация данных
Мы анонизируем и суммируем все данные о задержке и доступности по подсети / 24 в случае IPv4 и / 56 в случае IPv6. Мы не работаем напрямую с IP-адресами реальных пользователей и применяем строгие политики ACL и хранения для всех данных RUM.
Очистка данных
Очистка данных — очень важный шаг в конвейере данных карты. Вот несколько общих шаблонов, которые мы нашли во время построения нашей карты:
- Стандартный
Таймер GetTickCount64
в Windows квантуется примерно на 16 мс. В нашем клиенте Python мы переключились наtime.perf_counter ()
. - TCP и HTTP-зонды менее надежны, чем HTTPS. Это в основном связано с захватом IP и DNS в дикой природе. Хорошими примерами этого являются портативные порталы Wi-Fi.
- Даже уникальные запросы DNS могут быть получены несколько раз. Как из-за потерянных ответов, так и упреждающего обновления кеша некоторыми DNS-серверами даже дублированные запросы, такие как
UUID4.perf.dropbox.com
могут быть дублированы. Мы учитываем это при присоединении к журналам HTTP и DNS. - И, конечно, есть все виды странных временных результатов от негативных и субмикросекундных результатов к тем, которые старше нашей вселенной (они, вероятно, пришли из другой).
Экстраполяция данных
В настоящее время мы используем следующие методы для спекулятивного расширения результирующей карты:
- Если все образцы для AS попадают в один и тот же «лучший» PoP, мы считаем, что все диапазоны IP, объявленные этой AS, должны перейти к этому PoP.
- Если у AS есть несколько «лучших» PoP, мы разбиваем их на объявленные диапазоны IP. Для каждого из них мы предполагаем, что если все измерения в диапазоне заканчиваются на одном и том же PoP, мы можем экстраполировать этот выбор на весь диапазон.
Этот метод позволяет нам удвоить покрытие нашей карты, сделать ее более устойчивой к изменениям и создать карту с использованием меньшего набора данных.
Устранение неполадок DNS-карты
. Когда построена карта на основе RUM, важно иметь возможность оценить, насколько она хороша, используя одно значение, что-то вроде оценки F1, используемой для двоичного кода классификация или оценка BLEU для оценки машинного перевода. Таким образом, нельзя не только автоматически предотвращать плохие карты, а также сравнивать качество различных итераций карт и алгоритмов построения.
Еще один распространенный подход для оценки карты — проверить его против подмножества данных, которые процесс обучения не видел.
Для интерактивной нарезки и обработки данных и устранения неполадок ad-hoc, мы сопоставляем подсети обратно в координаты lat / long, суммируем их статистику по регионам h3 и затем рисуем их с помощью kepler.gl. Это очень полезно для быстрого просмотра карт с низким рейтингом.
Мы пошли с h3 здесь вместо s2, потому что Kepler имеет встроенную поддержку для него, и, как правило, h3 имеет более простой интерфейс Python, поэтому нам легче экспериментировать с визуализацией.
Шепот: также шестиугольники смотри кулер =)
Такой же подход можно использовать для визуализации текущей производительности, разницы по неделям, разницы между версиями базы данных GeoIP и т. Д.
Здесь вы можете четко видеть, где находятся наши PoP. Все большие пятна синего и фиолетового цветов получают их PoPs в конце этого года или в следующем году.
Еще один способ визуализации IP-карт — пропустить весь шаг отображения GeoDNS и рассчитать IP-адреса на 2D-плоскости, сопоставляя их на кривой заполнения пространства, например. Гильберта. Можно также разместить дополнительные данные в размерах высоты и цвета. Этот подход потребует некоторой тяжелой регуляризации, чтобы он мог потребляться людьми и даже больше волшебства ColorBrewer2, чтобы быть эстетически приятным.
RUM DNS в Dropbox
DNS на основе RUM является активно развивающимся проектом, и мы еще не отправили его нашим основным VIP-персонам, но данные, которые мы собрали из наших экспериментов GSLB, показывают что это единственный способ, которым мы можем правильно использовать более 25-30 PoP. Этот проект станет одним из наших главных приоритетов в 2019 году, поскольку даже показатели, собранные с прототипов ранних карт, показывают, что он может повысить эффективность нашей пограничной сети на 30% с использованием RUM DNS.
Он также предоставит все побочные продукты, необходимые для Явного Loadbalancer … Говоря о том, что …
Явный нагрузочный баланс
Быстрая заметка о еще одном более ясном способе маршрутизации пользователей в PoP. Все эти танцы с угадыванием IP-адреса пользователей на основе их разрешения, эффективности GeoIP, оптимальности решений, сделанных BGP и т. Д., Больше не нужны после того, как запрос прибывает в PoP. Потому что в тот момент мы знаем IP-адрес пользователей и даже имеем для них RTT-измерение. В этот момент мы можем перенаправить пользователей на более высокий уровень, например, внедрить ссылку на конкретный PoP в html или передать другой домен настольному клиенту, пытающемуся загрузить файлы.
Та же самая IP-карта PoP, которая была построена для RUM DNS, может быть повторно использована здесь, теперь показана как служба RPC.
Этот метод балансировки позволяет очень гранулировать управление трафиком даже на основе информации о ресурсах, например, идентификатора пользователя, размера файла и физического местоположения в распределенном хранилище. Другим преимуществом является почти немедленное истощение новых связей, хотя ссылки на ресурсы, которые когда-то были выданы, могут жить в течение длительных периодов времени.
Здесь можно придумать очень сложные схемы, например, мы можем отбросить целые URL-адреса, которые
в информации о встраивании имени домена для внешней маршрутизации на основе DNS и в то же время вставлять информацию для внутренней маршрутизации внутри пути / queryargs, что позволит PoP сделать более оптимальное решение маршрутизации. Другой подход заключается в том, чтобы добавить эти дополнительные данные в виде непрозрачного блоба в зашифрованный / подписанный файл cookie.
Все эти возможности звучат захватывающе, поэтому следует проявлять осторожность, чтобы не перекомплементировать систему.
Явный loadbalancing в Dropbox
В настоящее время мы не используем это как внешний метод балансировки нагрузки, а вместо этого полагаемся на него для внутренней повторной маршрутизации. Команда трафика активно готовит основу для ее использования.
Внутри точки присутствия
Теперь давайте обсудим, что происходит, когда трафик действительно прибывает в PoP.
Сетевая архитектура
PoPs состоят из сетевого оборудования и наборов серверов Linux. Средний PoP имеет хорошую связность: магистраль, несколько транзитов, публичный и частный пиринг. Увеличивая сетевое подключение, мы уменьшаем количество пакетов времени в общедоступном Интернете и, следовательно, сильно уменьшаем потери пакетов и повышаем пропускную способность TCP. В настоящее время около половины нашего трафика поступает от пиринга.
Dropbox имеет открытую политику пиринга, поэтому не стесняйтесь обращаться к нам по всему миру.
Вы можете узнать больше о настройке сети в статье «Эволюция пограничной сети Dropbox».
L4 loadbalancer
Наши PoP состоят из нескольких ящиков nginx, которые действуют как L7 proxy и L4 loadbalancers (L4LBs), распространяющие нагрузку между ними.
Мы используем стандартные методы для масштабирования L4LB и повышаем их устойчивость к отказу: BGP ECMP, DSR и последовательное хеширование. IPVS действует как наш dataplane — loadbalancer уровня ядра с netlink API. Модуль ядра IPVS предоставляет нам отслеживание состояния, подключаемые алгоритмы планирования и инкапсуляцию IP-in-IP для DSR.
Есть два основных подхода для создания высокопроизводительных пакетных процессоров прямо сейчас.
Ядро
Выполняет пакетную обработку в начале сетевого стека. Это позволяет повторно использовать структуры данных ядра и процедуры разбора TCP / IP. Уже довольно давно Linux имеет модули IPVS и netfilter, которые могут использоваться для балансировки уровня соединения. В последних ядрах есть комбо eBPF / XDP, что позволяет более безопасный и быстрый способ обработки пакетов в пространстве ядра. Тесная связь с ядром, хотя и имеет некоторые недостатки: для обновления такого LB может потребоваться перезагрузка, очень строгие требования к версии ядра и сложные интеграционные тесты.
Этот подход используется такими компаниями, как Facebook и Dropbox.Пользовательское пространство
Создайте виртуальное сетевое устройство PCIe с помощью SRIO-V, обходите ядро через DPDK / netmap / etc и получите очереди RX / TX в адресном пространстве приложения. Это дает программистам полный контроль над сетью, но парсинг tcp / ip, структуры данных и даже управление памятью должны выполняться вручную (или предоставляться сторонней библиотекой). Тестирование такого рода настроек также намного проще.
Этот подход используется такими компаниями, как Google и Github.
В настоящее время мы используем нашу версию исходного хеширующего модуля homebrew, но начиная с linux-4.18 существует реализация Maglev Hash: [ip_vs_mh] (https://github.com/torvalds/linux/blob/master/ сеть / Netfilter / IPVS / ip_vs_mh.c)
. По сравнению с Ketama, Maglev Hash отделяет часть хэш-отказоустойчивости для более равномерного распределения нагрузки по всему серверу и скорости поиска.
Вы можете больше узнать о Maglev Hash в бумаге Maglev или утренней бумаге или быстро просмотреть резюме последовательные хэш-методы от Дамиана Гриски.
Мы принимаем входящие пакеты на основе 5-кортежей (proto, sip, dip, sport, dport), которые еще больше улучшают распределение нагрузки. Это, к сожалению, означает, что любое кеширование на стороне сервера становится неэффективным, так как различные соединения от одного и того же клиента, скорее всего, окажутся на разных бэкэндах. Если наш Edge полагался на локальное кэширование, мы могли бы использовать режим хеширования 3-х кортежей, где мы будем использовать только хэш (протокол, sip, dip).
Еще один интересный факт заключается в том, что L4LB необходимо будет выполнить некоторую специальную обработку ответов ICMP Packet Too Big, поскольку они будут происходить из другого хоста и, следовательно, не могут использовать простой внешний хэширование заголовков, но вместо этого должны быть хешированы основанный на заголовках tcp / ip в полезной нагрузке пакета ICMP. Cloudflare использует другой подход для решения этой проблемы с помощью
[pmtud] (https://github.com/cloudflare/pmtud)
: передача входящих ICMP-пакетов во все поля в PoP. Это может быть полезно, если у вас нет отдельного слоя маршрутизации и есть пакеты ECMP прямо на ваши прокси-серверы L7.
Контрольная плоскость для L4LB в настоящее время написана на Go и тесно интегрирована с нашей инфраструктурой и отвечает за онлайн-реконфигурацию, подключение к BGP и проверку работоспособности бэкэндов.
Проверки работоспособности любого инкапсулируемого LSRL на основе DSR очень сложны. Особое внимание должно быть уделено проверке работоспособности через тот же процесс инкапсуляции пакетов, что и сама передача данных, в противном случае легко начать отправлять трафик в ящик, в котором еще нет надлежащего настроенного туннеля.
Ключевые свойства L4LBs:
- Они устойчивы и масштабируемы по горизонтали. Поскольку L4LB не прерывает TCP-соединение и полагается на согласованное хеширование для планирования соединений, мы можем безопасно добавлять / удалять L4LB, потому что все они будут последовательно маршрутизировать пакеты в нужное место назначения
- Изящное удаление / добавление прокси-серверов L7. Поскольку L4LB также имеют таблицу отслеживания соединений, даже если набор внутренних компонентов изменяется, они будут продолжать маршрутизацию существующих подключений к ним, что является ключевой отличительной особенностью простого ECMP
- Позволяет горизонтальное масштабирование прокси-серверов L7. L4LB достаточно быстр, чтобы быть ограниченным сетью, что означает, что мы можем масштабировать прокси-серверы L7 до тех пор, пока у нас не будет достаточной пропускной способности
- Поддерживает любой протокол на основе IP
- Поддерживает любой алгоритм хэширования. Maglev? Rendezvous? Мы можем быстро поэкспериментировать с любым из них
- Поддерживает любую политику хэширования. 3-кортеж? 5-кортеж? Идентификатор соединения QUIC? Легко!
Не говоря уже о том, что теперь мы можем конвертировать практически любой сервер в производство в высокопроизводительный loadbalancer, просто запустив на нем двоичный файл.
Что касается будущей работы, у нас есть несколько вещей, которые мы хотим попробовать. Во-первых, замените dataplane маршрутизации либо решением DPDK, либо XDP / eBPF, либо, возможно, просто интегрируйте проект с открытым исходным кодом, такой как Katran. Во-вторых, в настоящее время мы используем IP-in-IP для пакетной инкапсуляции, и пришло время переключить его на нечто более современное, как GUE, что является более дружественным NIC с точки зрения поддержки рулевого управления и разгрузки
Прокси L7 (nginx)
Having PoPs close to our users decreases the time needed for both TCP and TLS handshakes, which essentially leads to a faster TTFB. But owning this infrastructure instead of renting it from a CDN provider allows us to easily experiment and iterate on emerging technologies that optimize latency and throughput sensitive workloads even further. Let’s discuss some of them.
TCP
Starting from the lowest layers of the stack here is a Fair Queueing packet scheduler example: not only because it introduces fairness between flows, but also adds “pacing” to the upper level protocol. Let’s look at some specific examples.
Without fair queueing, packets will be dumped to the network as they arrive from the TCP stack, which will lead to the huge Head-of-Line blocking further down network stack.
With FQ packets of different flows are interleaved and one flow no longer blocks another.
Without pacing, if you want to send multiple megabytes of data to the user, and current TCP congestion window allows that, then you’ll just dump thousands of packets onto the underlying network stack.
With pacing, TCP will hint packet scheduler a desired sending rate (based on the congestion window and rtt) and then scheduler is responsible for submitting packets to the network stack every once in a while to maintain that steady sending rate:
FQ comes at a relatively low CPU cost of around 5%, but it essentially makes routers and shapers along the path way happier, which leads to lower packet loss and less bufferbloat.
Fun fact: when we first deployed FQ we’ve noticed that all the buffer drops on our Top-of-the-Rack (ToR) switches had gone away. Even though they were very beefy boxes capable of handling terabits of traffic it seems like they had shallow buffers and were susceptible to packet drop during microbursts.
This is only one of the features that new Linux kernels provide, including but not limited to: Tail Loss Probe, TCP Small Queues, [TCP_NOTSENT_LOWAT](https://lwn.net/Articles/560082/)
RACK, etc.
We work on network- and transport-level optimizations from time to time—and when we do, it’s super fun and usually involves some amount of Wiresharking and packetdrilling. For example, one upcoming project for the Traffic team is to evaluate BBR v2 (once it is ready for public testing).
TLS
All connections to Dropbox are protected by TLS that encrypts and authenticates data in transit over the public internet. We also re-encrypt data and send it over an encrypted and mutually authenticated channel over our backbone network.
Since we use the same TLS stack internally for gRPC, we are very invested in its performance, especially around the TLS handshake part, where we make sure our libraries are using the most efficient hardware instructions possible, and for large file transfers, where we try to minimize the number of memory copies that they perform.
Our TLS setup is relatively simple: BoringSSL, TLS tickets with frequently rotated ephemeral keys, preferring AEAD ciphersuites with ChaCha20/Poly1305 for older hardware (we are very close the Cloudflare’s TLS config.) We are also in the process of rolling out the RFC version of the TLS 1.3 across our Edge network.
As for the future plans: as our boxes get closer to 100Gbit we are starting to look towards
[TCP_ULP](https://github.com/torvalds/linux/blob/master/Documentation/networking/tls.txt)
and how we can add support for it to our software stack.
HTTP
The main job of the nginx proxies on the Edge is to maintain keep alive connections to the backends in data center over our fat-long-pipe backbone. This essentially means that we have a set of hot connections that are never constrained by CWND on an almost lossless link.
Very quick note about how we build and deploy nginx: like everything else in Dropbox, we use Bazel to reproducibly and hermetically build a static nginx binary, copy over configs, package all of this into a squshfs, use torrent to distribute resulting package to all the servers, mount it (read-only), switch symlink, and finally run nginx upgrade.
We probably should write a blog post on it too, since it is very simple and very efficient.
Our nginx configuration is static and bundled with the binary therefore we need a way to dynamically configure some aspects of the configuration without full redeploy. Here is where Upstream Management Service kicks in. UMS is basically a look-aside external loadbalancer for nginx which allows us to reconfigure upstreams on the fly. One can create such system by:
- Regenerating config for nginx and hot reloading it. Sadly, when used extensively this approach negatively impacts connection reuse and increases memory pressure
- Using configuration API from the nginx plus
- Using standalone sidecar proxy on the same box, but that will lead to major increase in CPU/MEM resource usage
- Using Lua APIs or custom C modules
Because we are already relying on the Lua there, we’ve built a data plane for UMS with it by combining a balancer_by_lua_block
directive and ngx.timer.every
hook that periodically fetches configuration from control plane via https.
A nice side effect of writing the balancer module in Lua: we can now quickly experiment with different loadbalancing algorithms before writing them in C. The downside of Lua is that it is tricky to test, especially in a company where Lua is not one of the primary languages.
Control plane for UMS is a Golang service that gets information from our service discovery, monitoring system, and manual overrides, then aggregates and exposes it as a REST endpoint that nginx then accesses through a simple httpc:request_uri
.
gRPC
Nginx is terminating HTTP, HTTP/2, and gRPC connections on the Edge. Ability to proxy gRPC through our stack allows us to experiment with our apps talking gRPC directly to the application servers. Being able to do that streamlines development process and unifies the way services communicate externally and internally.
We are looking how we can use gRPC for all APIs. For the APIs that we can’t switch to gRPC, like web, we consider converting all HTTP requests into the gRPC method calls right at the Edge.
Wrap up and future blog posts
All of this pretty much covers the external part of Traffic Infrastructure, but there is another half that is not directly visible to our users: gRPC-based service mesh, scalable and robust service discovery, and a distributed filesystem for config distribution with notification support. All of that is coming soon in the next series of blog posts.
We’re hiring!
Do you like traffic-related stuff? Dropbox has a globally distributed Edge network, terabits of traffic, and millions of requests per second. All of which is managed by a small team in Mountain View, CA.
The Traffic team is hiring both SWEs and SREs to work on TCP/IP packet processors and loadbalancers, HTTP/2 proxies, and our internal gRPC-based service mesh. Not your thing? Dropbox is also hiring for a wide variety of engineering positions in San Francisco, New York, Seattle, Tel Aviv, and other offices around the world.
Acknowledgments
This article describes the work done by many people over a course of multiple years. Thanks to all current and past traffic team members: all of you helped make Dropbox faster and more reliable:
Ashwin Amit, Brian Pane, Dmitry Kopytkov, Dzmitry Markovich, Eduard Snesarev, Haowei Yuan, John Serrano, Jon Lee, Kannan Goundan, Konstantin Belyalov, Mario Brito, Oleg Guba, Patrick Lee, Preslav Le, Ross Delinger, Ruslan Nigmatullin, Vladimir Sheyda, Yi-Shu Tai.