Pull to refresh
26
0
Роман Иманкулов @Outspector

User

Send message
Кто-то уже пробовал такую связку в бою?

У меня есть ничем не обоснованное подозрение, что всё это может сломаться в самый неподходящий момент. Раз Redis хранит всю свою базу в памяти, значит эта система будет работать до тех пор, пока на сервере с редисом она не закончилась. В случае DDoS-атаки количество запросов резко возрастает. Предположим, что количество залогированных запросов стало таким, что Redis увел сервер в swap и стал тормозить, замедляя работу и самого nginx-а. Наверное, такое возможно?

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

Кроме того, интересно, что произойдет, если Redis отвалится. Насколько я вижу, модуль пытается переустановить соединение. Мне кажется, это катастрофически должно сказаться на производительности сервера (кстати, этот вариант легко проверяется с помощью бенчмарков).

Если бы я настраивал что-то подобное, то скорее всего, я бы предпочел, чтобы nginx скидывал логи в обычные предсказуемые файлы, а потом по крону парсил бы их содержимое и запихивал в любую базу (и скорее всего, это был бы не Redis).
Не могу удержаться и не прокомментировать вопрос о массовых увольнениях вот такой ссылкой: Российский рынок труда: между нормой и аномалией.

Идея статьи в том, что в большинстве стран (ссылаются, в основном, на Европу) заработная плата не снижается, а адаптация к кризисам происходит в основном за счет изменения численности занятых. С этой точки зрения Google поступил вполне естественно.

В России (наверное, примерно также и в Украине) рынок труда выглядит по-другому. Здесь проще и дешевле оставить сколь угодно неэффективного работника и платить ему минимальную заработную плату, чем уволить его с соблюдением ТК. Это, с одной стороны, удобно для «всех» (для предприятия, для ленивого работника, и для гос. чиновников, рапортующих о низком уровне безработицы), а с другой стороны, понятно, что «затягивает в болото» и тормозит развитие экономики и всего такого, что принято развивать.

Я сам сталкивался с подобной ситуацией, хотя это было давно, и вопрос о соблюдении ТК там рассматривался, как оскорбление. Игровой клуб, в котором я подрабатывал админом, был «задавлен» более сильным и клевым конкурентом. Доходы падали, и когда все стало совсем плохо, руководство сказало: «Друзья мои, у нас инновация! Теперь вместо фиксированной зарплаты все будут получать процент от выручки!» Я уволился сразу же после получения первой инновационной зарплаты (что-то около 900 рублей за месяц, кажется).

Так что, как по мне, закрыть офис и разогнать сотрудников — это еще не самый худший вариант развития событий. По крайней мере, это честно. И мотивирует «не засиживаться в болоте».
По сравнению с GAE есть очень серьезное преимущество — с ep.io вы не завязаны на платформу. То есть, если вас что-то не устроит в GAE (например, цены), слезать с него вы будете долго и мучительно (ну, или не очень мучительно, зависит от того, насколько плотно вы используете специфику GAE), а проект, который вы разворачиваете на ep.io — это самый обычный Django-проект с реляционной базой данных. Если он вам не нравится — берете свой VDS или сервер, и разворачиваете всё то же самое.
Если хочется перевести, я бы перевел «запрос на включение изменений». У меня лично «извлечение» почему-то вызывает ассоциации с хирургическим вмешательством.
Кстати, pull request — это не единственный способ обратить внимание разработчика на сделанные тобой изменения. Если изменение — это bugfix и спокойно укладывается в один коммит, то возможно, более логичным будет создать отчет об ошибке (в раздел issues) и включить в описание ошибки ссылку на коммит, который ее исправляет.

Ссылку на коммит в теле сообщения специально оформлять не нужно, достаточно просто включить в текст его идентификатор. Парсер markdown распознает его, сократит и преобразует в правильную ссылку.
> ну вот и вернулись к крону, причем тут асинхронные задачи?

А разве выполнение задач через cron — это не один из способов реализации асинхронных задач? Это был пример того, что даже на ненагруженном сайте не все действия нужно выполнять синхронно, то есть в цикле обработки HTTP-запроса.

И раз уж речь зашла о «ненужном» хостинге. Панель управления управляет не только shared-хостингом. Она работает с разными серверами, в т.ч. и не на нашей площадке, а также с серверами клиентов (которые заказали VDS или разместились на collocation). При всем желании, если канал между площадками просел, или клиент загрузил свой сервер так, что тот еле ворочается, хостер ничем помочь не сможет.

Если вам не нравится такой пример, представьте, что вы парсите выдачу яндекса, обращаетесь к стороннему REST API или ходите по другому сайту, на скорость работы которого никак повлиять не можете. В любом случае, асинхронное выполнение задач, даже если клиент всего один — ваш браузер, будет удачным решением.
> Если речь о маленьких сайтах где практически нет никакой нагрузки мне сложно представить ситуацию когда нужно выполнить какие-то действия асинхронно.

Приведу такой пример, который встречается, к сожалению, довольно часто. Есть интернет-магазин, на который приходят 1,5 посетителя в сутки, и в основное время нагрузка на сайт практически нулевая. А еще у администратора есть поле upload и кнопочка типа «загрузить номеклатуру», с помощью которой он раз в сутки обновляет информацию на сайте. Через upload передается многометровый XML или XLS, который начинает тут же обрабатываться и запихиваться в базу. Даже если этот процесс хорошо оптимизирован, все равно время на обработку легко может превысить максимальное время ожидания ответа веб-сервером, и процесс будет принудительно завершен. Это типичная задача, которая просится в оффлайн, и мы (я имею в виду техподдержку NetAngels) всегда советуем обрабатывать такие задачи как раз с помощью cron-а.

Другая подобная задача возникает уже у меня. Панель управления хостингом не оперирует большим количеством данных, и большинство времени нагрузка на ней тоже близка к никакой. Однако эта панель в ответ на действия пользователя отправляет команды на удаленные серверы (создай сайт, обнови конфиг и т.п.). Если этот сервер чрезмерно нагружен или находится в другом месте и есть проблемы на каналах связи, то работать с панелью станет, как минимум, некомфортно. С другой стороны, если пользователь нажал на кнопочку «изменить пароль ftp», то заставлять ждать его 1-3 минуты, пока задание выполнит cron, тоже негуманно. Поэтому мы вместо этого формируем задания, которые celery выполняет так быстро, как ей это позволяют условия.

> ну так и сообщайте прямо из этой management command

Да, тут я согласен. Действительно, обычно не будет проблемой сообщить что-то клиенту из задачи celery или из management команды. С другой стороны, если возникла необходимость отслеживать состояние задачи из вызывающей функции, то достаточно просто сохранить async_result.task_id и периодически обращаться к задаче, проверяя, не выполнилась ли она. Объект request.session выглядит удобным местом для сохранения таких идентификаторов. В тех случаях, когда задача выполняется за время, сопоставимое с интервалом между запросами клиента, overhead будет минимальным.
Сорри, не удержался, и ответил дважды.
Никто не говорит, что добавить к задаче статус выполнения — это сложно. Речь идет о том, что это уже получается не просто «связка cron+management commands», а «связка cron+management commands+дополнительная логика, про которую нужно не забыть, и которую нужно сделать».

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

> Опять же, если вдруг что-то пошло не так, команду можно банально выполнить вручную и глянуть что происходит. А как с этим в Celery?

Создавая задачу, вы навешивает декоратор на функцию. Эта же функция может быть вызвана и напрямую, без обращения к брокеру.
Никто не говорит, что добавить к задаче статус выполнения — это сложно. Речь идет о том, что это уже получается не просто «связка cron+management commands», а «связка cron+management commands+дополнительная логика, про которую нужно не забыть, и которую нужно сделать».

С задачей расстановки приоритетов я не сталкивался, но принципиально не вижу никаких сложностей. Тот, что лежит на поверхности — запустить несколько демонов celeryd, каждый из которых будет обрабатывать свою очередь. Задачи разных приоритетов будут раскладываться в разные очереди. Интенсивность загрузки можно регулировать количеством процессов демона, обслуживающего очередь, или запустив один из демонов под найсом.

> Опять же, если вдруг что-то пошло не так, команду можно банально выполнить вручную и глянуть что происходит. А как с этим в Celery?

Создавая задачу, вы навешивает декоратор на функцию. Эта же функция может быть вызвана и напрямую, без обращения к брокеру.
Если не использовать сторонний «шлак», то этот шлак придется написать самому. Насколько я понял, асинхронные команды вы предлагаете использовать следующим образом (предполагаю, потому что сам так делал, и в некоторых случаях этот подход действительно хорошо работает):

— куда-нибудь в базу пишем команду, которую предполагается выполнить, или каким-то способом отмечаем «необработанные» объекты
— в cron добавляем задание, которое периодически (раз в минуту) проверяет список и выполняет действия с необработанными объектами.

Все работает нормально до тех пор, пока у вас 1-2 таких действия, они выполняются достаточно быстро, и задержка в 1-2 минуты с момента добавления задания до момента начала его исполнения вас устраивает. Если хотя бы одно из этих действий не выполняется, то наивный подход перестает работать, вы начинаете добавлять костыли, и вот уже незаметно для себя изобретаете велосипед.

— если задание не успевает выполниться за 1-2 минуты, то последующие задания начинают «наступать на пятки» уже выполняющемуся, и нужно придумывать блокировки. Либо на уровне задания cron (flock), либо на уровне записей в базе (вводить состояния задач: «не выполнялось», «выполняется», «выполнено»). В celery эта задача уже решена.
— если заданий у вас становится больше, чем 1-2, то либо для каждого задания (resize картинки, получение rss фида с внешнего сервера, загрузка товаров в базу и т.п.) вам нужно писать отдельную management команду, либо придумывать способ выделить общую часть, отвечающую за выполнение команд. В celery код, который непосредственно занимается работой, отделяется от кода, который занимается управлением очереди, с помощью декоратора task. Довольно элегантно, на коленке такое не скрутишь.
— если вам нужно отслеживать результат выполнения команды (было бы клево сообщить пользователю, что всё сделано), то нужно придумать отдельное хранилище для этого результата, и удобный способ его получения.

Ну, и так далее. Не факт, что при возникновении подобных проблем решить их у вас получится быстрее и лучше, чем у перфекционистов с дедлайнами, не освоившими синтаксис crontab.
Главная особенность celery вовсе не в том, что с ее помощью можно запускать периодические задания и использовать вместо cron-а (эта плюшка вообще приделана сбоку, и ее можно не использовать). Больше пользы в том, что долго выполняющееся действие можно легко отвязать от кода, который выполняется во view в ответ на запрос пользователя.

Фактически, используя celery, вы добавляете задание в очередь и на время забываете про него. Затем запущенный отдельно демон по имени celeryd это задание выполняет, а результат выполнения складывает обратно.
С одной стороны, написано про отбор, а с другой, «совсем слабых студентов мы заставим пройти через подготовительный год интенсивной математики и английского», т.е. будут и сильные, и слабые. А если будут настолько слабые, то по каким критериям предполагается делать отбор?

Так что селекция поможет снизить остроту проблемы, но не избавит от нее полностью. Люди придут разные, и пытаться с первых дней (или даже после некоторого периода обучения) заставить всех писать код в production бесперспективно. Слабые студенты — это не смертельно, а слабые сотрудники будут тормозить весь процесс, и нет никакого смысла вешать на них задачи.
Никого я в обезьян не превращаю. Ниже уже много и правильно говорили о том, что нельзя всех обучить программированию, и дело тут не в объеме мозга, а в предыдущем опыте и в том окружении, в котором рос и воспитывался человек. Ведь речь идет о вузе, а не о детском саде, и предполагается, что люди приходят туда уже со своим багажом знаний, привычек и жизненного опыта. Мне кажется, вот в этом комментарии отлично описаны проблемы, с которыми придется столкнуться.

Очень любопытный проект. Насколько я понял, основная часть идеи базируется на том, что в Сомалиленд кто-то (бесплатно?) проведет электричество толстый Интернет. Интересно узнать, кто это собирается сделать, и с какой целью?

Другой вопрос, имеет ли смысл привлекать всех студентов поголовно к работе над реальными проектами. У меня есть сильное подозрение, что нет. Скорее всего, окажется так, что у многих из обучающихся никогда не появится даже понимания того, как работают простые алгоритмы, и почему компьютеру нельзя объяснить человеческим языком, чего от него надо (я, к сожалению, ориентируюсь на собственный опыт общения со студентами). Сил на работу с ними вы потратите много, а в результате только измучаете и себя, и студентов, и заказчика.

Было бы полезнее сделать возможность работать на зарубежного заказчика привилегией, и оплачивать эту работу соответственно. Тогда и мотивация к обучению была бы выше, и полезного продукта вы смогли бы выпускать больше.
Собственно, манипуляции с объектами connection в sqlite — это решение, которое вообще завязано на базу всеми руками и ногами. Полностью согласен, вариант dump-restore для быстрой инициализации выглядит более естественным, особенно в том случае, если нужно использовать базу, отличную от sqlite.

Продолжая защищать sqlite, замечу, что никаких проблем с получением среднего арифметического там нет, и это значение можно получать через ORM. Вот доказательство
Вовсе и не в любом. Наша панель управления хостингом, например, нетривиальный проект, но мы не делаем с базой ничего такого, что не мог бы делать Django ORM. Есть у нас отдельный проект, который собирает и агрегирует всякую статистику — там тоже за пределы ORM выбираемся только, чтобы построить индексы.

И дело тут, наверное, не столько в проекте, сколько в разработчике. Когда знаешь, как использовать молоток, всё кажется гвоздем. Уверен, большинство проблем с нестандартными запросами могут быть довольно успешно решены денормализацией и кешированием.
Спасибо за наводку. Согласен с тем, что управление fixtures в проекте — это отдельная головная боль, и замедление исполнения тестов — не самое страшное из того, с чем приходится сталкиваться. Сами же мы используем кучу самописных функций типа make_test_user или make_order, которые частично эту проблему снимают.
Кажется, появился, но прошел мимо меня незамеченным.

Насколько я понял из вашего описания, речь идет о проекте factory girl. Для Django есть клон по имени factory boy и похожий по назначению инструмент django-any от kmmbvnr.

Information

Rating
Does not participate
Location
Минск, Минская обл., Беларусь
Registered
Activity