Блог им. fininja

No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера

    • 08 февраля 2024, 14:51
    • |
    • Fininja
  • Еще
No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис.1: Ответ gRPC сервера на любой вопрос.

Краткое содержание для непрограммистов: gRPC круто и быстро и знать об этом незачем. Всего хорошего!

При написании коннектора к любой бирже на 99% везде используется два основных вида способа передачи запросов и получения данных — это через отдельные REST-вызовы (например, «биржа, дай мне список инструментов») и через веб-сокеты (например, «биржа, дай мне поток обезличенных сделок по Газпромнефти»).

В этих «обычных» случаях всё общение происходит через JSON-запросы, то есть, говоря по-русски, в текстовом виде.

No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис. 2: пример запроса списка продуктов и ответа рептилоидов с сервера BitGet

Запросы нужно отсылать по заранее известным адресам API.


Но время от времени появляются необычные протоколы и вот у Тинькофф инвестиций попался gRPC.

Лезем в гугл разбираться что это за зверь и выясняем:

No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис. 3: мой стек длиннее твоего.

* gRPC работает быстрее за счет более нового и производительного стандарта http/2 (обновления данных станут более риалтаймные)
* в отличие от REST/WebSockets, у gRPC все данные передаются в бинарном виде, что быстрее и экономнее в плане размера
* gRPC работает с четкой типизацией, что означает, что сериализация/десериализация происходят «автоматически» и не надо гадать как преобразовывать данные в текст и обратно
* gRPC это все еще RPC, удаленный вызов процедур, то есть используется все так, будто ты не к удаленному серверу обращаешься, а делаешь вызов на локальной машине.

Много непонятных букв, но давайте приведу один практический пример.

No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис. 4: меняем пару буковок в строчке, которую отравляем на сервер.

Например, нам нужно получить информацию о доступных бумагах на сервере.

REST-запрос на Битгете будет выглядеть примерно так: GET запрос на адрес api.bitget.com/api/spot/v1/public/products

или в коде:

No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис. 5: Запрос доступных бумаг в OsEngine (коннектор Битгет)

Здесь мы видим сначала формирование запроса, отправку, а потом десериализацию ответа (это когда из текста мы создаем объекты данных).
Дальше объекты передаются в UpdateSecurity, где происходит окончательное формирование полей:

No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис. 6
: разбор из строки в объект.

Чтобы разобрать при помощи библиотеки JSON, нам понадобится вручную создать класс, соответствующий ответу сервера:
No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис. 7: Разработчик сделал класс, где строки ответа разложены по полочкам.

Но при этом приходится в коде приводить все к правильным типам данных.

А теперь посмотрим как все делается в gRPC?

What is gRPC?. Part 1: Authentication and… | by MD Mobin | Stackademic
Рис. 8: перерыв на обед.

В gRPC всё известно заранее благодаря .proto файлам, в которых описаны методы, предоставляемые сервером:


No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис. 9: методы получения данных по инструментам из instruments.proto Тинькофф инвестиций.

Эти прото-файлы скачиваются с сайта брокера и подключаются в проект.
А дальше происходит небольшая магия.

Из этих прото-файлов компилятор Protobuf генерит файлы с нужными функциями и объявлениями классов. Всё, что нужно, чтобы пользоваться API.
В отличие от REST, тут эти функции/типы не нужно писать самому.

Просто начинаем их использовать:

No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис. 10: получаем список акций.

То есть тип SharesResponse, InstrumentsRequest, метод Shares — все это было сгенерировано автоматически из прото-файлов.

В результате мы получаем ответ с набором объектов, у которых уже объявлены типы данных:
No REST for the Wicked - Первые впечатления от gRPC с точки зрения алготрейдера
Рис
. 11: Заполняем новый объект бумаги в коннекторе OsEngine/Tinkoff

Стоит обратить внимание, что разбираются уже объекты типа Share и да, его определение тоже было автоматом сгенерировано из прото-файла.

А еще в gRPC есть потоковая передача, которая по обещаниям должна работать лучше и быстрее вебсокетов. Но для начального знакомства это уже слишком (:

До встречи в следующем эпизоде!


Данная публикация является личным мнением автора. Мнение владельца сайта может не совпадать с мнением автора.
4.7К | ★6
16 комментариев
Делал работу с ними на swift'е. Подписка/отписка на события (котировки, статусы) через асинхронный bidir streaming у тинька очень неудобно сделана, на мой взгляд. Если отправить запрос на подписку на список А, потом отписку от Б, потом подписку на В, в ответах непонятно на какой из трёх запросов этот ответ пришёл. Неужели так сложно было какой-нибудь id прицеплять и к запросу, и к ответу? И тем более непонятно, нахрена вообще такого рода запросы сделали через стриминг.
avatar
dt0wer, да, я чувствую скоро с этим столкнусь. Меня еще зацепили лимиты — всего 300 подписок на стрим, но с другой стороны «нормальным» алгашам больше и не нужно.
avatar
Fininja, напишите, если найдёте способ сделать красивее, чем я. У меня в итоге вышло что-то вида «отправить запрос -> блокировать -> дожидаться ответа -> разблокировать». И технически криво и неудобно.
avatar
Вам не надо «думать» как распаковывать или конвертировать данные в вебсокетах, это делают готовые библиотеки.

gRPC не спасает от глупых изменений. То есть если у вас в JSON пришедшему по веб-сокету что-то изменилось и ваше приложение крашнулось, то оно точно так же даст сбой при gRPC. Единственное удобство gRPC это то что там единый формат файлов с настройками из которых потом генерится нативный код в нужном языке и вам не надо делать свои конвертации.

П.С. И да, типизированным языкам неудобно работать с JSON. Какой-нибудь PHP съест любой json и не сломается.
avatar
xezdx, согласен. Просто как-то уже привык эти классы для распаковки писать, а тут хопа — и всё само сгенерилось.

В целом понятно, что это лишь удобство, а вовсе не гарантия защиты от ошибок когда.
avatar
xezdx, на protobuf'е не JSON-ы катаются. «Точно также» не будет.
avatar
dt0wer, не знаю что вы понимаете под «точно так же». Я имел ввиду «приложение перестанет правильно работать». Суть в том, что при правильной разработке ничего случайно не меняется и нормальные разработчики не делают изменений, накладывающих дополнительные обязательства на другую сторону (типа изменения формата данных). Если такое произошло, то точно так же они сломают и любое другое приложение какие бы данные там не гонялись, хоть xml, хоть байты. Если на стороне сервера изменился протокол, а у вас нет, то ошибка так или иначе возникнет.
avatar
xezdx, если формат поменялся, изменившиеся данные вы нормально не получите, но и не «крашнитесь» (e.g. в эксепшон при десереализации не упадёте).
avatar
dt0wer, упадёт что то в эксепшн или нет — это вопрос конкретной реализации, а не протокола. И большой вопрос что хуже — кинуть ошибку или выплюнуть заведомо неправильные данные
avatar
СмартХабр-лаб 2.0
avatar
Sprite, алгаши везде о своём (:
avatar
Весьма странное сравнение.
gRPC работает быстрее за счет более нового и производительного стандарта http/2 (обновления данных станут более риалтаймные)

REST вполне себе может работать через http/2
в отличие от REST/WebSockets, у gRPC все данные передаются в бинарном виде, что быстрее и экономнее в плане размера
Вебсокеты поддерживают бинарные данные.
gRPC работает с четкой типизацией, что означает, что сериализация/десериализация происходят «автоматически» и не надо гадать как преобразовывать данные в текст и обратно
При нормальном дизайне rest коннектора — тоже ни о чем гадать не нужно — есть строго типизированный объект, где каждое поле можно однозначно разобрать. Да, писать придется руками (хотя если есть swagger — можно тоже автоматом все сгенерировать)
gRPC это все еще RPC, удаленный вызов процедур, то есть используется все так, будто ты не к удаленному серверу обращаешься, а делаешь вызов на локальной машине.
То что удаленный вызов спрятан ничего не меняет, ровно так же можно все спрятать и для реста
Рис. 6: разбор из строки в объект.

Чтобы разобрать при помощи библиотеки JSON, нам понадобится вручную создать класс, соответствующий ответу сервера:
У вас кровь из глаз от такого не течет? Зачем разбирать сначала в строки, а потом героически их парсить? Почему бы не разобрать сразу в нужные типы?
avatar
Aleksandr Chernikov, да, я скорее про типичную ситуацию с торговыми апи разных бирж. В целом конечно практически те же яйца, только в профиль.
 
avatar
мосбиржа все таки потехнологичней будет. все подобные штуки давно в прошлом
avatar
болеемодно flatbuffers, тоже от гугла
avatar
Roman Ivanov, ну если какой-нибудь модный брокер даст апишку на таких, то будем разбираться
avatar

Читайте на SMART-LAB:
Фото
Финансовые результаты Аэрофлота по РСБУ за 6 месяцев 2026 года
Аэрофлот опубликовал финансовые результаты по РСБУ за 2 квартал и 6 месяцев 2026 года. ✈️ Выручка во 2 квартале увеличилась на 3,3% год к году и...
Фото
Эмитент допустил дефолт: что делать инвесторам в таком случае?
Дефолт по облигациям не всегда означает полную потерю вложений. Даже если эмитент перестал платить купоны или не погасил долг, инвестор...
Ключевые тезисы менеджмента Норникеля по итогам раскрытия финансовых результатов за 1П 2026 г.
Сегодня мы раскрыли финансовые результаты за 1П 2026 г. по МСФО. Все наши материалы доступны на сайте...

теги блога Fininja

....все тэги



UPDONW
Новый дизайн