Удалённый вызов процедур
Удалённый вызов процедур (англ. Remote Procedure Call, RPC) — это технология, позволяющая программе вызывать функцию или процедуру в другом адресном пространстве (как правило, на удалённом компьютере) так, как если бы она была локальной. RPC абстрагирует детали сетевого взаимодействия, предоставляя разработчику механизм, при котором вызов процедуры на сервере выглядит синтаксически и семантически как обычный вызов функции в коде клиента. Ключевое свойство RPC — прозрачность расположения: вызывающий код не обязан знать, выполняется ли процедура локально или на другом узле сети.
История
Концепция удалённого вызова процедур была впервые формально описана в 1976 году в работе Брюса Джея Нельсона «Remote Procedure Call» (диссертация в Стэнфордском университете). Нельсон предложил идею скрыть сложность сетевого взаимодействия за интерфейсом, напоминающим вызов локальной подпрограммы.
В 1980-х годах технология получила практическую реализацию. Одной из первых коммерческих систем стала Sun RPC (ONC RPC), разработанная компанией Sun Microsystems в 1985 году для операционной системы SunOS. Эта реализация стала основой для протоколов Network File System (NFS) и Network Information Service (NIS). Примерно в то же время компания Apollo Computer представила собственный протокол Network Computing System (NCS).
В 1990-е годы с развитием объектно-ориентированного программирования появились объектные расширения RPC — CORBA (Common Object Request Broker Architecture) от консорциума OMG, DCOM (Distributed Component Object Model) от Microsoft, а затем Java RMI (Remote Method Invocation) от Sun Microsystems. Эти технологии позволяли вызывать методы удалённых объектов, а не просто процедуры.
В 2000-е годы на смену тяжёлым объектным системам пришли более лёгкие протоколы на основе XML и HTTP — XML-RPC и SOAP (Simple Object Access Protocol). Они использовали текстовый формат обмена данными и могли передаваться через стандартные веб-порты, что упрощало интеграцию с интернетом.
С середины 2010-х годов популярность приобрели фреймворки нового поколения, такие как gRPC (разработан Google в 2015 году) и Apache Thrift (создан Facebook в 2007 году, открыт в 2008 году). Они используют бинарные протоколы сериализации (Protocol Buffers для gRPC, Thrift Binary Protocol) и поддерживают множество языков программирования.
Архитектура и принцип работы
Система RPC обычно включает четыре основных компонента: клиент, клиентский стаб (stub), серверный скелетон (skeleton) и сервер.
- Клиент — программа, которая инициирует вызов удалённой процедуры.
- Клиентский стаб — локальный код, который выглядит как вызываемая процедура. Он упаковывает аргументы вызова в сообщение (процесс маршаллинга, marshalling), отправляет его по сети на сервер и ожидает ответа.
- Серверный скелетон — код на стороне сервера, который принимает сообщение, распаковывает аргументы (демаршаллинг), вызывает реальную процедуру на сервере, упаковывает результат и отправляет его обратно.
- Сервер — программа, реализующая фактическую логику удалённой процедуры.
Процесс вызова состоит из следующих шагов:
- Клиент вызывает локальную процедуру-стаб, передавая ей аргументы.
- Стаб сериализует аргументы в формат, понятный сети (например, бинарный протокол или XML).
- Стаб отправляет запрос по сети на сервер (обычно через протокол TCP или UDP).
- Скелетон на сервере получает запрос, десериализует аргументы.
- Скелетон вызывает реальную процедуру на сервере с переданными аргументами.
- Результат выполнения процедуры передаётся обратно скелетону.
- Скелетон сериализует результат и отправляет его клиенту.
- Стаб клиента получает ответ, десериализует результат и возвращает его клиенту как обычное возвращаемое значение.
Важным аспектом является обработка ошибок. Если удалённый сервер недоступен, процедура не выполняется или происходит тайм-аут, стаб должен корректно сообщить об этом вызывающему коду, обычно через исключение или код ошибки.
Классификация и виды
RPC-системы можно классифицировать по нескольким признакам.
По типу синхронности
- Синхронные RPC — клиент блокируется и ждёт завершения удалённой процедуры. Это наиболее распространённый тип, соответствующий семантике обычного вызова функции.
- Асинхронные RPC — клиент отправляет запрос и продолжает выполнение, не дожидаясь ответа. Результат может быть получен позднее через callback, future или polling.
По формату сериализации
- Текстовые протоколы — данные передаются в человекочитаемом формате (XML, JSON). Примеры: XML-RPC, SOAP, JSON-RPC.
- Бинарные протоколы — данные передаются в компактном бинарном формате, что обеспечивает высокую производительность. Примеры: gRPC (Protocol Buffers), Apache Thrift (Binary Protocol), Avro.
По транспортному протоколу
- На основе TCP — обеспечивают надёжную доставку сообщений.
- На основе UDP — используются для быстрых, но ненадёжных вызовов (например, в некоторых реализациях Sun RPC).
- На основе HTTP — SOAP и XML-RPC работают поверх HTTP, что упрощает прохождение через брандмауэры.
По модели взаимодействия
- Двухточечные (point-to-point) — клиент напрямую обращается к одному серверу.
- Шинные (bus-based) — сообщения публикуются на общую шину, и любой подписчик может их обработать (например, DDS, некоторые реализации CORBA).
Протоколы и реализации
Sun RPC (ONC RPC)
Одна из старейших реализаций, разработанная для UNIX-систем. Использует External Data Representation (XDR) для сериализации данных. Легла в основу NFS и NIS. В 2009 году была стандартизирована как RFC 5531.
XML-RPC
Протокол, использующий XML для кодирования вызовов и HTTP в качестве транспорта. Был создан в 1998 году компанией Microsoft и стал предшественником SOAP. Отличается простотой, но ограничен в типах данных.
SOAP (Simple Object Access Protocol)
Протокол обмена структурированными сообщениями в формате XML. Широко использовался в корпоративных системах (например, в веб-сервисах на платформе .NET). Поддерживает сложные типы данных, безопасность (WS-Security) и транзакции.
JSON-RPC
Лёгкий протокол, использующий JSON для кодирования запросов и ответов. Поддерживает как одиночные, так и пакетные вызовы. Прост в реализации и популярен в современных веб-приложениях.
gRPC
Современный фреймворк от Google, основанный на HTTP/2 и Protocol Buffers. Поддерживает синхронные и асинхронные вызовы, потоковую передачу данных, двустороннюю потоковую передачу. gRPC отличается высокой производительностью и кроссплатформенностью. Широко применяется в микросервисной архитектуре.
Apache Thrift
Фреймворк, разработанный в Facebook (продукт Meta, признанной экстремистской и запрещённой в РФ). Включает собственный язык описания интерфейсов (IDL) и генерацию кода для многих языков (C++, Java, Python, PHP и др.). Поддерживает несколько протоколов (бинарный, компактный, JSON) и транспортов (TCP, HTTP).
Применение
Удалённый вызов процедур применяется в различных областях.
- Распределённые вычисления — объединение вычислительных мощностей нескольких машин для решения одной задачи (например, в кластерных системах).
- Микросервисная архитектура — взаимодействие между независимыми сервисами в современных приложениях. gRPC и Thrift являются популярными решениями для этой цели.
- Файловые системы — NFS использует Sun RPC для доступа к удалённым файлам.
- Веб-сервисы — SOAP и XML-RPC применялись для создания корпоративных веб-сервисов, хотя в последние годы их вытеснили REST API.
- Игровые серверы — RPC используется для синхронизации состояния игры между клиентом и сервером.
- Системы управления базами данных — удалённые вызовы для выполнения запросов к распределённым БД.
Преимущества и недостатки
Преимущества
- Прозрачность расположения — разработчик не обязан заботиться о сетевых деталях.
- Простота разработки — вызов удалённой процедуры выглядит как локальный, что упрощает написание распределённых приложений.
- Языковая независимость — многие RPC-фреймворки поддерживают генерацию кода для нескольких языков, что позволяет интегрировать разнородные системы.
- Производительность — бинарные протоколы (gRPC, Thrift) обеспечивают высокую скорость передачи данных.
Недостатки
- Сетевые задержки — вызов удалённой процедуры всегда медленнее локального из-за передачи данных по сети.
- Надёжность — сеть может быть ненадёжной; необходимо обрабатывать ошибки, тайм-ауты и повторные попытки.
- Сложность отладки — ошибки в распределённой системе труднее локализовать и воспроизвести.
- Синхронность — синхронные RPC могут блокировать клиент на время ожидания ответа, что снижает отзывчивость приложения.
- Сложность управления состоянием — RPC не подходит для приложений, требующих поддержания сессионного состояния (stateful), без дополнительных механизмов.
Сравнение с другими подходами
RPC часто сравнивают с REST (Representational State Transfer). REST — это архитектурный стиль, ориентированный на ресурсы (например, документы, изображения), а не на процедуры. В REST запросы выполняются через стандартные HTTP-методы (GET, POST, PUT, DELETE), и каждый запрос является самодостаточным. RPC, напротив, фокусируется на действиях (вызове функций). RPC-системы обычно используют пользовательские протоколы и могут быть более производительными для вызовов с большим объёмом данных, но REST проще в кэшировании и масштабировании.
Другой альтернативой является асинхронный обмен сообщениями (message queue), например, RabbitMQ, Apache Kafka. В этом подходе клиент отправляет сообщение в очередь, а сервер обрабатывает его асинхронно. Это обеспечивает высокую надёжность и развязку компонентов, но не даёт прямого ответа в стиле вызова процедуры.
Интересные факты
- Термин «стаб» (stub) происходит от англ. stub — «заглушка». Стаб «заглушает» реальный вызов, превращая его в сетевой запрос.
- В 2009 году протокол Sun RPC (RFC 5531) был признан устаревшим (Historic status), но продолжает использоваться в NFSv3.
- gRPC использует HTTP/2, что позволяет мультиплексировать несколько вызовов в одном TCP-соединении, снижая накладные расходы.
- Apache Thrift поддерживает 28 языков программирования (по состоянию на 2024 год).
Источники
- Nelson, B. J. (1976). Remote Procedure Call. Stanford University.
- RFC 5531 — Remote Procedure Call Protocol Specification Version 2 (Sun RPC).
- Birrell, A. D., & Nelson, B. J. (1984). Implementing Remote Procedure Calls. ACM Transactions on Computer Systems, 2(1), 39–59.
- gRPC documentation (grpc.io).
- Apache Thrift documentation (thrift.apache.org).
- Tanenbaum, A. S., & Van Steen, M. (2007). Distributed Systems: Principles and Paradigms (2nd ed.). Pearson.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →