Программирование

Celery: 'Отказано в доступе' на Windows 11 с RabbitMQ

Разбор ошибки Celery worker 'Отказано в доступе' (WinError 5) на Windows 11 с RabbitMQ 4.2.0. Причина в billiard и семафорах, решения: gevent, solo, права доступа, WSL/Docker для продакшена.

Celery worker выдает ошибку ‘Отказано в доступе’ на Windows 11 с RabbitMQ 4.2.0

Настройка:

  • Операционная система: Windows 11
  • RabbitMQ: 4.2.0
  • Celery: v5.5.3

Код конфигурации celery.py:

python
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
app = Celery('config')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

Код tasks.py:

python
from celery import shared_task

@shared_task
def add(x, y):
 return x + y

Команда запуска воркера:
celery -A config:celery_app worker -l info

Логи ошибок:

[2025-11-12 16:20:03,963: ERROR/SpawnPoolWorker-3] Pool process <billiard.pool.Worker object at 0x0000026A1B232BA0> error: PermissionError(13, 'Отказано в доступе', None, 5, None)
Traceback (most recent call last):
 File "C:\pch_projects\net-base\microservices\db-operations-service\db-ops-venv\Lib\site-packages\billiard\pool.py", line 473, in receive
 ready, req = _receive(1.0)
 ~~~~~~~~^^^^^
 File "C:\pch_projects\net-base\microservices\db-operations-service\db-ops-venv\Lib\site-packages\billiard\pool.py", line 445, in _recv
 return True, loads(get_payload())
 ~~~~~~~~~~~^^
 File "C:\pch_projects\net-base\microservices\db-operations-service\db-ops-venv\Lib\site-packages\billiard\queues.py", line 394, in get_payload
 with self._rlock:
 ^^^^^^^^^^^
 File "C:\pch_projects\net-base\microservices\db-operations-service\db-ops-venv\Lib\site-packages\billiard\synchronize.py", line 115, in __enter__
 return self._semlock.__enter__()
 ~~~~~~~~~~~~~~~~~~~~~~~^^
PermissionError: [WinError 5] Отказано в доступе

Что было предпринято:
По совету ИИ был заменен стандартный пул на gevent, что решило проблему. Однако хочется понять корневую причину возникновения ошибки и разобраться в деталях.

Вопрос:
В чем заключается причина возникновения ошибки ‘Отказано в доступе’ при запуске Celery воркера на Windows 11 с использованием стандартного пула процессов, и как правильно настроить окружение для избежания этой проблемы?

Ошибка celery отказано в доступе (WinError 5) на Windows 11 с RabbitMQ 4.2.0 возникает из-за проблем с семафорами в библиотеке billiard при стандартном пуле prefork — Windows не позволяет создавать named locks без повышенных прав. Это классическая засада multiprocessing на Винде: fork недоступен, используется spawn, и процессы не могут обмениваться сигналами без конфликта UAC. Быстрое решение — запуск с --pool=gevent или --pool=solo, но для стабильности лучше мигрировать в WSL или Docker.


Содержание


Симптомы ошибки celery отказано в доступе

Представьте: запускаете celery -A config worker -l info, и вместо тихой работы задач вроде @shared_task def add(x, y) вылетает трейсбек. В логах — чистый WinError 5:

PermissionError: [WinError 5] Отказано в доступе

Конкретно у вас в billiard.pool.py строка 473, потом queues.py:394 с _rlock и synchronize.py:115 с _semlock.__enter__(). Это не случайность. Worker пытается создать пул процессов, но один из SpawnPoolWorker не может захватить семафор для обмена сообщениями. Задачи вроде add(x, y) даже не доходят до исполнения — всё стопорится на старте.

А что если заглянуть глубже? В вашем случае с Celery 5.5.3 и Django это повторяется стабильно, особенно если venv свежий и PyCharm в деле.


Корневая причина: billiard и WinError 5

Сердце проблемы — billiard, multiprocessing-библиотека под капотом Celery. Стандартный пул по умолчанию — prefork, который на Unix fork’ит процессы (дешево и сердито). Но на Windows 11 fork запрещён по дизайну: вместо него spawn — каждый worker заново импортирует модули и стартует чистый Python-процесс.

Вот где засада: процессы общаются через named semaphores и locks (из win32 API). Billiard создаёт их с именами вроде billiard-xxx, но Windows требует прав на создание глобальных named objects. UAC (User Account Control) или sandbox текущего пользователя блокирует это — бац, celery отказано в доступе.

Смотрите реальный баг в billiard: там точно такой же трейсбек в queues.py:87 с self._sem.acquire(). Не вы один — это системная хрень multiprocessing на Винде с 3.6+ версий Python.

Почему не всегда? Зависит от пользователя: если admin — может прокатить, но не надёжно.


Почему это происходит именно на Windows 11

Celery windows 11 — комбо из эволюции ОС. Windows 10/11 усилили изоляцию: семафоры теперь проверяют ACL (Access Control Lists) строже. Плюс Defender и ASLR добавляют паранойи. На Linux такого нет — там fork летает без именованных объектов.

Ваш лог показывает SpawnPoolWorker-3 — третий процесс не прошёл handshake. Billiard пытается _receive() payload, но lock не даётся. RabbitMQ тут ни при чём: брокер ждёт, проблема в локальном пуле воркера.

Коротко: winerror 5 celery — это когда Python multiprocessing встречает Windows security model. Не баг Celery, а фича ОС.


Влияние RabbitMQ и конфигурации

RabbitMQ windows (версия 4.2.0) работает идеально — он Erlang-based, не лезет в ваши семафоры. Ваш celery.py с app.config_from_object('django.conf:settings', namespace='CELERY') стандартный, autodiscover_tasks ок. Проблема не в брокере или tasks.py, а в --pool=prefork (по умолчанию).

Если AMQP соединение живое (проверьте rabbitmqctl list_queues), то ошибка чисто worker-side. Gevent сработал, потому что он event-loop based, без форков — greenlets делят один процесс, семафоры не нужны.


Быстрые решения: смена пула воркера

Вы уже пробовали — и gevent спас. Но разберём все варианты. Главное: укажите --pool явно, prefork на Винде — зло.

  1. Gevent (рекомендую для IO-bound задач):
pip install gevent
celery -A config worker --pool=gevent --concurrency=1000 -l info

Один процесс, тысячи greenlets. Легко масштабируется.

  1. Solo (для тестов/debug):
celery -A config worker --pool=solo -l info

Без пула вовсе — синхронно. Медленно, но стабильно.

  1. Threads:
celery -A config worker --pool=threads --concurrency=20 -l info

GIL жрёт CPU-bound, но для простых задач как add(x,y) ок.

В celery.py добавьте:

python
app.conf.worker_pool = 'gevent' # дефолт для всех воркеров

Перезапуск — и celery отказано в доступе уходит.


Настройка прав доступа и окружения

Если хотите prefork (не советую), фиксим права:

  • Запуск от админа: Правой кнопкой на cmd/PowerShell → “Запуск от имени администратора”. Или runas /user:Administrator.
  • Отключить UAC (временно): msconfig → Tools → Change UAC → Never notify. Рискованно!
  • Проверить директории: icacls venv_path /grant Users:F — дать full права venv и logs.
  • Антивирус: Добавьте venv в исключения Defender (Real-time protection → Exclusions).
  • Named pipes/semaphors: В реестре HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Protection Mode — но не трогайте без нужды.

Из StackOverflow примера: часто виноваты logs или temp dirs. Создайте CELERYD_LOG_DIR с правами.

Но честно: это костыли. Лучше пул менять.


Рекомендации для продакшена

RabbitMQ windows популярен (115 запросов в Wordstat), но Celery на нём в проде — через WSL2/Docker:

  • WSL2: wsl --install Ubuntu, установите RabbitMQ/Celery внутри. Нативный fork работает.
  • Docker:
docker run -d --name celery-worker -v $(pwd):/app celery:5.5 python -m celery -A config worker --pool=gevent

Compose с RabbitMQ сервисом — идеал.

  • Linux VM или облако (Yandex Cloud, AWS EC2).

Для Django: docker-compose up с multi-stage build. Забудьте про native Windows в проде — 99% devops так делают.


Примеры команд и конфигураций

Полный запуск с gevent:

celery -A config:celery_app worker --pool=gevent --concurrency=500 --logfile=celery.log -l info

В settings.py:

python
CELERY_BROKER_URL = 'amqp://guest:guest@localhost:5672//'
CELERY_RESULT_BACKEND = 'rpc://'
CELERY_WORKER_POOL = 'gevent'
CELERY_WORKER_CONCURRENCY = 1000

Тест: celery -A config call config.tasks.add --args='[2, 3]' — увидите 5.


Часто задаваемые вопросы (FAQ)

Почему gevent решает проблему?
Нет multiprocessing — нет семафоров. Monkey-patching делает всё async.

Можно ли оставить prefork?
Технически да, с admin/UAC off. Но в проде — нет, scaling сломается.

RabbitMQ 4.2.0 виноват?
Нет, апгрейдьте до 4.x stable, но проблема в Celery.

Альтернативы Celery?
RQ с Redis проще на Винде.



Источники

  1. GitHub billiard issue #328 — точный трейсбек с PermissionError в queues.py.
  2. StackOverflow: Celery log Permission Denied — примеры с правами на Windows.
  3. StackOverflow: Celery not running Permission Denied — проверка прав на dirs/logs.
  4. StackOverflow: Celery service PermissionError — запуск под пользователем.

Заключение

Корень celery отказано в доступе на Windows 11 — конфликт billiard семафоров с prefork пулом, где spawn требует прав, которых нет. Gevent/solo фиксит на раз, но для серьёзного дела — WSL/Docker с rabbitmq windows. Протестируйте --pool=gevent, добавьте concurrency, и ваш add(x,y) полетит. В итоге: Винда для dev ок, но прод — Linux always wins. Удачи с задачами!

Авторы
Проверено модерацией
Модерация
Celery: 'Отказано в доступе' на Windows 11 с RabbitMQ