Аннотация
Быстрые и эффективные удалённые вызовы процедур (RPC) являются ключом к производительности приложений, основанных на микросервисах. Однако сегодня обмен данными по RPC сопряжён со значительными накладными расходами, поскольку он опирается на стандартный, многоуровневый стек протоколов и слабую связанность между конечным хостом и сетевыми прокси, которые обрабатывают RPC. Мы предлагаем устранить разделение на уровни в стеке связи RPC и тесно связать обработку на конечном хосте и в сети с использованием абстракций высокого уровня. Этот подход приводит к более эффективному и производительному общению по RPC, поскольку он устраняет многие источники накладных расходов.
Ключевые слова: Сети приложений, Микросервисы, RPC
Текст статьи
ВВЕДЕНИЕ
Современные облачные приложения состоят из сотен или тысяч микросервисов, часто управляемых одной организацией или тесно интегрированными командами. Эта архитектура превращает то, что когда-то было простыми вызовами функций внутри монолитных двоичных файлов, в удалённые вызовы процедур (RPC) по сети.
Связь по RPC обеспечивается путём обмена структурированными данными, определёнными на таком языке, как Protobuf [7], между клиентами и серверами. Это включает сериализацию данных, добавление необходимых метаданных (например, какой конечный пункт RPC был вызван) и их доставку с обеспечением сквозных свойств, таких как надёжность и порядок. Это также включает применение одной или нескольких сетевых функций приложений (ANFs) для таких задач, как маршрутизация запросов, балансировка нагрузки, безопасность и мониторинг.
Рисунок 1. Подходы к коммуникации RPC
Сегодня связь по RPC обычно достигается с использованием многоуровневого стека стандартных протоколов, как показано на Рисунке 1a. (Мы используем gRPC [4] в качестве примера; стек похож на другие библиотеки RPC, такие как Apache Dubbo [2].) Конечные хосты полагаются на gRPC, HTTP, TCP и IP, а ANF реализуются в виде пользовательских HTTP-прокси [3], [6]. Кроме того, разработчики должны вручную связывать стек хоста с ANF по мере необходимости. Если ANF необходимо маршрутизировать запросы на основе поля имени пользователя RPC, разработчик должен добавить эту информацию в виде пользовательского HTTP-заголовка на конечном хосте.
Эта архитектура приводит к значительному «налогу RPC» [28], [31], происходящему из двух источников.
Стандартный, многоуровневый стек конечного хоста.
Современная связь по RPC опирается на стандартные и многоуровневые стеки конечных хостов. Этот стек объединяет функции, которые не нужны для определённых приложений. Например, приложениям реального времени со строгими требованиями к задержкам может не потребоваться доставка в порядке очереди или надёжная доставка, но они всё равно обременены накладными расходами TCP и HTTP/2 [18], [25]. Даже в рамках одного и того же приложения разные конечные точки RPC могут иметь разные требования к транспорту — операции чтения могут допускать ослабленную доставку, в то время как операции записи требуют строгой надёжности. Взаимодействия между уровнями также могут вызывать проблемы с производительностью. Например, HTTP/2 мультиплексирует несколько RPC поверх одного TCP-соединения, но поскольку TCP обеспечивает доставку в порядке очереди, единственный потерянный пакет блокирует все последующие данные в соединении, что приводит к блокировке начала линии (head-of-line blocking) для последующих RPC [20]. Наконец, каждый уровень добавляет свои собственные заголовки, увеличивая размер передаваемых сообщений.
Слабо связанный стек конечного хоста и ANF. Чтобы обеспечить работу ANF, оставаясь совместимыми со стандартными интерфейсами, сервисные сетки (service meshes) [6], [8], [9] стали популярным решением. В сервисных сетках, таких как Istio [8] и Linkerd [6], пользовательский HTTP-прокси развертывается рядом с каждым экземпляром службы или в качестве промежуточного устройства (middlebox), перехватывая и обрабатывая весь входящий и исходящий трафик, а метаданные кодируются в HTTP-заголовках [9], [39]. Эти прокси завершают TCP-соединение и анализируют HTTP-заголовки для реализации логики ANF. Хотя эта конструкция эффективна для предоставления богатой функциональности, она вносит существенные накладные расходы — исследования показали, что прокси сервисной сетки могут увеличивать задержку и нагрузку на ЦП до 7 раз [27], [38] из-за дополнительного анализа протоколов и заголовков, копирования данных и переключения контекста. Метаданные (HTTP-заголовки) для связи стека конечного хоста и ANF дополнительно увеличивают размер заголовка и накладные расходы на анализ.
Мы предлагаем устранить разделение на уровни в стеке связи RPC и тесно связать обработку на конечном хосте и ANF, как показано на Рисунке 1b. Уплощая стек, мы можем устранить избыточные функции и оптимизировать связь, что может значительно повысить производительность и эффективность. Тесно связывая обработку на конечном хосте и ANF, мы можем позволить ANF напрямую обращаться к данным RPC без ненужного декодирования, обеспечивая легковесную обработку на уровне ядра или даже с аппаратным ускорением.
Для реализации этого видения мы предлагаем подход на основе компилятора, который автоматически генерирует оптимизированные стеки связи RPC и формат передаваемых сообщений. Разработчики приложений задают требования к связи RPC на высоком уровне, включая транспортные свойства для каждой конечной точки RPC (например, надёжность, доставка по порядку, приоритет) и их ANF (например, политики, маршрутизация, наблюдаемость). Учитывая эти спецификации и доступные ресурсы для обработки в сети (например, SmartNIC и программируемые коммутаторы), компилятор автоматически определяет, какие компоненты должны выполняться в стеке конечного хоста, а какие должны быть делегированы сетевому процессору. Понимая, как метаданные и полезные данные RPC используются в транспортных и внутрисетевых программах, мы можем компактно форматировать сообщения и оптимизировать их для обработки в ядре или с аппаратным ускорением.
Мы можем оптимизировать связь по RPC таким образом только тогда, когда обе стороны и ANF контролируются одной организацией или тесно сотрудничающими организациями, что обычно для облачных приложений. Наш подход может быть реализован через общую библиотеку RPC, с которой связываются различные микросервисы. Приложения также могут общаться внешним образом с конечными точками, использующими традиционный стек. Мы поддерживаем такое общение с использованием шлюзов, похожих на те, что используются в сервисных сетях сегодня [5]. Шлюзы выполняют преобразование между стандартным стеком и нашим пользовательским протоколом, и наш компилятор будет генерировать их автоматически.
Мы не выступаем против программных абстракций и модульности, но мы переносим абстракции на более высокий, спецификационный уровень, где мы можем быстрее их итерировать. Автоматическая генерация плоских реализаций из этих спецификаций позволяет нам избежать накладных расходов, обычно связанных с прямой реализацией многоуровневых абстракций.
НАКЛАДНЫЕ РАСХОДЫ СВЯЗИ ПО RPC
Рассмотрим микросервис хранилища ключ-значение с двумя методами: get и set. Метод get извлекает значение по заданному ключу, а set обновляет хранилище новой парой ключ-значение. Для некоторых приложений эти два метода могут иметь различные требования к связи. Например, рассмотрим менеджер нагрузки, который поддерживает текущую нагрузку различных реплик веб-сервера. Реплики используют set для обновления своей нагрузки, когда она существенно меняется, в то время как балансировщик нагрузки периодически использует get для получения текущей нагрузки и выбора целевой реплики. В этой настройке occasional потеря или задержка запросов или ответов get может быть приемлемой, но потеря запросов или ответов set может привести к длительному периоду перегрузки реплики.
Предположим также, что разработчик приложения стремится применить две ANF ко всем RPC: (1) межсетевой экран приложений для блокировки запросов от определённых пользователей на основе поля имени пользователя и (2) трекер сеансов, который подсчитывает запросы на сеанс на основе session-id.
Мы реализуем приложение хранилища ключ-значение на Go, используя четыре различных базовых протокола: 1) UDP, 2) TCP, 3) HTTP/2 (который использует TCP) и 4) gRPC (который использует HTTP/2 и TCP). Мы проводим эксперименты на машинах с Ubuntu 20.04 с двумя 10-ядерными процессорами Intel Xeon Gold 5215 и 256 ГБ ОЗУ. В наших экспериментах каждый запрос или ответ составляет примерно 100 байт, а рабочая нагрузка состоит из 80% операций чтения и 20% операций записи — типичный шаблон для служб кэширования и интенсивной работы с метаданными.
Рисунок 2. Задержка и размер заголовка для хранилища «ключ-значение» при использовании разных протоколов. Все сообщения в разных протоколах сериализуются с помощью Protobuf
При современной многоуровневой и слабо связанной архитектуре приложение сталкивается со значительной неэффективностью производительности: Стек конечного хоста. Независимо от фактических требований к конечным точкам RPC, существующая связь по RPC использует один и тот же тяжелый стек (т.е. gRPC, HTTP/2 и TCP). На Рисунке 2a показано влияние использования разных протоколов на производительность приложения хранилища ключ-значение. Каждый уровень (TCP, HTTP/2, gRPC) добавляет немаленькие накладные расходы к сквозной задержке: реализация конечной точки get с помощью gRPC увеличивает задержку до 448% по сравнению с использованием UDP, протокола, который всё ещё удовлетворяет требованиям get.
Рисунок 3. Задержка анализа HTTP-заголовка
Кроме того, полезные данные RPC сегодня обернуты в несколько уровней заголовков (IP, TCP, HTTP/2, gRPC), добавляя существенные накладные расходы на заголовки, как показано на Рисунке 2b. Аналогично задержке, каждый уровень в стеке добавляет значительные накладные расходы на заголовки. Например, в наших экспериментах использование gRPC добавляет 133 байта заголовка поверх TCP. Недавнее исследование [35] показывает, что производственные кластеры Twitter обрабатывают размеры объектов (ключ+значение) от 55 до 294 байт, что означает, что все заголовки в сообщении gRPC могут добавлять 42-79% накладных расходов.
ANF. Для реализации ANF, таких как межсетевой экран и трекер сеансов, разработчики обычно полагаются на сервисные сетки, которые перехватывают трафик через пользовательские HTTP-прокси, такие как Envoy [3]. Эти прокси реализуют и используют полный стек протоколов с внешними уровнями (TCP и HTTP), как показано на Рисунке 1a: они завершают входящее TCP-соединение, анализируют и извлекают метаданные из HTTP-заголовков, применяют желаемую логику ANF, а затем устанавливают новое соединение с целевой службой. Эта конструкция вносит значительные накладные расходы из-за переключения контекста между ядром и пользовательским пространством, повторяющегося анализа протоколов, избыточного копирования данных и операций сериализации/десериализации. Предыдущие исследования [27], [38] показывают, что популярные сервисные сетки могут снижать пропускную способность, увеличивать задержку в хвосте распределения и повышать использование ЦП в 1,27–7 раз по сравнению с прямой связью.
Что хуже, из-за слабой связи между сервисной сеткой и стеком конечного хоста разработчики должны вставлять метаданные, требуемые ANF, в виде пользовательских HTTP-заголовков на конечном хосте, что вносит дополнительные накладные расходы на анализ HTTP [38]. Эти накладные расходы на анализ растут с количеством заголовков, поскольку анализ HTTP плохо масштабируется с увеличением метаданных. В нашем исследовании развертывания Istio [8], популярной сервисной сетки, с функциями наблюдаемости, безопасности и маршрутизации обычно включают более 20 заголовков на запрос (включая заголовки HTTP/2 по умолчанию, метаданные gRPC, внутренние заголовки Istio и поля трассировки). Как показано на Рисунке 3, добавление 25 пользовательских HTTP-заголовков увеличивает задержку анализа на 250 мксек.
Непереносимость. Многообещающий способ уменьшить накладные расходы — это выгрузка (offload) ANF в ядро (через eBPF), SmartNIC или программируемые коммутаторы [1], [27], [33]. Однако выгрузка является сложной задачей при текущем стеке протоколов, потому что любым сетевым процессорам приходится обрабатывать и управлять несколькими уровнями протоколов, анализировать HTTP-заголовки и буферизовать сетевые пакеты на случай, если размер RPC превысит MTU (максимальную единицу передачи). Кроме того, такие распространенные протоколы, как TCP (и его варианты), налагают механизмы надежности и управления перегрузками, которые усложняют перехват и преобразование, требуемые ANF [14].
СУЩЕСТВУЮЩИЕ РЕШЕНИЯ
Предыдущие работы изучали эти проблемы изолированно, сосредотачиваясь либо на оптимизации стека протоколов конечного хоста, либо на обработке ANF. Однако эти подходы имели ограниченный успех в решении коренных причин неэффективности, возникающих из-за многоуровневой и слабо связанной архитектуры.
Оптимизация только стека конечного хоста. Многие предложения [10], [17], [18], [20], [25], [32] были сосредоточены на снижении накладных расходов транспортного протокола, в частности TCP. Такие подходы, как MTP [14] и NetRPC [36], используют пользовательские транспортные протоколы для облегчения работы программ внутрисетевых вычислений. Хотя эти методы эффективно снижают транспортные накладные расходы, они являются универсальными и страдают от избыточности функций. Например, и MTP, и NetRPC гарантируют надежную доставку сообщений независимо от требования приложения.
NetBlocks [10] позволяет приложению настраивать стек конечного хоста и макет сообщения. Однако они не решают проблему слабой связи между стеком конечного хоста и ANF.
Оптимизация только обработки ANF. Другие предложения были сосредоточены на улучшении производительности сетей приложений [1], [12], [22], [34], [39]. Например, Cilium [1] выгружает простые ANF 4-го уровня (транспортные) в ядро с помощью eBPF, в то время как Proxyless gRPC [19] и ServiceRouter [30] позволяют выполнять сетевые функции внутри процесса — до стека RPC на клиенте и после него на сервере. AppNet [37], [39], Lyra [12] и ClickINC [34] вводят новые абстракции для компиляции и оптимизации размещения функций. Хотя эти решения достигают выигрыша в производительности в целевых областях, они всё ещё ограничены существующим многоуровневым стеком протоколов. В результате значительное повышение производительности от оптимизированной связи и выгрузки ANF остаётся неиспользованным.
Связывание стека конечного хоста и ANF. Недавние работы по внутрисетевым вычислениям совместно проектируют стек конечного хоста и ANF. Однако, как обсуждается в §3, они страдают от высоких затрат на разработку и плохой повторной используемости.
ПЕРЕОСМЫСЛЕНИЕ СВЯЗИ ПО RPC
Учитывая ограничения обеспечения связи по RPC с использованием универсальных, многоуровневых и слабо связанных архитектур, мы предлагаем фундаментальный пересмотр, который тесно интегрирует все компоненты связи по RPC. Вместо того чтобы полагаться на многоуровневые стеки, конечный хост и ANF должны работать на уплощённом, оптимизированном стеке, настроенном для каждого метода RPC. Этот стек строится непосредственно поверх IP, который обеспечивает базовую связность между конечными точками, в то время как функции более высокого уровня адаптированы к потребностям приложения.
Мы выступаем за подход, который использует спецификации высокого уровня и компиляторы для обеспечения такой связи по RPC. Чтобы мотивировать этот подход, мы намечаем две альтернативы.
Ручное кодирование, ориентированное на приложение: Один из подходов — вручную проектировать тесно интегрированные, пользовательские системы, настроенные под конкретные приложения. Этот подход включает ручное создание каждого компонента — сериализации, транспорта и ANF — для удовлетворения точных требований к производительности и эксплуатации. Недавние системы внутрисетевых вычислений [15], [16], [21], [23], [32] являются примерами этой категории. Например, NetCache [16] вводит пользовательский формат сообщений и использует облегченный транспортный протокол для обеспечения внутрисетевой службы кэширования между клиентом и сервером. Эта конструкция достигает максимальной производительности за счёт устранения ненужных абстракций и тонкой настройки каждого компонента под рабочую нагрузку. Однако, хотя этот подход может обеспечить отличную производительность, он страдает от высоких затрат на разработку и его трудно адаптировать к новым случаям использования или развивающимся рабочим нагрузкам.
Расширенные межуровневые интерфейсы: Альтернативный подход, который ставит во главу угла повторную используемость, заключается в расширении интерфейсов между уровнями протоколов, обеспечивая более богатый обмен контекстной информацией. Расширяя API и заголовки, уровень сериализации может передавать подсказки о производительности (например, приоритет, требования к согласованности) на транспортный уровень, позволяя сетевым функциям адаптироваться динамически. Этот подход улучшает совместимость и сохраняет модульность существующих стеков протоколов, позволяя проводить постепенное развертывание без необходимости полного перепроектирования. Однако расширенные интерфейсы остаются фундаментально ограниченными стандартами протоколов, ограничивая степень, в которой они могут поддерживать сквозную, полноценную оптимизацию стека. Например, TCP позволяет дополнительным заголовкам (называемым опциями TCP) передавать дополнительную информацию, такую как масштабирование окна [13] или выборочные подтверждения [24]. Однако эти опции ограничены пространством (40 байт) и своей гибкостью.
Подход, основанный на языке высокого уровня и оптимизирующем компиляторе, предлагает сбалансированное решение между кастомизацией систем с ручным кодированием и повторной используемостью расширенных интерфейсов. Он может обеспечить преимущества в производительности тесно интегрированных конструкций без высоких затрат на разработку и плохой повторной используемости ручных решений. Автоматически генерируя оптимизированные стеки на основе требований приложения, система на основе компилятора может устранить избыточность и обеспечить бесшовное совместное проектирование сериализации, свойств связи и ANF. Она также может легко адаптироваться к разнообразным рабочим нагрузкам и средах развертывания.
КЛЮЧЕВЫЕ ИССЛЕДОВАТЕЛЬСКИЕ ВОПРОСЫ
Реализация нашего подхода требует ответа на несколько ключевых исследовательских вопросов.
Q1: Какие абстракции должен предоставлять наш DSL (предметно-ориентированный язык) для указания требований к связи RPC? Чтобы позволить разработчикам выражать специфические для приложения требования к связи, наш DSL должен предоставлять выразительные, но лаконичные абстракции. Это включает возможность выражать сквозные требования к связи, такие как надежность, порядок, приоритет, и ANF, такие как маршрутизация, балансировка нагрузки и контроль доступа. Задача заключается в проектировании абстракций, которые достаточно гибки для поддержки разнообразных потребностей приложений, но при этом поддаются эффективной компиляции и ряду оптимизаций.
Q2: Как генерировать эффективную реализацию стека связи RPC? Генерация высокопроизводительных реализаций связи RPC требует перевода спецификаций связи высокого уровня в оптимизированный код низкого уровня, который минимизирует накладные расходы на производительность. Это включает несколько проблем, таких как устранение избыточной обработки и анализа и сокращение наслоения протоколов. Компилятор также должен адаптировать сгенерированный код под целевую среду развертывания, выбирая между выполнением в пользовательском пространстве, пространстве ядра или в сети на основе ограничений производительности и ресурсов.
Q3: Как обеспечить легковесное выполнение ANF? Как упоминалось ранее, выполнение ANF сегодня имеет высокие накладные расходы, потому что прокси должны завершать транспортные соединения и анализировать HTTP-заголовки до выполнения любой специфичной для приложения функциональности. Можем ли мы избавиться от этих накладных расходов, сохраняя при этом полную выразительность ANF, такую как доступ к содержимому сообщения и возможность преобразования или применение политик к RPC? Решение этой проблемы требует компилятора, который может генерировать пользовательские форматы сообщений, которые предоставляют необходимые метаданные ANF на основе их функциональности. Нам также необходимо обеспечить внутрисетевую обработку сообщений в полете, сохраняя при этом транспортную семантику и корректность приложения.
Q4: Как координировать стек конечного хоста и внутрисетевые процессоры? Достижение бесшовной координации между стеком конечного хоста и внутрисетевые процессоры крайне важно для эффективного выполнения. Это требует механизмов для разделения функциональности между этими компонентами при сохранении корректности и производительности. Ключевые проблемы включают определение четких интерфейсов для совместного использования состояния, обеспечение согласованности путей управления и данных и динамическую адаптацию к изменениям в сетевых условиях или рабочих нагрузках приложения. Система должна интеллектуально решать, какие ANF выгружать на внутрисетевое устройства, а какие оставлять на конечном хосте, балансируя использование ресурсов, задержку и отказоустойчивость. Эффективные механизмы координации также должны учитывать неоднородность программируемого оборудования и обеспечивать переносимость между средами развертывания. В зависимости от размещения ANF (например, на конечном хосте через eBPF или в сети через программируемые коммутаторы), определенные метаданные могут не нуждаться в кодировании в передаваемом сообщении. Например, при реализации трекера сеансов на клиентском конечном хосте идентификатор сеанса не нужно включать.
ПРЕДЛАГАЕМОЕ РЕШЕНИЕ
Мы намечаем возможный подход к реализации нашего видения, который частично отвечает на вышеупомянутые вопросы.
АБСТРАКЦИИ ПРОГРАММИРОВАНИЯ
Разработчики выражают требования к связи RPC через спецификацию связи RPC высокого уровня, которая охватывает как транспортные свойства (например, надежность, доставка по порядку), так и сетевые функции приложений (например, балансировка нагрузки, контроль доступа). Мы строим на абстракциях, предоставляемых AppNet [37], [39] и NetBlocks [10] как на основе.
AppNet — это DSL, который позволяет разработчикам специфицировать ANF, используя правила сопоставления-действия (match-action), которые работают с полями RPC, переменными состояния и встроенными функциями как для запросов, так и для ответов. Эта модель упрощает сложные операции, такие как изменение, перехват, изменение порядка и динамическая модификация RPC. Для спецификации связи между каждой парой микросервисов AppNet состоит из спецификации цепочки и соответствующих спецификаций элементов. Спецификация цепочки определяет, какие сетевые функции должны быть вызваны и порядок их вызова. Каждая спецификация элемента включает четыре раздела: раздел состояния, который объявляет локальные или общие переменные состояния, раздел инициализации для инициализации состояния, и разделы req и resp, которые определяют правила сопоставления-действия для обработки запросов и ответов RPC.
Ключевое преимущество AppNet — прозрачность развертывания: от разработчиков не требуется указывать, где (например, конечный хост, SmartNIC, программируемый коммутатор) или как развертываются ANF. Компилятор автоматически анализирует входную спецификацию и доступную инфраструктуру, чтобы определить оптимальное размещение функций, обеспечивая эффективное выполнение в гетерогенных средах.
Чтобы дополнительно оптимизировать разработку, мы расширяем DSL AppNet с помощью NetBlocks, чтобы разработчики могли определять сквозные свойства связи вместе с сетевыми функциями, используя унифицированный синтаксис. NetBlocks — это DSL и компилятор для проектирования специальных протоколов. Он позволяет пользователям настраивать транспортные требования, выбирая и настраивая функции. Подобно NetBlocks, мы предоставляем библиотеку общих транспортных функций (например, надежность, упорядочивание RPC) с настраиваемыми параметрами, позволяя разработчикам настраивать поведение без реализации этих функций с нуля.
Рисунок 4. Пример спецификации для приложения хранилища ключ-значение.
ПОЛЬЗОВАТЕЛЬСКИЙ МАКЕТ RPC И ТРАНСПОРТ
Для легковесной обработки ANF без дорогостоящего завершения транспорта или анализа заголовков наш компилятор генерирует пользовательский макет RPC, который позволяет эффективно обрабатывать сообщения «в полете». На основе использования метаданных в программе AppNet и определенной приложением структуры RPC компилятор синтезирует компактный макет сообщения фиксированного формата со статически известными смещениями, размерами и выравниванием для каждого поля метаданных и раздела полезной нагрузки. Этот дизайн позволяет ANF — независимо от того, реализованы ли они в eBPF, P4 или пользовательском пространстве — дешево проверять и манипулировать сообщениями.
Кроме того, современные транспортные протоколы (например, TCP, QUIC) предполагают неизменяемые, сквозные байтовые потоки и ломаются, когда сообщения задерживаются, изменяются, перехватываются или изменяют порядок с помощью ANF. Вдохновленные MTP [14], наш сгенерированный компилятором стек протоколов включает логику транспортного уровня, которая учитывает потенциальные преобразования на уровне сообщений и внутрисетевое поведение. Например, управление перегрузкой учитывает ANF и может адаптироваться к задержкам, вызванным ANF. Точно так же надежность реализуется на уровне сообщений с использованием сквозных подтверждений, избегая зависимости от порядковых номеров на уровне байтов, которые несовместимы с изменяемыми или перехваченными сообщениями.
Кроме того, пользовательский транспорт поддерживает несколько RPC в одном соединении, как в потоках HTTP/gRPC. Каждый пакет несет идентификатор RPC, и компилятор гарантирует, что, когда это возможно, первый пакет RPC содержит все метаданные, необходимые ANF. Это позволяет проводить раннюю проверку и обработку без ожидания получения всего сообщения, уменьшая накладные расходы на буферизацию.
СТЕК КОНЕЧНОГО ХОСТА И ANF
Учитывая спецификацию связи и доступные платформы обработки (например, конечные хосты, SmartNIC, коммутаторы), компилятор генерирует оптимизированный код как для стеков протоколов конечных точек, так и для ANF:
Стек конечного хоста: На основе свойств связи, указанных для каждого метода RPC, компилятор генерирует высокооптимизированный стек протоколов на конечном хосте. Этот стек включает только необходимые функции, избегая ненужных уровней и функций, и настраивается для каждой конечной точки. Одна из проблем — негибкость сетевого стека ядра Linux, которая ограничивает возможность настройки, тогда как стеки в пользовательском пространстве compromize защиту [26] и управляемость [29]. Чтобы решить эту проблему, мы используем eTran [11], настраиваемый сетевой стек ядра, построенный на eBPF. Сгенерированный стек интегрируется со слоем XDP, высокопроизводительным хуком eBPF, который обрабатывает пакеты до того, как они достигнут слоя сокетов, чтобы обеспечить выполнение с малой задержкой.
ANF: Помимо сквозных свойств связи, компилятор переводит спецификации сетей приложений AppNet в оптимизированный, целеспецифичный код для внутрисетевых процессоров, например, P4 для программируемых коммутаторов и eBPF для выполнения в пространстве ядра. Сгенерированный код тесно интегрирован с пользовательскими сгенерированными заголовками RPC, обеспечивая эффективное извлечение и обработку заголовков на внутрисетевых процессорах. Когда ANF размещается на клиентском стеке хоста, используемые ею метаданные будут удалены из передаваемых сообщений, чтобы уменьшить накладные расходы на заголовки.
ЗАКЛЮЧЕНИЕ
Тесно интегрируя компоненты связи RPC через единую абстракцию, компилятор может автоматически генерировать эффективный стек связи, который устраняет накладные расходы и оптимизирует передачу данных. Кроме того, компилятор производит оптимизированный макет RPC, позволяя ANF эффективно выполняться внутри сети, используя emerging платформы ускорения на уровне ядра и аппаратного обеспечения.
БЛАГОДАРНОСТИ
Мы хотели бы поблагодарить анонимных рецензентов за их полезные отзывы. Эта работа частично поддерживается UW FOCI и его партнерами (Alibaba, Amazon, Cisco, Google, Microsoft и VMware), грантами NSF 2402695 и 2402696, и ACE, центром, который является частью DARPA's JUMP 2.0. Yang Zhou поддерживается UC Berkeley Sky Computing Lab.
Литература
- [n.d.]. Cilium Service Mesh. https://cilium.io/use-cases/service-mesh/. (Accessed on 04/13/2025).
- [n.d.]. Dubbo: A Cloud-Native Microservice Framework. https://dubbo.apache.org/. (Accessed on 04/13/2025).
- [n.d.]. Envoy. https://www.envoyproxy.io/. (Accessed on 04/13/2025).
- [n.d.]. gRPC: A high performance, open source universal RPC framework. https://grpc.io. (Accessed on 04/13/2025).
- [n.d.]. Ingress Gateways. https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/. (Accessed on 04/13/2025).
- [n.d.]. Linkerd: the world’s most advanced service mesh. https://linkerd.io/. (Accessed on 04/13/2025).
- [n.d.]. Protocol Buffers. https://protobuf.dev/. (Accessed on 04/13/2025).
- [n.d.]. The Istio Service Mesh. https://istio.io/. (Accessed on 04/13/2025).
- Sachin Ashok, P Brighten Godfrey, and Radhika Mittal. 2021. Leveraging service meshes as a new network layer. In Proceedings of the 20th ACM Workshop on Hot Topics in Networks. 229–236.
- Ajay Brahmakshatriya, Chris Rinard, Manya Ghobadi, and Saman Amarasinghe. 2024. NetBlocks: Staging Layouts for High-Performance Custom Host Network Stacks. Proceedings of the ACM on Programming Languages 8, PLDI (2024), 467–491.
- Zhongjie Chen, Qingkai Meng, ChonLam Lao, Yifan Liu, Fengyuan Ren, Minlan Yu, and Yang Zhou. 2025. eTran: Extensible Kernel Transport with eBPF. In 22nd USENIX Symposium on Networked Systems Design and Implementation (NSDI 25).
- Jiaqi Gao, Ennan Zhai, Hongqiang Harry Liu, Rui Miao, Yu Zhou, Bingchuan Tian, Chen Sun, Dennis Cai, Ming Zhang, and Minlan Yu. 2020. Lyra: A cross-platform language and compiler for data plane programming on heterogeneous asics. In Proceedings of the Annual conference of the ACM Special Interest Group on Data Communication on the applications, technologies, architectures, and protocols for computer communication. 435–450.
- Van Jacobson, Robert Braden, and David Borman. 1992. TCP extensions for high performance. Technical Report.
- Tao Ji, Rohan Vardekar, Balajee Vamanan, Brent E. Stephens, and Aditya Akella. 2025. MTP: Transport for In-Network Computing. In 22nd USENIX Symposium on Networked Systems Design and Implementation (NSDI 25).
- Xin Jin, Xiaozhou Li, Haoyu Zhang, Nate Foster, Jeongkeun Lee, Robert Soulé, Changhoon Kim, and Ion Stoica. 2018. {NetChain}:{Scale-Free}{Sub-RTT} coordination. In 15th USENIX Symposium on Net-worked Systems Design and Implementation (NSDI 18). 35–49.
- Xin Jin, Xiaozhou Li, Haoyu Zhang, Robert Soulé, Jeongkeun Lee, Nate Foster, Changhoon Kim, and Ion Stoica. 2017. Netcache: Balancing key-value stores with fast in-network caching. In Proceedings of the 26th Symposium on Operating Systems Principles. 121–136.
- Anuj Kalia, Michael Kaminsky, and David Andersen. 2019. Datacenter RPCs can be general and fast. In 16th USENIX Symposium on Networked Systems Design and Implementation (NSDI 19). 1–16.
- Marios Kogias, George Prekas, Adrien Ghosn, Jonas Fietz, and Edouard Bugnion. 2019. R2P2: Making RPCs first-class datacenter citizens. In 2019 USENIX Annual Technical Conference (USENIX ATC 19). 863–880.
- Steven Landow. 2021. gRPC Proxyless Service Mesh. https://istio.io/latest/blog/2021/proxyless-grpc/.
- Adam Langley, Alistair Riddoch, Alyssa Wilk, Antonio Vicente, Charles Krasic, Dan Zhang, Fan Yang, Fedor Kouranov, Ian Swett, Janardhan Iyengar, et al. 2017. The quic transport protocol: Design and internet-scale deployment. In Proceedings of the conference of the ACM special interest group on data communication. 183–196.
- ChonLam Lao, Yanfang Le, Kshiteej Mahajan, Yixi Chen, Wenfei Wu, Aditya Akella, and Michael Swift. 2021. ATP: In-network aggregation for multi-tenant learning. In 18th USENIX Symposium on Networked Systems Design and Implementation (NSDI 21). 741–761.
- Hao Li, Changhao Wu, Guangda Sun, Peng Zhang, Danfeng Shan, Tian Pan, and Chengchen Hu. 2021. Programming network stack for middleboxes with Rubik. In 18th USENIX Symposium on Networked Systems Design and Implementation (NSDI 21). 551–570.
- Jialin Li, Jacob Nelson, Ellis Michael, Xin Jin, and Dan RK Ports. 2020. Pegasus: Tolerating skewed workloads in distributed storage with {In-Network} coherence directories. In 14th USENIX Symposium on Operating Systems Design and Implementation (OSDI 20). 387–406.
- Matt Mathis, Jamshid Mahdavi, Sally Floyd, and Allyn Romanow. 1996. TCP selective acknowledgment options. Technical Report.
- Behnam Montazeri, Yilong Li, Mohammad Alizadeh, and John Ouster-hout. 2018. Homa: A receiver-driven low-latency transport protocol using network priorities. In Proceedings of the 2018 Conference of the ACM Special Interest Group on Data Communication. 221–235.
- Simon Peter, Jialin Li, Irene Zhang, Dan RK Ports, Doug Woos, Arvind Krishnamurthy, Thomas Anderson, and Timothy Roscoe. 2015. Arrakis: The Operating System is the Control Plane. ACM Transactions on Computer Systems (TOCS) 33, 4 (2015), 1–30.
- Shixiong Qi, Leslie Monis, Ziteng Zeng, Ian-chin Wang, and KK Ramakrishnan. 2022. Spright: Extracting the server from serverless computing! high-performance ebpf-based event-driven, shared-memory processing. In Proceedings of the ACM SIGCOMM 2022 Conference. 780– 794.
- Mubashir Adnan Qureshi, Junhua Yan, Yuchung Cheng, Soheil Hassas Yeganeh, Yousuk Seung, Neal Cardwell, Willem De Bruijn, Van Jacobson, Jasleen Kaur, David Wetherall, et al. 2023. Fathom: Understanding Datacenter Application Network Performance. In Proceedings of the ACM SIGCOMM 2023 Conference. 394–405.
- Hugo Sadok, Zhipeng Zhao, Valerie Choung, Nirav Atre, Daniel S Berger, James C Hoe, Aurojit Panda, and Justine Sherry. 2021. We need kernel interposition over the network dataplane. In Proceedings of the Workshop on Hot Topics in Operating Systems. 152–158.
- Harshit Saokar, Soteris Demetriou, Nick Magerko, Max Kontorovich, Josh Kirstein, Margot Leibold, Dimitrios Skarlatos, Hitesh Khandelwal, and Chunqiang Tang. 2023. {ServiceRouter}: Hyperscale and minimal cost service mesh at meta. In 17th USENIX Symposium on Operating Systems Design and Implementation (OSDI 23). 969–985.
- Korakit Seemakhupt, Brent E Stephens, Samira Khan, Sihang Liu, Hassan Wassel, Soheil Hassas Yeganeh, Alex C Snoeren, Arvind Krishnamurthy, David E Culler, and Henry M Levy. 2023. A cloud-scale characterization of remote procedure calls. In Proceedings of the 29th Symposium on Operating Systems Principles. 498–514.
- Hao Wang, Han Tian, Jingrong Chen, Xinchen Wan, Jiacheng Xia, Gaoxiong Zeng, Wei Bai, Junchen Jiang, Yong Wang, and Kai Chen. 2024. Towards Domain-Specific Network Transport for Distributed DNN Training. In 21st USENIX Symposium on Networked Systems Design and Implementation (NSDI 24). 1421–1443.
- Tao Wang, Jinkun Lin, Gianni Antichi, Aurojit Panda, and Anirudh Sivaraman. 2023. Application-Defined Receive Side Dispatching on the NIC. arXiv preprint arXiv:2312.04857 (2023).
- Wenquan Xu, Zijian Zhang, Yong Feng, Haoyu Song, Zhikang Chen, Wenfei Wu, Guyue Liu, Yinchao Zhang, Shuxin Liu, Zerui Tian, et al. 2023. Clickinc: In-network computing as a service in heterogeneous programmable data-center networks. In Proceedings of the ACM SIGCOMM 2023 Conference. 798–815.
- Juncheng Yang, Yao Yue, and KV Rashmi. 2021. A large-scale analysis of hundreds of in-memory key-value cache clusters at twitter. ACM Transactions on Storage (TOS) 17, 3 (2021), 1–35.
- Bohan Zhao, Wenfei Wu, and Wei Xu. 2023. NetRPC: Enabling In-Network computation in remote procedure calls. In 20th USENIX symposium on networked systems design and implementation (NSDI 23). 199–217.
- Xiangfeng Zhu, Weixin Deng, Banruo Liu, Jingrong Chen, Yongji Wu, Thomas Anderson, Arvind Krishnamurthy, Ratul Mahajan, and Danyang Zhuo. 2023. Application defined networks. In Proceedings of the 22nd ACM Workshop on Hot Topics in Networks. 87–94.
- Xiangfeng Zhu, Guozhen She, Bowen Xue, Yu Zhang, Yongsu Zhang, Xuan Kelvin Zou, XiongChun Duan, Peng He, Arvind Krishnamurthy, Matthew Lentz, et al. 2023. Dissecting overheads of service mesh side-cars. In Proceedings of the 2023 ACM Symposium on Cloud Computing. 142–157.
- Xiangfeng Zhu, Yuyao Wang, Banruo Liu, Yongtong Wu, Nikola Bojanic, Jingrong Chen, Gilbert Bernstein, Arvind Krishnamurthy, Sam Kumar, Ratul Mahajan, and Danyang Zhuo. 2025. High-level Programming for Application Networks. In 22nd USENIX Symposium on Networked Systems Design and Implementation (NSDI 25).