Pull to refresh
22
-1
Oleg Churkin @Bahusss

Development Lead

Send message

А какие есть альтернативы gevent'у в 2022?

Под альтернативами я имею ввиду фреймворк, который за пару строк превращает приложение написанное в синхронном стиле в асинхронное.

В данный момент используем только стандартный куберовский rolling-update, canary релизы в далеких планах.

Мы используем ORM peewee и инструмент для миграций созданный внутри QIWI: https://github.com/aachurin/peewee_migrations, он позволяет автоматизировать создание миграций и конвертирует их в безопасные с ключом --autocommit.

На своем проекте мы реализовали доступ через прокси сервер, который расположен в окружении для которого реестр доступен :)

В общем случаем можно воспользоваться зеркалом Яндекса: https://cloud.yandex.ru/blog/posts/2022/03/terraform-and-packer

Интересно как появляется этот гигабайт данных изначально? Некий воркер собирает его из разных источников в памяти? Что будет если этот воркер упадет на полпути? Заново начнет пересобирать?

В классическом ETL не зазорно иметь какой-нибудь простой сторадж, в котором хранить временные данные, хоть в базе хоть в файле.

Основная проблема с редисом в том, что если очередь не влазит в память, она теряется вообще вся. И это как бы by-design, решить с этим ничего нельзя. Разве что выдавать редису меньше памяти, чем на самом деле доступно и в случае аварии докидывать ему сверху.

Можете подтвердить это ссылкой на источник? Все очень сильно зависит от настроек самого редиса и системы, например в дефолтном конфиге четвертой версии github.com/antirez/redis/blob/4.0/redis.conf, параметр maxmemory-policy noeviction – это значит что ни при каких обстоятельствах ни один ключ не потеряется, т.е. celery будет просто отваливаться с ошибкой при постановке новых задач, если они не влезают в память.

По поводу примера, мне несколько сложно понять, что мешает сделать такую логику:


Мне кажется на видео это момент разобран подробнее, проблемы которые мы хотели решить:

1. Маштабируемость решения: не завалить редис и решить нюансы с задачей деспечеризации.
2. Сэмулировать более подходящий для нас рейт лимит по задачам, потому что рейтлимит на воркер нас не устраивал.

Вариант засасывать все айди из базы и создавать все необходимые задачи в одной задаче диспетчеризации к сожалению не скейлится. Более того появляется одна большая точка отказа в виде задачи диспетчеризации – она долго выполняется, занимает время воркера и если с ней что-то случится во время ее работы система может оказаться в неопределенном состоянии.
Ну так и надо ему в этом помочь.

Этим приведенный вами код и занимается, как и мой. Но ваш вариант более элегантен, спасибо.

А в текущем виде декораторы classmethod и staticmethod вообще никак не влияют на поведение функции — это же неправильно.

Это очевидно, потому что в примере мы заменяем все эти методы на один PolyMethod, который by-design обертка, которую я не старался сделать похожей во всем на оригинальные методы. Задачи такой не было: «Совсем не production-ready код, но очень хороший пример».

Вот к чему это приводит:

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

Но вы же так не делаете.

Я и состояние не храню.

Декоратор classmethod сам этот объект класса туда засовывает.

Только в том случае, если вы вызываете этот метод у класса «CLASS.method», потому что classmethod – это декоратор, который создает хитрый дескриптор. В момент создания PolyMethod-ов, класса еще нет, поэтому и classmethod о нем ничего не знает.
Зато у них будет одинаковый self. Тот самый, который возвращается из __get__

Ну если хранить какое-то состояние в классе PolyMethod, то да, возможны проблемы, но это легко решается созданием каждый раз нового объекта в __get__.

Тем страньше что вам потребовалось сохранение cls — ведь обычные методы его не сохраняют...

classmethod требует объект класса первым параметром.
А не будет ли тут проблем с мутабельностью?


А какие именно? У двух разных объектов будет 2 разных instance, поэтому привязка должна быть точной.

Интерпретатор помещает в словарь не unbound функции, а простые функции.


Насколько я помню термина unbound function в питоне нет, есть unbound method, но для Python 3 он не актуален, в тексте статьи я написал «unbound функции» подразумевая, что это обычные функции, которые после привязки к объекту станут методами. Может быть стоит переписать этот участок, чтобы он никого не смущал.

Если теперь взять метод foo.bar — он окажется привязан к объекту foo, хотя должен бы к t1000.


Это интересный кейс, спасибо) Но привязка к определенному объекту\классу достаточно сильно усложнит код примера, поэтому я использовал самый простой и короткий вариант. Он конечно оказался с сайд-эффектами.
А почему бы для этих целей не использовать фабрику классов, которая в зависимости от переданных параметров возвращала бы нужный класс с нужным набором методов?
Промазал, ответил вам ниже.
Хм… это самописное решение или таки celery?


celery, мы в таски передаем только id-шники, сообщение в таком случае и не должно занять больше 2Кб.

В сообщениях приходится передавать большие объемы информации


Все еще не совсем понятен юзекейс, зачем вы передаете в задачу всю информацию по событию? Событие в sentry все равно посылается асинхронно без задач, а в других случаях разве не нужно сохранять это событие в промежуточный сторадж (база, кэш)? Чтобы потом прочитать его в задаче по ключу? Мы у себя редко передает в параметры задач что-то больше 2Кб. Вся информация, которая нужна в задаче «достается» из каких-либо стораджей.

Задачи выполняются очень долго и все время, пока выполняются висят в очереди (кстати, а у вас так или вы как-то по другому удостоверяетесь в том, что задача не пропала?)


Мы ставим максимальный софт таймаут для некоторых задач на 5 минут, если задача работает больше – значит это ненормально и что-то пошло не так, если внешний сервис лежит, то в задачах у нах предусмотрен exponential backoff и подходящая retry policy. А что значит «не пропала»? Вы имеете ввиду гарантируем ли мы как-то что все задачи действительно выполнены? Нет не гарантируем, да и сам redis такого не гарантирует, но мы знаем об этой особенности, для нашего проекта она пока не критична.

Задачи идут волнами. Например, есть задача «импорт с внешнего источника» и она создает большое количество задач волнами, что как бы приводит к их накоплению.


Буду об этом рассказывать в своем докладе. Мы тоже несколько раз получали task flooding, поэтому поигрались с настройками и написали свой чанкификатор задач, который запускает их определенными порциями и таким образом обеспечивает равномерное накопление задач в очередях и не перегружает внутренние (например базу) и внешние сервисы.

Ну и да, возвращаясь к редису — вы его как-то кластеризируете или он у вас просто так стоит как единая точка отказа?


Пока мы кластеризуем его хуже чем нам хотелось бы, AWS обеспечивает автоматический фейловер в случае если с мастер нодой что-то случилось, но в те несколько секунд пока происходит фейловер – постановка задач фейлится, может быть какие-то окажутся потеряны. Эту проблему мы у себя пока не решили, но можно посмотреть в сторону github.com/dealertrack/celery-redis-sentinel – там есть retry в случае connection error'a.

redis для очередей вполне production-ready решение, проверено уже на многих проектах.
При 50000 задач ежесекундно (при условии что воркеры успевают их разгребать) redis в нашем проекте потреляет 80 Мб памяти.

Если очередь перестает помещаться в память, то скорее всего происходит что-то не то: либо задачи накапливаются – что не очень хорошо, либо вы передаете в сообщениях мегабайты данных, чего тоже делать не стоит.
Сколько вопросов вы зададите интервьюеру, чтобы понять насколько он технически подкован? Почему он должен отвечать на ваши вопросы, если на интервью пришли вы а не он?

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

В комментарии ниже вы привели пример хорошего вопроса после интервью, а еще можно спросить – какие архитектурные проблемы сейчас есть у проекта? как их планируют решать? почему выбрали именно такой стек технологий? как устроен процесс разработки (кто ставит задачи, есть ли тестирование)?

Это тоже хорошие вопросы, которые позволяют понять и техническую развитость компании\команды, культуры разработки и проблемы над которыми нужно будет работать.

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

На мой взгляд такое поведение подтверждает наличие проблем с теми самыми «soft skills» у кандидата и поэтому я отнес его к «антипаттернам».
Понятно. Это тот тип вопросов, который не стоит спрашивать на собеседовании :)

Ваш будущий руководитель совсем не обязан разбираться в каких-то определенных технических тонкостях. По разным причинам. Например он хочет нанять вас, чтобы вы смогли усилить его команду с вашими знаниями в нужных технологиях. Более подробно этот момент описан в книге «Как пасти котов» Дж. Рейнвотера.
Какие вопросы вы бы задали непосредственному руководителю, чтобы быть в нем уверенным?
Эта фраза относится к кандидатам, которые после нескольких неудачных ответов на вопросы, пытаются проверить технические знания интервьюера, что выглядит слегка наивным «ах вот ты как? а сам то сможешь ответить?».

К вопросам про работу\процессы после интервью это конечно не относится.
Кстати часто собеседуют не те люди, с которыми предстоит работать и это тоже стоит иметь ввиду.
1
23 ...

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity