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:
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:
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 отказано в доступе
- Корневая причина: billiard и WinError 5
- Почему это происходит именно на Windows 11
- Влияние RabbitMQ и конфигурации
- Быстрые решения: смена пула воркера
- Настройка прав доступа и окружения
- Рекомендации для продакшена
- Примеры команд и конфигураций
- Часто задаваемые вопросы (FAQ)
- Источники
- Заключение
Симптомы ошибки 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 на Винде — зло.
- Gevent (рекомендую для IO-bound задач):
pip install gevent
celery -A config worker --pool=gevent --concurrency=1000 -l info
Один процесс, тысячи greenlets. Легко масштабируется.
- Solo (для тестов/debug):
celery -A config worker --pool=solo -l info
Без пула вовсе — синхронно. Медленно, но стабильно.
- Threads:
celery -A config worker --pool=threads --concurrency=20 -l info
GIL жрёт CPU-bound, но для простых задач как add(x,y) ок.
В celery.py добавьте:
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:
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 проще на Винде.
Источники
- GitHub billiard issue #328 — точный трейсбек с PermissionError в queues.py.
- StackOverflow: Celery log Permission Denied — примеры с правами на Windows.
- StackOverflow: Celery not running Permission Denied — проверка прав на dirs/logs.
- 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. Удачи с задачами!