Granian можно ещё раз в 10 пробустить, во первых просто поменять протокол с http1.1 на http2 даёт буст примерно в 2.5 раза а если по юникс сокету слать то и вовсе 10x можно ожидать. Количество воркеров должно быть на одно-два ядра меньше чем весь объём cpu так как рантаймовские растовские воркеры также должны свободно работать, больший объём в асинхронном коде не целесообразен так как один воркер всё ядро может поглотить. Бэклог можно спокойно увеличивать с примерным расчётом 1 * (частота процессора / 2) * количество ядер, все запросы всё равно попадают в цикл событий, лучше пусть будет выше таймаут чем возврат ошибки 500. Если запустить через python3.14-nogil -m granian то все воркеры запустяться в отдельных потоках со своим личным циклом событий, задачи будут поступать в конкретный цикл событий (скорее всего по кругу) через loop.call_soon_treadsafe() что снижает оверхед межпроцесорного взаимодействия. На unix python код в 2 раза быстрее чем на Windows даже в WSL.
Бенчам выше я бы не доверял, на практики wsgi серверы валятся с 500 ошибкой когда онлайн менее 1000 пользователей на сайте с мощным сервером, asgi/rsgi с такой нагрузкой на одном ядре справляются.
Это всё на опыте приходит, по началу такой думаешь о джанго это лучшее что смогло придумать человечество, а потом бац и сайт лежит после одновременного наплыва сотни пользователей, начинаешь нагруженные ендпоинты на асинхронку переписывать, вроде как производительность улучшилась но на 1000 коннектах база отваливается, привет сырой сиквил и кеш. Кто с подобным сталкивался по дефолту оптимизированный код пишут.
Я обожаю постгрес, когда mvp по быстрому надо сделать, одной таблицы достаточно.
CREATE TABLE IF NOT EXISTS DataObject (
ids JSONB,
extra JSONB,
space VARCHAR(50) NOT NULL,
id BIGSERIAL,
PRIMARY KEY (space, id)
) PARTITION BY LIST(space);
Аля NoSql, в ids джейсон на эту же таблицу {space: id} также и связи с внешними сервисами могут хранится, вся логика и описание extra данных на уровне выше в бекенде реализуется, в базе остаётся только тригеры на спейсы настроить для обработки ON DELETE/UPDATE событий.
Это всё на любителя, я топлю за грязный код. Есть два популярных алгоритма для поиска информации, деревья и хешмапы. Чистокодеры слишком заморачиваются и пилят структуру в виде дерева, мелкий скрипт на 2к строк раскидывают в 20+ файлов по 50-100 строк, тот кто этот код писал год спустя не сходу разберëтся от куда читать нужно начать и что с чем связано. Если всю логику в один фаил описать то VSCode сбоку всю структуру покажет, читать можно как сверху так и снизу, Ctrl+F быстрый поиск по ключу.
Мне кажется автор не удачный пример показал так как по моему пилить под каждого провайдера отдельный микросервис не всегда целесообразно так как провайдер обычно изначально как внешний сервис служит. В монолите можно просто перейти на 4ую нормальную форму или ещё проще разбить на партиции и каждую партицию в отдельной реплике запустить + микрофреймворк написать по кругу читать с реплик а писать и обновлять на мастере вот вам и не только вертикальное масштабирование.
Я несколько лет пользовался Джанго ОРМ но в итоге отказался от неë в пользу сырых запросов на asyncpg. Минусов у Джанго больше чем плюсов, описание таблиц и запросов к ним требует написания больше символов чем на sql, когда указываю on delete он управляется на уровне Джанго а не СУБД, наследование моделей создаёт связь один к один хотя по логике один к многим и фича постгре с наследованием таблиц не используется, установленные значения по дефолту также только на уровне Джанго проверяются.
Я сравниваю try/finally с with если у нас в enter есть ошибка то она передаётся в exit метод и там обрабатывается, если нету то сразу выходит из контекста. Кастомные исключения в самом объекте могут иметь фикс методы и логику.
Granian можно ещё раз в 10 пробустить, во первых просто поменять протокол с http1.1 на http2 даёт буст примерно в 2.5 раза а если по юникс сокету слать то и вовсе 10x можно ожидать. Количество воркеров должно быть на одно-два ядра меньше чем весь объём cpu так как рантаймовские растовские воркеры также должны свободно работать, больший объём в асинхронном коде не целесообразен так как один воркер всё ядро может поглотить.
Бэклог можно спокойно увеличивать с примерным расчётом 1 * (частота процессора / 2) * количество ядер, все запросы всё равно попадают в цикл событий, лучше пусть будет выше таймаут чем возврат ошибки 500.
Если запустить через python3.14-nogil -m granian то все воркеры запустяться в отдельных потоках со своим личным циклом событий, задачи будут поступать в конкретный цикл событий (скорее всего по кругу) через loop.call_soon_treadsafe() что снижает оверхед межпроцесорного взаимодействия.
На unix python код в 2 раза быстрее чем на Windows даже в WSL.
Бенчам выше я бы не доверял, на практики wsgi серверы валятся с 500 ошибкой когда онлайн менее 1000 пользователей на сайте с мощным сервером, asgi/rsgi с такой нагрузкой на одном ядре справляются.
Это всё на опыте приходит, по началу такой думаешь о джанго это лучшее что смогло придумать человечество, а потом бац и сайт лежит после одновременного наплыва сотни пользователей, начинаешь нагруженные ендпоинты на асинхронку переписывать, вроде как производительность улучшилась но на 1000 коннектах база отваливается, привет сырой сиквил и кеш. Кто с подобным сталкивался по дефолту оптимизированный код пишут.
Я обожаю постгрес, когда mvp по быстрому надо сделать, одной таблицы достаточно.
Аля NoSql, в ids джейсон на эту же таблицу {space: id} также и связи с внешними сервисами могут хранится, вся логика и описание extra данных на уровне выше в бекенде реализуется, в базе остаётся только тригеры на спейсы настроить для обработки ON DELETE/UPDATE событий.
Это всё на любителя, я топлю за грязный код. Есть два популярных алгоритма для поиска информации, деревья и хешмапы. Чистокодеры слишком заморачиваются и пилят структуру в виде дерева, мелкий скрипт на 2к строк раскидывают в 20+ файлов по 50-100 строк, тот кто этот код писал год спустя не сходу разберëтся от куда читать нужно начать и что с чем связано. Если всю логику в один фаил описать то VSCode сбоку всю структуру покажет, читать можно как сверху так и снизу, Ctrl+F быстрый поиск по ключу.
Мне кажется автор не удачный пример показал так как по моему пилить под каждого провайдера отдельный микросервис не всегда целесообразно так как провайдер обычно изначально как внешний сервис служит.
В монолите можно просто перейти на 4ую нормальную форму или ещё проще разбить на партиции и каждую партицию в отдельной реплике запустить + микрофреймворк написать по кругу читать с реплик а писать и обновлять на мастере вот вам и не только вертикальное масштабирование.
Я несколько лет пользовался Джанго ОРМ но в итоге отказался от неë в пользу сырых запросов на asyncpg. Минусов у Джанго больше чем плюсов, описание таблиц и запросов к ним требует написания больше символов чем на sql, когда указываю on delete он управляется на уровне Джанго а не СУБД, наследование моделей создаёт связь один к один хотя по логике один к многим и фича постгре с наследованием таблиц не используется, установленные значения по дефолту также только на уровне Джанго проверяются.
Я сравниваю try/finally с with если у нас в enter есть ошибка то она передаётся в exit метод и там обрабатывается, если нету то сразу выходит из контекста. Кастомные исключения в самом объекте могут иметь фикс методы и логику.
Кто бигдатой занимается, в курсе что недообучение лучше чем переобучение так как всегда можно дообучать на новых данных.
Что появилось раньше, функция или класс? =)
Мне кажется Celery давно устарел и писался он под python2, почему бы ну упростить всё до asyncio.Queue и multiprocessing.Queue ?