celery -A proj report
dalam terbitan.master
.# tasks.py
from celery import Celery
app = Celery('tasks', broker='pyamqp://guest@localhost//')
@app.task
def add(x, y):
return x + y
@app.task
def mul(x, y):
return x * y
Saya menguji kasus saat rabbitmq turun. Jadi saya tidak memulai rabbitmq sama sekali. Kemudian, saya menjalankan perintah berikut di ipython:
from tasks import add
add.delay()
add.delay()
selalu diblokir. Saya mencoba menyetel retry
ke False, tetapi tidak berhasil.
add.apply_async((2, 2), retry=False)
Saya juga mencoba memberikan retry_policy dan itu juga tidak berhasil.
add.apply_async((2, 2), retry=True, retry_policy={
'max_retries': 3,
'interval_start': 0,
'interval_step': 0.2,
'interval_max': 0.2,
})
Saya berharap untuk melihat pengecualian saat saya menyetel coba lagi ke False. Ketika saya menyetel coba lagi ke True, itu harus menjalankan jumlah default max_retries dan jika tidak berfungsi, itu harus mengeluarkan pengecualian.
Fungsi tersebut berjalan selamanya dan memblokir proses tersebut.
Saya menekan ctrl+c
untuk mendapatkan informasi kesalahan berikut:
In [1]: from tasks import add, mul
In [2]: add.delay(2,3)
^C---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
~/github/celery-demo/.venv/src/kombu/kombu/utils/functional.py in __call__(self)
35 try:
---> 36 return self.__value__
37 except AttributeError:
AttributeError: 'ChannelPromise' object has no attribute '__value__'
During handling of the above exception, another exception occurred:
ConnectionRefusedError Traceback (most recent call last)
~/github/celery-demo/.venv/src/kombu/kombu/utils/functional.py in retry_over_time(fun, catch, args, kwargs, errback, max_retries, interval_start, interval_step, interval_max, callback)
337 try:
--> 338 return fun(*args, **kwargs)
339 except catch as exc:
~/github/celery-demo/.venv/src/kombu/kombu/connection.py in connect(self)
260 self._closed = False
--> 261 return self.connection
262
~/github/celery-demo/.venv/src/kombu/kombu/connection.py in connection(self)
801 self._default_channel = None
--> 802 self._connection = self._establish_connection()
803 self._closed = False
~/github/celery-demo/.venv/src/kombu/kombu/connection.py in _establish_connection(self)
756 self._debug('establishing connection...')
--> 757 conn = self.transport.establish_connection()
758 self._debug('connection established: %r', self)
~/github/celery-demo/.venv/src/kombu/kombu/transport/pyamqp.py in establish_connection(self)
129 conn.client = self.client
--> 130 conn.connect()
131 return conn
~/github/celery-demo/.venv/lib/python3.6/site-packages/amqp/connection.py in connect(self, callback)
281 )
--> 282 self.transport.connect()
283 self.on_inbound_frame = self.frame_handler_cls(
~/github/celery-demo/.venv/lib/python3.6/site-packages/amqp/transport.py in connect(self)
108 def connect(self):
--> 109 self._connect(self.host, self.port, self.connect_timeout)
110 self._init_socket(
~/github/celery-demo/.venv/lib/python3.6/site-packages/amqp/transport.py in _connect(self, host, port, timeout)
149 self.sock.settimeout(timeout)
--> 150 self.sock.connect(sa)
151 except socket.error:
ConnectionRefusedError: [Errno 61] Connection refused
During handling of the above exception, another exception occurred:
KeyboardInterrupt Traceback (most recent call last)
<ipython-input-2-e2f2f196d9be> in <module>()
----> 1 add.delay(2,3)
~/github/celery-demo/.venv/src/celery/celery/app/task.py in delay(self, *args, **kwargs)
414 celery.result.AsyncResult: Future promise.
415 """
--> 416 return self.apply_async(args, kwargs)
417
418 def apply_async(self, args=None, kwargs=None, task_id=None, producer=None,
~/github/celery-demo/.venv/src/celery/celery/app/task.py in apply_async(self, args, kwargs, task_id, producer, link, link_error, shadow, **options)
537 link=link, link_error=link_error, result_cls=self.AsyncResult,
538 shadow=shadow, task_type=self,
--> 539 **options
540 )
541
~/github/celery-demo/.venv/src/celery/celery/app/base.py in send_task(self, name, args, kwargs, countdown, eta, task_id, producer, connection, router, result_cls, expires, publisher, link, link_error, add_to_parent, group_id, retries, chord, reply_to, time_limit, soft_time_limit, root_id, parent_id, route_name, shadow, chain, task_type, **options)
747 with P.connection._reraise_as_library_errors():
748 self.backend.on_task_call(P, task_id)
--> 749 amqp.send_task_message(P, name, message, **options)
750 result = (result_cls or self.AsyncResult)(task_id)
751 if add_to_parent:
~/github/celery-demo/.venv/src/celery/celery/app/amqp.py in send_task_message(producer, name, message, exchange, routing_key, queue, event_dispatcher, retry, retry_policy, serializer, delivery_mode, compression, declare, headers, exchange_type, **kwargs)
552 delivery_mode=delivery_mode, declare=declare,
553 headers=headers2,
--> 554 **properties
555 )
556 if after_receivers:
~/github/celery-demo/.venv/src/kombu/kombu/messaging.py in publish(self, body, routing_key, delivery_mode, mandatory, immediate, priority, content_type, content_encoding, serializer, headers, compression, exchange, retry, retry_policy, declare, expiration, **properties)
179 body, priority, content_type, content_encoding,
180 headers, properties, routing_key, mandatory, immediate,
--> 181 exchange_name, declare,
182 )
183
~/github/celery-demo/.venv/src/kombu/kombu/connection.py in _ensured(*args, **kwargs)
492 for retries in count(0): # for infinity
493 try:
--> 494 return fun(*args, **kwargs)
495 except conn_errors as exc:
496 if got_connection and not has_modern_errors:
~/github/celery-demo/.venv/src/kombu/kombu/messaging.py in _publish(self, body, priority, content_type, content_encoding, headers, properties, routing_key, mandatory, immediate, exchange, declare)
185 headers, properties, routing_key, mandatory,
186 immediate, exchange, declare):
--> 187 channel = self.channel
188 message = channel.prepare_message(
189 body, priority, content_type,
~/github/celery-demo/.venv/src/kombu/kombu/messaging.py in _get_channel(self)
207 channel = self._channel
208 if isinstance(channel, ChannelPromise):
--> 209 channel = self._channel = channel()
210 self.exchange.revive(channel)
211 if self.on_return:
~/github/celery-demo/.venv/src/kombu/kombu/utils/functional.py in __call__(self)
36 return self.__value__
37 except AttributeError:
---> 38 value = self.__value__ = self.__contract__()
39 return value
40
~/github/celery-demo/.venv/src/kombu/kombu/messaging.py in <lambda>()
222 connection = channel
223 self.__connection__ = connection
--> 224 channel = ChannelPromise(lambda: connection.default_channel)
225 if isinstance(channel, ChannelPromise):
226 self._channel = channel
~/github/celery-demo/.venv/src/kombu/kombu/connection.py in default_channel(self)
829
830 # make sure we're still connected, and if not refresh.
--> 831 self.ensure_connection(**conn_opts)
832 if self._default_channel is None:
833 self._default_channel = self.channel()
~/github/celery-demo/.venv/src/kombu/kombu/connection.py in ensure_connection(self, errback, max_retries, interval_start, interval_step, interval_max, callback, reraise_as_library_errors)
403 (), {}, on_error, max_retries,
404 interval_start, interval_step, interval_max,
--> 405 callback)
406 return self
407
~/github/celery-demo/.venv/src/kombu/kombu/utils/functional.py in retry_over_time(fun, catch, args, kwargs, errback, max_retries, interval_start, interval_step, interval_max, callback)
348 if callback:
349 callback()
--> 350 sleep(1.0)
351 # sleep remainder after int truncation above.
352 sleep(abs(int(tts) - tts))
KeyboardInterrupt:
Saya menemukan masalah utama terjadi pada kombu/kombu/messaging.py::_publish
, yang akhirnya mencapai kombu/kombu/connection.py::default_channel
. default_channel
memanggil kombu/kombu/connection.py::ensure_connection
sesuai dengan max_retries
, interval_start
, interval_step
, interval_max
dalam transport_options
.
Ketika transport_options
adalah {} dan broker jatuh, self.ensure_connection(**conn_opts)
dalam default_channel
berjalan selamanya.
Tampaknya ada dua pembungkus yang mencoba lagi di kombu/messaging.py::Producer.publish
. Satu didasarkan pada retry
dan retry_policy
disediakan oleh seledri amqp dan yang lainnya didasarkan pada transport_options
.
Solusi saya saat ini adalah menambahkan konfigurasi percobaan ulang ke transport_options
juga.
app.conf.broker_transport_options = {
'max_retries': 3,
'interval_start': 0,
'interval_step': 0.2,
'interval_max': 0.2,
}
Hai,
Saya mengalami masalah yang kedengarannya mirip dengan masalah Anda:
https://github.com/celery/kombu/issues/795
Bagi saya sebagai solusinya, menggunakan Kombu 4.0.2 telah berhasil.
@HengfengLi versi apa yang Anda gunakan?
@markddavidoff Ini celery (4.1.0)
.
Saya mengalami masalah ini juga ketika mencoba memperbarui Jobtastic untuk mendukung seledri 4. Saya perlu mematok versi Kombu agar tes tidak hang selamanya.
Jadi, dalam versi kombu / seledri yang lebih rendah, waktu tunggu tidak semuanya diteruskan ke redis-py dengan benar, jadi dalam kasus saya, saya akhirnya membuat versi bercabang dari redis-py dan mengganti batas waktu secara manual
https://github.com/celery/kombu/pull/769 ini seharusnya memperbaiki masalah
Saya tidak memiliki masalah terselesaikan. Saya menggunakan seledri 4.1 dan kombu 4.1. Haruskah saya menggunakan versi kombu yang lebih baru?
Ketika ada masalah dengan pekerja, program yang mengatur tugas di beberapa titik mengirimkan tugas. Kode itu adalah app.send_task('module.name', [])
dan frezzes di sana. Ini harus memberikan kesalahan koneksi atau sesuatu. Tidak diblokir di sana sepanjang hari. Mungkin saya melewatkan konfigurasi? Saya menggunakan rabbitMQ dan database backend, karena rpc memberi saya banyak masalah.
tunggu rilis 4.2
Mengapa? Apakah ini bug dari rilis 4.1.0? Sementara itu, apakah saya harus menurunkan versi ke 4.0.x? Terima kasih
sementara itu coba instal dari github master
Kami juga melihat masalah serupa menggunakan seledri & kombu dari cabang induknya. Saat broker redis turun, apply_async()
akan diblokir hingga redis tersedia lagi. Saya telah bereksperimen dengan broker_transport_options yang berbeda, tetapi tidak berhasil.
cara mengatur penundaan 5 menit dalam kode di bawah ini
dari flask import Flask, Blueprint, abort, jsonify, request, session
pengaturan impor
dari seledri import Seledri
app = Flask (__ name__)
app.config.from_object (pengaturan)
def make_celery (app):
seledri = Seledri (app.import_name, broker = app.config ['CELERY_BROKER_URL'])
celery.conf.update (app.config)
TaskBase = celery.Task
kelas ContextTask (TaskBase):
abstrak = Benar
def __call __ (self, args, * kwargs):
dengan app.app_context ():
return TaskBase .__ call __ (self, args, * kwargs)
celery.Task = ContextTask
kembalikan seledri
seledri = make_celery (aplikasi)
@ celery.task (nama = "tugas.add")
def tambahkan (x, y):
return x + y
@ app.route ("/ test")
def hello_world (x = 16, y = 16):
x = int (request.args.get ("x", x))
y = int (request.args.get ("y", y))
res = add.apply_async ((x, y))
konteks = {"id": res.task_id, "x": x, "y": y}
hasil = "tambah ((x) {}, (y) {})". format (konteks ['x'], konteks ['y'])
goto = "{}". format (konteks ['id'])
return jsonify (result = result, goto = goto)
@ app.route ("/ tes / hasil /
def show_result (task_id):
retval = add.AsyncResult (task_id) .get (waktu tunggu = 5.0)
kembali repr (retval + "mmk")
jika __name__ == "__main__":
port = int (environment.get ("PORT", 5000))
app.run (host = '0.0.0.0', port = port, debug = True)
Bahkan dengan seledri 4.1.1 saya masih mengalami hang saat broker (RabbitMQ) turun.
apa yang Anda hadapi di 4.2rc4? ini bukan di cabang 4.1.x.
Ini terdengar sangat mirip # 4627, yang masih menjadi masalah bahkan pada master.
terima kasih @clok
Jadi 4,2rc4 tidak akan berhasil? Atau bagaimana cara mendapatkan versi itu?
silakan coba versi itu dan laporkan
Saya melihat apa yang tampak seperti masalah yang sama. Saya menggunakan seledri 4.1.1 dan kombu 4.2.1.
Nanti: Sebenarnya dalam kasus saya, server - redis - harus aktif dan merespons. ketukan seledri tampaknya memicu kejadian dengan baik, tetapi metode penundaan panggilan hang selamanya. Akan terus menyelidiki mulai minggu depan kalau-kalau saya telah melakukan kesalahan lain.
ini harus diperbaiki di 4.2rc4, mau mencobanya? kami ingin tahu statusnya saat ini
Asif Saifuddin Auvi [email protected] menulis:
ini harus diperbaiki di 4.2rc4, mau mencobanya?
Akan melakukannya pada hari Selasa (Senin adalah hari libur umum di sini dan sudah
Brian May [email protected]
https://linuxpenguins.xyz/brian/
Ok terima kasih
Lupakan, ternyata masalah saya berbeda. Saya tidak menginisialisasi Celery dengan benar dari Django, jadi secara diam-diam menggunakan amqp daripada redis, di mana ia diam-diam mencoba untuk menghubungkan ke soket AMQP yang sebenarnya tidak mendengarkan.
tolong buka masalah baru setelah mencoba seledri 4.2
Saya telah mencoba dengan:
celery==4.2.0
kombu==4.2.1
dan juga perlu menentukan broker_transport_options
agar apply_async
tidak diblokir selamanya saat Redis mati.
Masih mengalami masalah ini:
Proses utama ditutup dan tidak ada pengecualian yang dimunculkan.
Memperbarui:
diselesaikan dengan:
app.conf.broker_transport_options = {
'max_retries': 3,
'interval_start': 0,
'interval_step': 0,2,
'interval_max': 0,2,
}
Masih menjadi masalah jika broker berfungsi, lalu mati dan kami mengirimkan beberapa tugas tepat setelah saat ini:
seledri: 4.2.1
kombu: 4.2.1
broker: rabbitmq
Langkah-langkah untuk mereproduksi:
Saya mencoba melakukan penggalian. Kesimpulan saya:
- Seledri meminta properti Connection default_channel
.
- default_channel tahu tentang broker_transport_options dan panggilan -> ensure_connection()
-> retry_over_time()
dengan broker_transport_options.
Fungsi ini mencoba melakukan return fun(*args, **kwargs)
dimana kesenangan bound method Connection.connect.
Dan fungsi ini berhasil mengembalikan objek Connection /.
jadi default_channel mengembalikan self._default_channel
dan seledri mencoba sesuatu dengannya.
Tetapi setelah serangkaian langkah pemrosesan on_task_call
-> maybe_declare
-> _imaybe_declare
dari kombu.common dipanggil. Itu mengambil objek Connection dari Queue dan memanggil metode sure () nya. Tetapi tidak tahu tentang broker_transport_options jadi metode ensure
dipanggil tanpa broker_transport_options
dan menggunakan nilai default - max_retries=None
yang berarti percobaan ulang tak terbatas :(
Saya telah menambahkan pemrosesan broker_transport_options di kombu.connection.Connection ensure() method
sehingga menggunakan broker_transport_options setiap kali memeriksa koneksi ke broker tetapi saya tidak tahu apakah ini perbaikan yang tepat untuk masalah ini atau tidak.
seledri: 4.2.1
kombu: 4.2.1
Contoh minimal mereproduksi masalah:
from celery import Celery
celery_app = Celery('lol', broker='LOL_NOT_VALID')
celery_app.send_task('test')
Saya mendapat masalah serupa. Masalahnya adalah saya lupa menambahkan ini.
Kemudian Anda perlu mengimpor aplikasi ini ke modul proj / proj / __ init__.py Anda. Ini memastikan bahwa aplikasi dimuat ketika Django mulai sehingga dekorator @shared_task (disebutkan nanti) akan menggunakannya:
proj / proj / __ init__.py:
from __future__ import absolute_import, unicode_literals
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ('celery_app',)
Adakah yang bisa datang dengan solusi yang sesuai?
Saya pikir kami mengatasi ini dengan menyediakan opsi transportasi yang hanya mencoba ulang beberapa kali (secara default Celery mencoba selamanya):
# Try 5 times. Initially try again immediately, then add 0.5 seconds for each
# subsequent try (with a maximum of 3 seconds). This comes out to roughly 3
# seconds of total delay (0, 0.5, 1, 1.5).
CELERY_BROKER_TRANSPORT_OPTIONS = {
'max_retries': 4,
'interval_start': 0,
'interval_step': 0.5,
'interval_max': 3,
}
Saya dapat mencoba mencari informasi lebih lanjut jika tidak jelas.
BROKER_TRANSPORT_OPTIONS memperbaikinya untuk saya, bukan CELERY_BROKER_TRANSPORT_OPTIONS. Menggunakan seledri 4.2.1, kombu 4.2.1 dan django 1.8.
Apakah Anda menggunakan BROKER_TRANSPORT_OPTIONS
vs. CELERY_BROKER_TRANSPORT_OPTIONS
vs. broker_transport_options
dll. Tergantung pada bagaimana Anda mengkonfigurasi aplikasi Celery Anda. Senang itu berhasil untuk Anda! 👍
Ini sangat bodoh, tetapi bagi saya yang menggunakan Flask, saya telah melakukan ini:
app.py
...
app = Flask(__name__)
app.config.from_object(config[config_name])
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
...
task.py:
import celery
@celery.task(bind=True)
def my_task():
...
Saya perlu melakukan:
app.py
...
app = Flask(__name__)
app.config.from_object(config[config_name])
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
app.celery = celery
...
task.py
from flask import current_app
celery = current_app.celery
@celery.task(bind=True)
def my_task():
...
Ini memecahkan masalah saya tentang gantung tanpa batas, tetapi sejujurnya saya berpikir bahwa mengingat pengaturan saya kacau, akan lebih baik seledri memberi tahu saya itu.
Solusi sebenarnya ada di sini: https://github.com/celery/celery/issues/4627#issuecomment -396907957
Sekadar memberi tahu Anda bahwa saya memiliki perilaku default yang sama dengan:
Pengaturan CELERY_BROKER_TRANSPORT_OPTIONS
berfungsi dengan baik.
Sama di sini saya menggunakan:
Apakah masalahnya muncul kembali?
@ jreed1701 Saya melihat masalah yang sama dengan Anda, dan kami mendapatkan traceback yang sama seperti yang disebutkan di utas ini, tetapi menurut saya bukan karena alasan yang sama. Bagi saya, apply_async
dan delay
menunjukkan perilaku ini untuk fungsi @shared_task
tetapi tidak untuk fungsi @app.task
. Traceback yang sama seperti yang dibahas di utas ini, tetapi tidak ada hubungannya dengan status broker.
Hai @chrisconlan , lucu Anda menunjukkan ini. Saya sampai pada kesimpulan ini kemarin ketika saya memodifikasi perangkat lunak saya untuk menggunakan pola pabrik / ekstensi. Saya menggunakan metode @shared_task yang Anda tunjukkan, tetapi pindah ke metode @ app.task ketika saya mengubah ke pola baru. Perubahan dalam implementasi di pihak saya bergerak, saya membuat instance seledri tanpa konteks aplikasi / tugas, dan menggunakannya untuk menghiasi fungsi tugas saya pada waktu impor. Kemudian pada saat runtime saya mengganti konteks tugas objek / instance seledri yang sama dengan konteks aplikasi yang sesuai, memperbaruinya dengan input konfigurasi, dan kemudian menjalankannya. Perilaku hangup yang tidak terbatas berhenti dan apply_async dijalankan meskipun saya tidak memiliki pialang yang terhubung. Saya bertanya-tanya bagaimana dengan mengubah konteks membebaskan semua ini?
@ jreed1701 Tidak yakin tentang Anda, tapi saya menggunakan celery
sampai django
. Saya tidak menyimpang terlalu jauh dari penggunaan yang terdokumentasi di bagian depan itu karena saya tidak ingin merusak penerapan. Seperti yang Anda katakan, saya tidak yakin ada sesuatu yang pada dasarnya rusak tentang seledri di sini, tapi menurut saya dokumen django-seledri memerlukan pembaruan untuk memastikan semua orang mengikuti praktik terbaik.
@ jreed1701 Anda memberi saya petunjuk bagus tentang konteks seledri. Saya memperbaikinya dengan yang berikut ...
Dari terminal, jalankan python manage.py shell
untuk menginisialisasi shell Django, lalu ...
# Make sure to initialize celery context
from django_project.celery import app
# Now you can import shared tasks
from other_app.tasks import the_shared_task
# Now the shared task won't hang
the_shared_task.delay()
Catatan untuk pengelola saya dan @ jreed1701 sampai di sini karena .delay
atau .apply_async
dicoba pada fungsi yang didekorasi tanpa konteks seledri, tetapi itu berada di luar cakupan masalah ini.
Saya akan membuat masalah tentang ini.
@chrisconlan Saya menggunakan Flask. Belum sempat ke Django.
Lihat Anda berbasis di MD! Saya dekat :)
Senang Anda melakukannya! Setuju, ini adalah perbaikan dokumentasi, tetapi juga periksa log masalah Kombu. Saya bingung membaca apakah itu masalah komunikasi Kombu dengan Redis atau tidak selain apa yang kami alami dengan Celery.
@ jreed701 Pria yang mengagumkan. Kirimi saya email dan tetap berhubungan.
Komentar yang paling membantu
Saya mendapat masalah serupa. Masalahnya adalah saya lupa menambahkan ini.