Открыть сервис

Apache Thrift

Apache Thrift — это кроссплатформенный фреймворк для разработки распределённых приложений, реализующий механизм удалённого вызова процедур (RPC). Разработанный в компании Facebook (организация, признанная экстремистской и запрещённая в РФ) в 2007 году, а затем переданный в инкубатор Apache Software Foundation, Thrift позволяет создавать клиент-серверные системы, в которых сервисы и структуры данных описываются на едином языке определения интерфейсов (IDL), а затем автоматически генерируется код для различных языков программирования. Ключевые характеристики Thrift — высокая производительность, компактность передаваемых данных и поддержка множества транспортных протоколов.

История

Разработка Thrift началась в 2007 году в компании Facebook (организация, признанная экстремистской и запрещённая в РФ) как внутреннее решение для масштабируемых сервисов социальной сети. В 2008 году код был открыт под лицензией Apache 2.0 и передан в инкубатор Apache Software Foundation. В 2010 году проект стал полноценным проектом верхнего уровня Apache. С этого момента Thrift активно развивался сообществом, получив поддержку для десятков языков и платформ. Ключевой вехой стал выход версии 0.9.0 в 2012 году, в которой были улучшены механизмы сериализации и обработки исключений. В 2019 году вышла версия 0.13.0, добавившая поддержку новых языков (например, Rust) и улучшенную работу с асинхронными вызовами.

Архитектура и принцип работы

Thrift основан на архитектуре «клиент-сервер» и использует язык определения интерфейсов (IDL) для описания сервисов и структур данных. Процесс работы включает три этапа:

  1. Описание сервиса — разработчик пишет файл .thrift, в котором объявляются типы данных (структуры, перечисления, константы) и методы сервиса с их входными и выходными параметрами.
  2. Генерация кодакомпилятор thrift обрабатывает IDL-файл и генерирует код на выбранных языках для клиента и сервера. Генерация включает:
  • классы для сериализации/десериализации данных;
  • заглушки (stubs) для клиента;
  • скелеты (skeletons) для сервера.
  1. Реализация сервера и клиента — на основе сгенерированного кода разработчик пишет логику сервера (обработчики вызовов) и клиента (вызовы удалённых методов).

Компоненты стека протоколов

Thrift предоставляет многоуровневый стек, который можно настраивать:

  • Транспортный слой — отвечает за передачу данных по сети. Поддерживаемые реализации:
  • TSocket — сокетное соединение (TCP);
  • TFramedTransport — фреймовая передача (с предварительным указанием длины сообщения);
  • TMemoryBufferработа с буфером в памяти;
  • TZlibTransportсжатие данных с помощью zlib.
  • Протокольный слой — определяет формат сериализации данных:
  • TBinaryProtocol — бинарный формат (компактный, быстрый);
  • TCompactProtocol — ещё более компактный бинарный формат (использует переменную длину для целых чисел);
  • TJSONProtocol — текстовый формат JSON (удобен для отладки);
  • TSimpleJSONProtocol — упрощённый JSON (не поддерживает все типы Thrift).
  • Серверный слой — управляет обработкой запросов:
  • TSimpleServer — однопоточный сервер (для тестов);
  • TThreadPoolServer — многопоточный сервер с пулом потоков;
  • TNonblockingServer — асинхронный сервер на основе событий (использует TFramedTransport);
  • THsHaServer — гибридный сервер с полусинхронной/полуасинхронной моделью.

Языки программирования

Thrift поддерживает кодогенерацию для более чем 20 языков, включая:

  • Основные: C++, Java, Python, PHP, Ruby, C#, Go, JavaScript, Node.js, Erlang, Perl, Haskell, Lua, Smalltalk.
  • Современные: Rust, Swift, Kotlin, Dart, TypeScript.
  • Экзотические: OCaml, D, Delphi (Object Pascal).

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

Типы данных

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

  • Базовые: bool, byte, i16 (16-битное целое), i32, i64, double, string.
  • Контейнерные: list<T>, set<T>, map<K, V>.
  • Пользовательские: struct (структура с полями), union (объединение), enum (перечисление).
  • Специальные: void (для методов, не возвращающих значения), optional (необязательные поля).

Поля структур могут иметь идентификаторы (ID) и значения по умолчанию. Для обратной совместимости рекомендуется использовать optional и избегать удаления полей.

Пример использования

Ниже приведён упрощённый пример описания сервиса на IDL и его реализации на Python.

Файл calculator.thrift

```thrift struct AddRequest { 1: required i32 a, 2: required i32 b, }

service Calculator { i32 add(1: AddRequest request), } ```

Генерация кода

``bash thrift --gen py calculator.thrift ``

Реализация сервера (Python)

```python from calculator import Calculator from thrift.transport import TSocket from thrift.protocol import TBinaryProtocol from thrift.server import TServer

class CalculatorHandler: def add(self, request): return request.a + request.b

handler = CalculatorHandler() processor = Calculator.Processor(handler) transport = TSocket.TServerSocket(port=9090) tfactory = TTransport.TBufferedTransportFactory() pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) server.serve() ```

Реализация клиента (Python)

```python from calculator import Calculator from thrift.transport import TSocket from thrift.protocol import TBinaryProtocol

transport = TSocket.TSocket('localhost', 9090) transport.open() protocol = TBinaryProtocol.TBinaryProtocol(transport) client = Calculator.Client(protocol) result = client.add(AddRequest(a=10, b=20)) print(result) # 30 transport.close() ```

Преимущества и недостатки

Преимущества

  • Высокая производительность — бинарные протоколы (TBinaryProtocol, TCompactProtocol) обеспечивают малый размер сообщений и быструю сериализацию.
  • Кроссплатформенность — поддерживаются практически все современные языки программирования.
  • Гибкость — возможность настраивать транспортный и протокольный стеки под конкретные задачи.
  • Компактность — IDL позволяет описывать сложные структуры данных без избыточности.
  • Обратная совместимость — грамотное использование optional и идентификаторов полей позволяет эволюционировать сервисы без нарушения работы старых клиентов.

Недостатки

  • Сложность отладки — бинарные протоколы нечитаемы для человека, требуется инструментарий для анализа трафика.
  • Отсутствие встроенной поддержки потоков — Thrift не предоставляет механизмов для реактивного программирования или стриминга данных.
  • Слабая поддержка асинхронности — хотя существуют неблокирующие серверы, асинхронные вызовы требуют дополнительной реализации.
  • Размер сообщений — по сравнению с современными форматами (например, Protocol Buffers), Thrift может генерировать более объёмные сообщения при использовании TBinaryProtocol.

Сравнение с аналогами

ХарактеристикаApache ThriftgRPCApache Avro
Формат сериализацииБинарный/JSONProtocol BuffersJSON/бинарный
ТранспортTCP/HTTPHTTP/2TCP/HTTP
Поддержка языков>20>10>10
ПроизводительностьВысокаяВысокаяСредняя
СтримингНетДаНет
ВерсионированиеЧерез IDЧерез поляЧерез схему

Применение

Apache Thrift широко используется в крупных распределённых системах, где требуется высокая производительность и гетерогенность языков. Примеры:

  • Социальные сети — Facebook (организация, признанная экстремистской и запрещённая в РФ) использовала Thrift для внутренних сервисов (лента новостей, сообщения, поиск).
  • Базы данныхApache Cassandra и Apache HBase используют Thrift для клиент-серверного взаимодействия (до перехода на собственные протоколы).
  • Платёжные системы — некоторые финтех-компании применяют Thrift для микросервисной архитектуры.
  • Облачные сервисыAmazon Web Services (AWS) использует Thrift для некоторых внутренних API.

Интересные факты

  • Название «Thrift» (англ. «бережливость») отражает стремление к экономному расходованию ресурсов — компактность сообщений и высокая скорость.
  • Изначально Thrift был написан на C++ и Python, но быстро распространился на другие языки.
  • В 2015 году Facebook (организация, признанная экстремистской и запрещённая в РФ) разработала собственный фреймворк Thrift на C++ под названием «Thrift2», который не был открыт.
  • Thrift является одним из старейших RPC-фреймворков, сохраняющих актуальность до сих пор (наряду с CORBA и XML-RPC).

Источники

  1. Официальная документация Apache Thrift (thrift.apache.org).
  2. Книга «Programming Thrift» by Randy Abernethy (O’Reilly Media, 2015).
  3. Статья «Thrift: Scalable Cross-Language Services Implementation» (Facebook, 2007).
  4. Сравнительный анализ RPC-фреймворков (IEEE, 2018).
  5. Репозиторий проекта на GitHub (github.com/apache/thrift).

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →