Celery: OSError: Sockel im Sellerie-Arbeiter mit Eventlet geschlossen

Erstellt am 14. Juni 2018  ·  23Kommentare  ·  Quelle: celery/celery

Sellerie-Version: 4.2.0

Schritte zum Reproduzieren

docker-compose.yml

version: '2'

services:
  worker:
    build: .
    depends_on:
      - rabbitmq

  rabbitmq:
    image: rabbitmq:alpine

Dockerfile

FROM alpine

RUN apk add --no-cache build-base python3 python3-dev
RUN pip3 install celery eventlet

CMD celery -b amqp://rabbitmq worker -P eventlet --loglevel=DEBUG
$ docker-compose up --build

Erwartetes Verhalten

Der Mitarbeiter bleibt fehlerfrei in Verbindung

Tatsächliches Verhalten

3 Minuten nach dem Start meldet der Worker mehrere Fehler mit einem Traceback, ähnlich wie folgt:

[2018-06-14 20:11:44,213: WARNING/MainProcess] Traceback (most recent call last):
[2018-06-14 20:11:44,213: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/eventlet/hubs/poll.py", line 114, in wait
    listener.cb(fileno)
[2018-06-14 20:11:44,214: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/celery/worker/pidbox.py", line 120, in loop
    connection.drain_events(timeout=1.0)
[2018-06-14 20:11:44,214: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/kombu/connection.py", line 301, in drain_events
    return self.transport.drain_events(self.connection, **kwargs)
[2018-06-14 20:11:44,215: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/kombu/transport/pyamqp.py", line 103, in drain_events
    return connection.drain_events(**kwargs)
[2018-06-14 20:11:44,216: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/amqp/connection.py", line 491, in drain_events
    while not self.blocking_read(timeout):
[2018-06-14 20:11:44,217: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/amqp/connection.py", line 496, in blocking_read
    frame = self.transport.read_frame()
[2018-06-14 20:11:44,217: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/amqp/transport.py", line 243, in read_frame
    frame_header = read(7, True)
[2018-06-14 20:11:44,218: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/amqp/transport.py", line 426, in _read
    raise IOError('Socket closed')
[2018-06-14 20:11:44,218: WARNING/MainProcess] OSError: Socket closed
[2018-06-14 20:11:44,219: WARNING/MainProcess] Removing descriptor: 7

Darüber hinaus meldet der rabbitmq-Server Warnungen ähnlich den folgenden (zweimal wiederholt):

2018-06-14 20:11:44.209 [warning] <0.586.0> closing AMQP connection <0.586.0> (172.19.0.3:42678 -> 172.19.0.2:5672):
missed heartbeats from client, timeout: 60s
Eventlet Workers Pool Gevent Workers Pool RabbitMQ Broker Bug Report

Hilfreichster Kommentar

@auvipy warum hast du das geschlossen? Das Problem besteht weiterhin.

Alle 23 Kommentare

Beachten Sie, dass der rabbitmq-Server bei Verwendung von prefork anstelle von eventlet weiterhin die Warnung zu fehlenden Herzschlägen meldet, im Worker jedoch keine Warnungen gedruckt sind:

2018-06-14 20:36:04.807 [warning] <0.698.0> closing AMQP connection <0.698.0> (172.19.0.3:46040 -> 172.19.0.2:5672):
missed heartbeats from client, timeout: 60s

Und gevent schlägt mit einer ähnlichen Fehlermeldung wie eventlet fehl:

[2018-06-14 20:43:29,908: WARNING/MainProcess] Traceback (most recent call last):
[2018-06-14 20:43:29,908: WARNING/MainProcess] File "src/gevent/_waiter.py", line 119, in gevent.__waiter.Waiter.switch
[2018-06-14 20:43:29,908: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/celery/worker/pidbox.py", line 120, in loop
    connection.drain_events(timeout=1.0)
[2018-06-14 20:43:29,909: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/kombu/connection.py", line 301, in drain_events
    return self.transport.drain_events(self.connection, **kwargs)
[2018-06-14 20:43:29,909: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/kombu/transport/pyamqp.py", line 103, in drain_events
    return connection.drain_events(**kwargs)
[2018-06-14 20:43:29,909: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/amqp/connection.py", line 491, in drain_events
    while not self.blocking_read(timeout):
[2018-06-14 20:43:29,910: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/amqp/connection.py", line 496, in blocking_read
    frame = self.transport.read_frame()
[2018-06-14 20:43:29,910: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/amqp/transport.py", line 243, in read_frame
    frame_header = read(7, True)
[2018-06-14 20:43:29,911: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/amqp/transport.py", line 418, in _read
    s = recv(n - len(rbuf))
[2018-06-14 20:43:29,911: WARNING/MainProcess] File "/usr/lib/python3.6/site-packages/gevent/_socket3.py", line 380, in recv
    return _socket.socket.recv(self._sock, *args)
[2018-06-14 20:43:29,912: WARNING/MainProcess] ConnectionResetError: [Errno 104] Connection reset by peer
[2018-06-14 20:43:29,912: WARNING/MainProcess] 2018-06-14T20:43:29Z
[2018-06-14 20:43:29,913: WARNING/MainProcess] <built-in method switch of gevent.__greenlet_primitives.TrackedRawGreenlet object at 0x7f791830ce88> failed with ConnectionResetError

Außerdem kann ich mit dieser Docker-Datei bestätigen, dass ich in den neuesten Entwicklungsversionen aller Bibliotheken dasselbe Verhalten sehe:

FROM alpine

RUN apk add --no-cache build-base python3 python3-dev
RUN pip3 install https://github.com/celery/celery/zipball/master#egg=celery https://github.com/celery/billiard/zipball/master#egg=billiard https://github.com/celery/py-amqp/zipball/master#egg=amqp https://github.com/celery/kombu/zipball/master#egg=kombu https://github.com/celery/vine/zipball/master#egg=vine eventlet gevent

CMD celery -b amqp://rabbitmq worker -P eventlet --loglevel=DEBUG

Dies entspricht dem, was wir erleben. In einer einzelnen Warteschlange haben wir mehrere Mitarbeiter task_acks_late = True und worker_prefetch_multiplier = 1 und wir haben eine Mischung aus lang anhaltenden und kurzen Aufgaben.

Wenn Sie wieder zu Celery 3.x wechseln, wird dieses Problem "verschwinden".

Zu Ihrer Information

Bei Sellerie 4.1.0 und Kombu 4.1.0 funktionierten die Wiederholungsversuche zunächst nicht. Nach der Aktualisierung auf 4.2.0 bzw. 4.2.1 begannen die Wiederholungsversuche zu funktionieren, es wurden jedoch dieselben Timeout-Meldungen angezeigt, und die Aufgaben schienen korrekt zugestellt zu sein, wurden jedoch nie von den Mitarbeitern verarbeitet. Wir verwenden prefork

-amqp==2.2.2
+amqp==1.4.9
-billiard==3.5.0.3
+billiard==3.3.0.23
-celery==4.2.0
+celery==3.1.23
-kombu==4.2.1
+kombu==3.0.34
-pyramid-celery==3.0.0
+pyramid-celery==2.0.0

Die Brokerverbindung verwendet standardmäßig die Heartbeat-Einstellung aus der App-Konfigurationsdatei (seit Version 4.2.0 , # 4148).

Konfiguration und Standardeinstellungen - Dokumentation

Broker_Heartbeat

Transporte unterstützt:

  • pyamqp

Standard: 120.0 (vom Server ausgehandelt).

Sie können versuchen, broker_heartbeat=0 . Hoffe das hilft.

@ y0ngdi Ich habe broker_heartbeat=0 , es gibt eine Reduzierung des Fehlers, aber er existiert immer noch.

amqp==2.3.2
celery==4.2.0
gevent==1.3.4
greenlet==0.4.13
kombu==4.2.0
Der Worker meldet mehrere Fehler mit einem Traceback:
[2018-06-22 09:41:21,467: INFO/MainProcess] sync with celery<strong i="11">@device_producer_tasks</strong>
[2018-06-22 09:41:21,468: ERROR/MainProcess] Control command error: error(32, 'Broken pipe')
Traceback (most recent call last):
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/celery/worker/pidbox.py", line 46, in on_message
    self.node.handle_message(body, message)
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/kombu/pidbox.py", line 129, in handle_message
    return self.dispatch(**body)
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/kombu/pidbox.py", line 112, in dispatch
    ticket=ticket)
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/kombu/pidbox.py", line 135, in reply
    serializer=self.mailbox.serializer)
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/kombu/pidbox.py", line 265, in _publish_reply
    **opts
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/kombu/messaging.py", line 181, in publish
    exchange_name, declare,
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/kombu/messaging.py", line 203, in _publish
    mandatory=mandatory, immediate=immediate,
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/amqp/channel.py", line 1732, in _basic_publish
    (0, exchange, routing_key, mandatory, immediate), msg
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/amqp/abstract_channel.py", line 50, in send_method
    conn.frame_writer(1, self.channel_id, sig, args, content)
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/amqp/method_framing.py", line 166, in write_frame
    write(view[:offset])
  File "/home/ubuntu/.local/share/virtualenvs/backend-uRCQ3Clv/local/lib/python2.7/site-packages/amqp/transport.py", line 275, in write
    self._write(s)
  File "/usr/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 32] Broken pipe

Ich bin auf dieses Problem mit Sellerie 4.2 und Eventlet gestoßen, habe aber keine perfekte Lösung gefunden

Ich habe ein wenig nachgeforscht. Sellerie stellt zwar eine neue Verbindung her, ruft jedoch nicht heartbeat_check dafür auf. Dies führt dazu, dass der RabbitMQ-Server die Verbindung schließt. Ich habe diesen Fehler bei der Befehlsverbindung festgestellt (z. B. stats , ping , ..).

Minimales Beispiel:

from __future__ import absolute_import, unicode_literals
from celery import Celery

app = Celery(
    'myapp',
    broker='amqp://guest@localhost//',
)
app.conf.broker_heartbeat = 5


if __name__ == '__main__':
    app.start()

Führen Sie das Beispiel aus

$ python3 example.py worker -l DEBUG

RabbitMQ-Protokolle

2018-06-27 19:49:41.109 [info] <0.471.1> accepting AMQP connection <0.471.1> (127.0.0.1:42744 -> 127.0.0.1:5672)
2018-06-27 19:49:41.111 [info] <0.471.1> connection <0.471.1> (127.0.0.1:42744 -> 127.0.0.1:5672): user 'guest' authenticated and granted access to vhost '/'
2018-06-27 19:49:41.116 [info] <0.479.1> accepting AMQP connection <0.479.1> (127.0.0.1:42746 -> 127.0.0.1:5672)
2018-06-27 19:49:41.118 [info] <0.479.1> connection <0.479.1> (127.0.0.1:42746 -> 127.0.0.1:5672): user 'guest' authenticated and granted access to vhost '/'
2018-06-27 19:49:41.131 [info] <0.500.1> accepting AMQP connection <0.500.1> (127.0.0.1:42748 -> 127.0.0.1:5672)
2018-06-27 19:49:41.133 [info] <0.500.1> connection <0.500.1> (127.0.0.1:42748 -> 127.0.0.1:5672): user 'guest' authenticated and granted access to vhost '/'
2018-06-27 19:49:56.135 [warning] <0.500.1> closing AMQP connection <0.500.1> (127.0.0.1:42748 -> 127.0.0.1:5672):
missed heartbeats from client, timeout: 5s

Versuchen Sie, einen Befehl zu senden, nachdem die Verbindung von RabbitMQ geschlossen wurde:

$ celery inspect ping

Das Sellerie-Arbeiterprotokoll druckt dies, wenn es den folgenden Befehl erhält:

[2018-06-27 19:51:25,638: DEBUG/MainProcess] pidbox received method ping() [reply_to:{'exchange': 'reply.celery.pidbox', 'routing_key': '5a7fe1f1-be67-397f-879c-d939ea3c076e'} ticket:d80183f3-a236-4057-841b-6b8cd2926917]
[2018-06-27 19:51:25,639: ERROR/MainProcess] Control command error: ConnectionResetError(104, 'Connection reset by peer')
Traceback (most recent call last):
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/celery/worker/pidbox.py", line 46, in on_message
    self.node.handle_message(body, message)
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/pidbox.py", line 129, in handle_message
    return self.dispatch(**body)
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/pidbox.py", line 112, in dispatch
    ticket=ticket)
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/pidbox.py", line 135, in reply
    serializer=self.mailbox.serializer)
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/pidbox.py", line 265, in _publish_reply
    **opts
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/messaging.py", line 181, in publish
    exchange_name, declare,
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/messaging.py", line 194, in _publish
    [maybe_declare(entity) for entity in declare]
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/messaging.py", line 194, in <listcomp>
    [maybe_declare(entity) for entity in declare]
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/messaging.py", line 102, in maybe_declare
    return maybe_declare(entity, self.channel, retry, **retry_policy)
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/common.py", line 129, in maybe_declare
    return _maybe_declare(entity, declared, ident, channel, orig)
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/common.py", line 135, in _maybe_declare
    entity.declare(channel=channel)
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/kombu/entity.py", line 185, in declare
    nowait=nowait, passive=passive,
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/amqp/channel.py", line 614, in exchange_declare
    wait=None if nowait else spec.Exchange.DeclareOk,
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/amqp/abstract_channel.py", line 50, in send_method
    conn.frame_writer(1, self.channel_id, sig, args, content)
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/amqp/method_framing.py", line 166, in write_frame
    write(view[:offset])
  File "/home/bar/Desktop/foo/virtualenv/lib/python3.6/site-packages/amqp/transport.py", line 275, in write
    self._write(s)
ConnectionResetError: [Errno 104] Connection reset by peer
[2018-06-27 19:51:25,647: DEBUG/MainProcess] Closed channel #2
[2018-06-27 19:51:25,647: DEBUG/MainProcess] using channel_id: 2
[2018-06-27 19:51:25,648: DEBUG/MainProcess] Channel open

Mögliche Fehlerursache

Ich denke, es gibt eine Verbindung, die von der Serverseite beendet wird, weil kombu.connection.Connection.heartbeat_check() auf der Instanz nicht wiederholt aufgerufen wird.

Ich sehe das gleiche Problem mit gevent.

Problemumgehung mit broker_heartbeat = 0 funktioniert bei mir.

Installierte Versionen:

amqp==2.2.2
celery==4.2.0
eventlet==0.23.0
kombu==4.2.1

Arbeiter:
celery -A celery_app worker --loglevel=info -P eventlet

PS Getestet unter Windows 10 mit Python 2 & 3.

@auvipy : Warum schließen? Das Problem ist nicht behoben ...

Hat @ stojan-jovic Workaround funktioniert?

Es scheint ja, aber eine Problemumgehung ist kein Bugfix.
Und es führte immer noch zu einer Menge Zeitverschwendung bei der Suche nach einer Lösung für jeden Tag mehr Menschen.

Wenn Sie eine mögliche Lösung finden, wird diese erneut geöffnet.

Problemumgehung mit broker_heartbeat = 0 scheint für mich für Sellerie 4.2.0 und Gevent 1.2.2 (Python 2) / RabbitMQ 3.7.8 zu funktionieren. Zumindest hat es bei der Standardeinstellung der 60er Jahre für mich nicht aufgelegt.

Django 1.8.4, Python 2.7.12
Das Problem trat nach dem Upgrade von 3.1.25 auf 4.2.1 auf
CELERY_BROKER_HEARTBEAT = 0 in settings.py hat dies behoben.

@auvipy warum hast du das geschlossen? Das Problem besteht weiterhin.

@djlambert Es ist bekannt, dass er Probleme / PRs ohne Grund schließt.

Irgendwelche Updates dazu? Eine Umgehung ist keine Fehlerbehebung.

Fühlen Sie sich frei, das Problem @gvdmarck zu untersuchen,

Django 1.8.4, Python 2.7.12
Das Problem trat nach dem Upgrade von 3.1.25 auf 4.2.1 auf
CELERY_BROKER_HEARTBEAT = 0 in settings.py hat dies behoben.

sollte BROKER_HEARTBEAT anstelle von CELERY_BROKER_HEARTBEAT sein?

amqp == 2.2.2

Ich versuche, Sellerie-Arbeiter mit dieser Konfiguration auszuführen, aber Sellerie-Arbeiter startet nicht.
Der Befehl, den ich verwende, lautet wie folgt
pipenv run Sellerie-Arbeiter -A src.celery_app -l Debug -P Eventlet
Aber ich sehe kein Sellerie-Startprotokoll oder irgendetwas, das direkt zur Windows-Cmd-Eingabeaufforderung zurückkehrt.

@ stojan-jovic, kannst du mich wissen lassen, wie man die Umgebung für Sellerie einrichtet?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen