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) для описания сервисов и структур данных. Процесс работы включает три этапа:
- Описание сервиса — разработчик пишет файл
.thrift, в котором объявляются типы данных (структуры, перечисления, константы) и методы сервиса с их входными и выходными параметрами. - Генерация кода — компилятор
thriftобрабатывает IDL-файл и генерирует код на выбранных языках для клиента и сервера. Генерация включает:
- классы для сериализации/десериализации данных;
- заглушки (stubs) для клиента;
- скелеты (skeletons) для сервера.
- Реализация сервера и клиента — на основе сгенерированного кода разработчик пишет логику сервера (обработчики вызовов) и клиента (вызовы удалённых методов).
Компоненты стека протоколов
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 Thrift | gRPC | Apache Avro |
|---|---|---|---|
| Формат сериализации | Бинарный/JSON | Protocol Buffers | JSON/бинарный |
| Транспорт | TCP/HTTP | HTTP/2 | TCP/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).
Источники
- Официальная документация Apache Thrift (thrift.apache.org).
- Книга «Programming Thrift» by Randy Abernethy (O’Reilly Media, 2015).
- Статья «Thrift: Scalable Cross-Language Services Implementation» (Facebook, 2007).
- Сравнительный анализ RPC-фреймворков (IEEE, 2018).
- Репозиторий проекта на GitHub (github.com/apache/thrift).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →