Что: 2d7649ccf65833e80de24d980ac1ff4536daf2bc
Когда: 2023-06-15 11:34:29+03:00
Темы: python
Parquet, ORC, Avro, Arrow, Protobuf, Thrift и MessagePack... https://habr.com/ru/companies/vk/articles/741702/ Честно говоря, я вот только названия слышал Parquet, ORC, Avro, Arrow, даже не вспомнив о чём это примерно. Не сталкивался с подобными задачами. Точнее только в составе уже готовых решений типа Hadoop. А вот с форматами серилиазции при общении между микросервисами уже имел дело. В ivi (сейчас не знаю как, ибо возможно уже всё переписано) тоже было много микросервисов: когда пользовательское приложение делает REST запрос, то за ним ещё с полдюжины запросов к разным БД и другим серверам может породиться. В основном всё общение между ними было по REST-like протоколу, где кидались всякие JSON-ы. Время затрачиваемое на (де)сериализацию JSON-а -- очень ощутимо в Python было (тогда никаких Py3 не использовалось). Даже если доли миллисекунды, то если просуммировать все многочисленные round-trip-ы между разными микросервисами, выдут десятки миллисекунд запросто. Я написал middleware для Flask, который прозрачно при запросах/ответах может смотреть на Content-Encoding заголовок и видеть в нём поддержку lz4 сжатия. lz4 для Python использовал Си-библиотеку и поэтому был очень быстрым. Это позволяло ощутимо экономить на трафике, на количестве пакетов передаваемых по сети, уменьшая задержки (размен CPU на кол-во пакетов в сети). Смотря на Content-Type и видя в нём поддержку BSON, для сериализации мог применяться BSON: он значительно быстрее JSON, хотя размер мог быть и больше. Но после lz4 сжатия размер уже роли не играл. Связка из прозрачных BSON+lz4 позволяла в разы, насколько помню, сократить задержки. Самое главное было конечно же минимизировать задержки связанные с сетью. Вместо того, чтобы просто из Flask программы подключаться requests/urllib/whatever к другому серверу, поднимался локальный nginx (не мой выбор, я то не люблю nginx) и подключения шли к нему. На противоположной стороне тоже был nginx. Между собой они поддерживали keep-alive HTTP соединение, существенно экономя на TCP roundtrip-ах. BSON был выбран потому что достаточно было поменять "json.encode" (или как там?) на "bson.encode". А сам BSON, как зависимость, уже присутствовала из-за MongoDB. Но позже поменяли это на MessagePack, который Си-binding-и имел к Python. Он был ощутимо компактнее и, действительно, очень быстрым. Насколько помню, сериализация BSON была сравнима по скорости с Python, а десериализация быстрее. MsgPack же в обе стороны был шустрее. Не все типы данных в него можно было засунуть как в JSON, но то ли нам повезло, то ли нужны были тривиальные правки к Python словарикам сериализуемым. А вот на серверах связанных с кэшированием контента, использовался Protocol Buffers. Между собой они широковещательно рассылали огромные потоки UDP пакетов со знаниями о том, у кого какой контент присутствует. Эта лавина UDP пакетов далеко не всегда полностью успевала обрабатываться и часть пакетов терялась по сути. Так как этот процесс происходил регулярно, то рано или поздно знания о соседях актуализировались. Так вот, чтобы уменьшить вероятность потерь пакетов, можно просто попытаться уменьшить их количество. В protobuf можно написать схему структуры данных которые мы хотим передавать, а дальше генератор напишет эффективный код по (де)сериализации онных. Действительно, получалось очень компактно (даже целые числа там имели варьируемой длины формат) и очень быстро даже в Python коде. Это первый и единственный раз когда я встречался с protobuf, но впечатления остались самые положительные, хотя это десять лет назад было. Причём protobuf сообщения нужно было в последствии слать между Python и Go программами -- никаких проблем тут не возникло.
Сгенерирован: SGBlog 0.34.0