【问题标题】:Celery does not work in AWS ECSCelery 在 AWS ECS 中不起作用
【发布时间】:2017-04-12 08:24:15
【问题描述】:

我使用 docker 将我的 django 项目部署到 AWS ECS 服务。为了使用 celery,我将 rabbitmq 设置为单独的 ec2 服务器(两个 ec2 带有代理和结果后端)。

问题是 celery 工作者在本地工作,但不在 AWS 上。 当我在本地输入docker run -rm -it -p 8080: 80 proj 命令时,worker 正在工作。

但是当我在 ECS 上部署应用程序时,worker 不工作。所以我必须在我本地的 django 项目中创建一个带有celery -A mysite worker -l INFO 的工人。尽管将主管设置为运行工人。

下面是我的代码。

Dockerfile

FROM        ubuntu:16.04

# A layer is created for each command ex)RUN, ENV, COPY, etc...
RUN         apt-get -y update
RUN         apt-get -y install python3 python3-pip
RUN         apt-get -y install nginx
RUN         apt-get -y install python-dev libpq-dev
RUN         apt-get -y install supervisor

WORKDIR     /srv
RUN         mkdir app

COPY        . /srv/app
WORKDIR     /srv/app

RUN         pip3 install -r requirements.txt
RUN         pip3 install uwsgi
ENV         DEBUG="False" \
            STATIC="s3" \
            REGION="Tokyo"

COPY        .conf/uwsgi-app.ini         /etc/uwsgi/sites/app.ini
COPY        .conf/nginx.conf            /etc/nginx/nginx.conf
COPY        .conf/nginx-app.conf        /etc/nginx/sites-available/app.conf
COPY        .conf/supervisor-app.conf   /etc/supervisor/conf.d/
COPY        .conf/docker-entrypoint.sh  /
RUN         ln -s /etc/nginx/sites-available/app.conf   /etc/nginx/sites-enabled/app.conf

EXPOSE      80
CMD         supervisord -n
ENTRYPOINT  ["/docker-entrypoint.sh"]

supervior-app.conf

[program:uwsgi]
command = uwsgi --ini /etc/uwsgi/sites/app.ini

[program:nginx]
command = nginx

[program:celery]
directory = /srv/app/django_app/
command = celery -A mysite worker -l INFO --concurrency=6
numprocs=1

stdout_logfile=/var/log/celery-worker.log
stderr_logfile=/var/log/celery-worker.err
autostart=true
autorestart=true
startsecs=10

; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 600

; When resorting to send SIGKILL to the program to terminate it
; send SIGKILL to its whole process group instead,
; taking care of its children as well.
killasgroup=true

; if rabbitmq is supervised, set its priority higher
; so it starts first
priority=998

settings.py

# CELERY STUFF
BROKER_URL = 'amqp://user:password@example.com//'
CELERY_RESULT_BACKEND = 'amqp://user:password@example.com//'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

celery.py

import os
from celery import Celery
from django.conf import settings

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
app = Celery('mysite')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

tasks.py

from celery.task import task
from celery.utils.log import get_task_logger

from .helpers import send_password_email

logger = get_task_logger(__name__)


@task(name="send_password_email_task")
def send_password_email_task(email, password):
    """Send an email when user when a user requests to find a password"""
    logger.info("Sent feedback email")
    return send_password_email(email, password)

添加 Nginx 代码...

nginx.conf

user root;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
daemon off;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    server_names_hash_bucket_size 512;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}


#mail {
#   # See sample authentication script at:
#   # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#   # auth_http localhost/auth.php;
#   # pop3_capabilities "TOP" "USER";
#   # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#   server {
#       listen     localhost:110;
#       protocol   pop3;
#       proxy      on;
#   }
#
#   server {
#       listen     localhost:143;
#       protocol   imap;
#       proxy      on;
#   }
#}

nginx-app.conf

server {
        listen 80;
        server_name localhost ~^(.+)$;
        charset utf-8;
        client_max_body_size 128M;


        location / {
                uwsgi_pass      unix:///tmp/app.sock;
                include         uwsgi_params;
        }
}

ACL 入站规则

ACL inbound rules image

任务定义

ECS Task definition capture

【问题讨论】:

  • 嗨,我不明白你说“它不起作用”。发生什么事?容器不启动?应用程序无法访问?您是否修改了 EC2 实例安全组以允许 8080 端口上的流量?开箱即用,它是关闭的。
  • 嗨~ @MaurizioBenedetti 当我在本地 8080 端口运行 docker 时,芹菜工人正在 http://localhost:8080 工作。那只是当地的情况。除 celery 外,ECS 应用服务器工作正常。我已经设置 EC2 安全组是所有流量都允许.. 容器正在为 supervisord ex 工作)Nginx 工作正常
  • 所以在本地你可以远程登录到本地主机 8080。从另一台机器你不能。正确的?有两个选项,安全组或操作系统防火墙。如果在 LInux 上运行,请检查 iptables/firewalld 的配置。您使用的是哪个防火墙?
  • @MaurizioBenedetti 我提到的安全组是 aws ec2 实例安全组。我想我应该看看iptables。这是一个我还不知道的概念。
  • 您使用的是哪个发行版和版本?我们可以在命令方面提供帮助,为了快速测试,您可以禁用防火墙

标签: django amazon-web-services docker


【解决方案1】:

解决问题太简单了。问题是我将代理节点设置为 localhost。应用代码没有问题。

【讨论】:

  • 我不太清楚你的意思。您可以在答案中添加更新的配置吗?我在部署 ECS 时遇到了类似的症状。
【解决方案2】:

如果你想在 ECS 中运行一个 celery worker 默认容器是由 root 用户执行的,并且要在 root 环境中使用 worker 你应该设置一个 env var 来这样做:

http://docs.celeryproject.org/en/latest/userguide/daemonizing.html

当您在任务定义中定义变量时,设置 C_FORCE_ROOT = true。

【讨论】:

    猜你喜欢
    • 2020-10-31
    • 2019-05-02
    • 2019-04-12
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 2018-11-12
    相关资源
    最近更新 更多