Cyber Monday Sale 40% off unlimited courses & creative assets! 40% off unlimited assets! Save Now
Advertisement
  1. Code
  2. Django

Menggunakan Celery dengan Django untuk Pemrosesan Tugas Latarbelakang

by
Read Time:15 minsLanguages:

Indonesian (Bahasa Indonesia) translation by Husain Ali Yahya (you can also view the original English article)

Aplikasi web biasanya bermula sederhana namun menjadi cukup rumit dan kebanyakan dari mereka melampaui tanggung jawabnya yang berupa memberi respon ke permintaan HTTP.

Saat itu terjadi, salah satu-nya harus membuat perbedaan di antara apa yang telah terjadi secara instan (biasanya di dalam siklus hidup permintaan HTTP) dan apan yang bisa terjadi pada akhirnya. Kenapa begitu? Karena saat aplikasimu dipenuhi dengan traffic, hal sederhana seperti ini akan membuat perbedaan.

Operasi di aplikasi web bisa diklasifikan menjadi operasi kritis atau request-time operations dan tugas-tugas latarbelakang, yang terjadi diluar waktu permintaan. Ini memetakan ke salah satu yang dideskripsikan di atas:

  • Harus terjadi secara instan: request-time operations
  • harus terjadi pada terjadi pada akhirnya: tugas-tugas latarbelakang

Request-time operations bisa diselesaikan dalam satu permintaan atau siklus respon tanpa perlu khawatir operasinya akan time out atau penggunanya akan mengalami pengalaman buruk. Contoh umumnya termasuk operasi database CRUD (Create, Read, Update, Delete) dan manajemen pengguna (aktivitas Login/Logout).

Tugas latarbelakang berbeda karena mereka biasanya cukup memakan waktu dan rentan gagal terutama karena external dependencies. Beberapa skenario umum di antara aplikasi web rumit termasuk:

  • Mengirim surel aktivitas atau konfirmasi
  • Mengeruk beberapa informasi dari aneka sumber tiap hari-nya dan menyimpan mereka
  • Melakukan analisis data
  • Menghapus sumber-sumber yang tidak dibutuhkan
  • Mengekspor foto/dokumen dalam aneka format

Tugas latarbelakang adalah fokus utama dari panduan ini. Pola pemograman yang paling umum digunakan untuk skenario ini ada Producer Consumer Architecture.

Secara sederhana, arsitektur ini bisa dideskripsikan seperti ini:

  • Produser membuat dat atau tugas.
  • Tugas-tugas dimasukkan ke dalam sebuah antrian yang diacuk sebagai antrian tugas.
  • Pelanggan bertanggung jawab untuk mengonsumsi data-nya atau menjalankan tugas-nya.

Biasanya, pelanggan menerima tugas-tugas dari antrian dengan aturan first-in-first-out (FIFO) atau berdasarkan prioritas. Pelanggan juga diacu sebagai pekerja dan itu adalah istilah yang akan kita gunakan karena dia konsisten dengan istilah yang digunakan oleh teknologi yang dibahas.

Tugas macam apa yang bisa diproses di latarbelakang? Tugas-tugas yang:

  • Tidak penting untuk fungsionalitas dasar aplikasi web
  • Tidak bisa dijalankan dalam siklus permintaan/respon karena mereka lambat (I/O intensif dan lain-lain)
  • Bergantung pada sumber-sumber eksternal yang tidak tersedia atau berperilaku tidak sesuai harapan.
  • Perlu dicoba kembali setidaknya sekali
  • Harus dieksekusi sesuai jadwal

Celery adalah pilihan pasti untuk melakukan tugas-tugas latar belakang dalam ekosistem Python/Django. Dia memiliki API yang sederhana dan bersih, dan terintegrasi dengan cantik bersama Django. Dia mendukung aneka teknologi untuk antrian tugas dan aneka paradigma untuk pekerja.

Pada panduan ini, kita akan membuat sebuah aplikasi web mainan django (yang menangani skenario nyata) yang menggunakan pemrosesan tugas di latarbelakang.

Persiapan

Dengan asumsi kamu telah familiar dengan manajemen Python package dan virtual environments, mari pasang Django:

Saya telah memutuskan untuk membuat aplikasi blogging lainnya. Fokus dari aplikasinya akan pada kesederhanaan. Seorang pengguna bisa membuat akun dan mengirim lalu mempublikasikan tulisan tanpa banyak kehebohan.

Persiapkan proyek Django quick_publisher:

Mari mulai aplikasinya:

Ketika membuat sebuah proyek Django baru, saya suka membuat main application yang mengandung, disamping hal-hal yang lainnya, sebuah costum user model. Biasanya, saya mengalami pembatasan dari User model bawaan Django. Memiliki model User kostum memberi kita keuntungan akan fleksibilitas.

Pastikan untuk mengecek dokumentasi Django jika kamu tidak familiar dengan cara kerja custom user models.

Sekarang kita harus memberitahu Django untuk menggunakan User model ini ketimbang yang bawaan. Tambahkan baris ini ke berkas quick_publisher/settings.py:

Kita perlu menambahkan main application ke daftar INSTALLED_APPS ke berkas quick_publisher/settings.py. Kita sekarang bisa membuat migrasi-nya, menerapkan mereka, dan membuat sebuah superuser untuk masuk ke panel admin Django:

sekarang mari buat sebuah aplikasi Django terpisah yang bertanggung jawab untuk kiriman-kiriman:

Mari definisikan sebuah model Post sederhana di publisher/models.py :

Menghubungkan model Post dengan admin Django dilakukan di berkas publisher/admin.py seperti ini:

Terakhir, mari kaitkan aplikasi publisher dengan proyek kita dengan menambahkannya ke daftar INSTALLED_APPS.

Sekarang kita bisa menjalankan server-nya dan pergi ke http://localhost:8000/admin/ dan membuat kiriman pertama kita sehingga kita memiliki sesuatu untuk dimainkan.

Saya percaya kamu telah mengerjakan pekerjaan rumah-mu dan telah membuat kirimannya.

Langkah selanjutnya adalah membuat sebuah cara untuk melihat kiriman terpublikasinya.

Mari asosiasikan view baru kita dengan sebuah URL di: quick_publisher/urls.py

Terakhir, mari buat template yang merender kirimannya di: publisher/templates/post.html

Sekarang kita bisa ke http://localhost:8000/the-slug-of-the-post-you-created/ di browser. Ini bukanla sebuah keajaiban dari web design, tapi membuat kiriman yang tampak bagus berada di luar jangkauan panduan ini.

Mengirim Surel Konfirmasi

Ini skenario klasik-nya:

  • Kamu membuat sebuah akun pada sebuah platform
  • Kamu menyediakan sebuah alamat surel untuk mengidentifikasi secara unik di platform-nya.
  • Platform-nya mengecek bahwa kamu benar-benar pemilik alamat surel dengan mengirim sebuah email dengan pesan konfirmasi.
  • Hingga kamu melakukan verifikasi-nya, kamu tidak bisa (sepenuhnya) menggunakan platform-nya.

Mari tambahkan sebuah flag is_verified dan verification_uuid pada User model:

Mari gunakan kesempatan ini untuk menambahkan User model ke admin-nya:

Mari buat perubahannya nampak di database-nya:

Sekarang kita harus menulis sebuah kode yang mengirim surel ketika sebuah user instance dibuat. Di sinilah signals Django digunakan, dan ini adalah saaat yang tepat untuk menyentuh pembahasan ini.

Signal dipanggil sebelum atau sesudah kejadian suatu event di aplikasi. Kita bisa mendefinisikan fungsi callback yang dipicu secara otomatis ketika signal-nya dipanggil. Untuk membuat pemicu callback, pertama kita harus menghubungkannya ke sebuah signal.

Kita akan membuat sebuah callback yang akan dipicu setelah sebuah User model dibuat. Kita akan menambahkan kode ini setelah definisi User model di: main/models.py

Aoa yang telah kita lakukan di sini adalah mendefinsikan fungsi user_post_save dan menghubungkannya ke signal post_save (satu yang dipicu setelah sebuah model telah disimpan) dikirim oleh User model-nya.

Django tidak mengirim pesan dengan sendirinya; dia harus dihubungkan dengan sebuah layanan email. Demi kesederhanaan, kamu bisa memasukkan kredensial Gmail-mu ke quick_publisher/setting.py atau kamu bisa menambahkan penyedia email favoritmu.

Beginilah tampilan konfigurasi Gmail:

Untuk mengetes, pergi ke panel admin dan buat sebuah pengguna baru dengan alamat surel yang valid dan bisa kamu cek dengan cepat. Jika semua lancar, kamu akan menerima sebuah surel dengan tautan verifikasi. Aktivitas verifikasinya masih belum selesai.

Ini adalah cara memverifikasi akun-nya:

Hubungkan view-nya di: quick_publisher/urls.py

Dan juga, ingatlah untuk membuat sebuah berkas home.html di bawah main/templates/home.html. Dia akan dirender oleh view home.

Coba untuk menjalankan keseluruhan skenario sekali lagi. Jika semua lancar, kamu akan menerima sebuah surel dengan URL verifikasi yang valid. Jika kamu mengikuti URL dan mengecek-nya di admin, kamu bisa melihat cara akunnya diverifikasi.

Mengirim Surel Secara Asinkron

Ini adalah masalah yang kita miliki dengan apa yang telah kita lakukan sejauh ini. Kamu mungkin menyadari bahwa pembuatan pengguna-nya sedikit lambat. Ini karena Django mengirim surel verifikasi di dalam request time.

Ini cara kerjanya: kita mengirim data pengguna ke aplikasi Django. Aplikasi-nya membuat sebuah User model dan membuat sebuah hubungan ke Gmail (atau layanan lain yang kamu pilih). Django menunggu responnya dan hanya setelahnya dia mengembalikan sebuah respon ke browser kita.

Di sinilah Celery bekerja. Pertama, pastikan dia terpasang:

Sekarang kita harus memasang aplikasi Celery di dalam aplikasi Django kita:

Celery adalah sebuah antrian tugas. Dia menerima tugas-tugas dari aplikasi Django kita dan dia akan menjalankannya di latarbelakang. Celery harus dihubungkan dengan layanan lainnya yang berfungsi sebagai broker.

Broker menengahi pengiriman pesan di antara aplikasi web dan Celery. Pada panduan ini, kita akan menggunakan Redis. Redis mudah dipasang dan kita bisa memulainya dengan mudah tanpa banyak kerumitan.

Kamu bisa memasang Redis dengan mengikuti petunjuk di halaman Redis Quick Start. Kamu harus memasang-nya ke pustaka Redis Python. pip install redis, dan bundel yang dibutuhkan untuk menggunakan Redis dan Celery: pip install celery[redis].

Mulai server redis-nya pada konsol terpisah: $ redis-server

Mari tambahkan Celery/Redis terkait ke quick_publisher/settings.py:

Sebelum segalanya berjalan di Celery. Dia harus dideklarasikan sebagai sebuah tugas.

Ini cara melakukannya:

Apa yang telah kita lakukan di sini adalah: kita memindahkan pengiriman verifikasi-nya fungsionalitas di berkas lain bernama tasks.py.

Beberapa catatan:

  • Nama berkas-nya penting. Celery akan pergi ke semua aplikasi di INSTALLED_APPS dan daftarkan tugas-tugasnya di berkas tasks.py.
  • Perhatikan cara kita mendekorasi fungsi send_verification_email fungsi dengan @app.task. Ini memberi tahu Celery ini adalah sebuah tugas yang akan berjalan di antrian tugas.
  • Perhatikan cara kita mengharapkan argumen user_id ketimbang sebuah objek User. Ini karena kita mungkin mendapatkan masalah menserialisasi objek rumit ketika pengirim tugasnya ke Celery. Membuatnya sederhana adalah yang paling baik.

Kembali ke main/models.py. Kode signal-nya menjadi:

Perhatikan cara kita memanggil metode .delay pada objek tugas. Ini berarti kita mengirim tugasnya ke Celery dan kita tindak menunggu hasilnya. Jika kita menggunakan send_verification_email(instance.pk), kita masih bisa mengirimnya ke Celery, tapi akan ditunggu hingga tugasnya selesai dan itu tidak kita inginkan.

Sebelum kamu mulai membuat pengguna baru, ada yang perlu ditangkap. Celery adalah sebuah layanan, dan kita harus memulainya. Buka sebuah konsol baru, pastikan kamu mengaktifkan virtualenv yang tepat, dan bernavigasilah ke folder proyek.

Ini akan menjalankan empat pekerja Celery. Sekang akhirnya kamu bisa membuat pengguna yang lainnya. Perhatikan bahwa tidak ada delay, dan pastikan untuk mengawasi logs di konsol Celery untuk memastikan tugas-tugasnya dieksekusi dengan benar. Ini harusnya nampak seperti ini:

Tugas Periodik dengan Celery

Ini adalah skenario umum lainnya. Kebanyakan aplikasi web tua mengirim surel-surel siklus hidup penggunanya untuk membuat mereka tetap tertarik. Beberapa contoh umum dari email periodik:

  • Laporan bulanan
  • Notifikasi aktivitas (likes, permintaan pertemanan dan lainnya).
  • Pengingat untuk menyelesaikan aksi tertentu ("Jangan lupa untuk mengaktifkan akunmu!")

Ini adalah apa yang akan kita lakukan di dalam aplikasi kita. Kita akan menghitung berapa banyak kiriman telah dilihat dan mengirim laporan harian ke penulisnya. Setiap hari, kita akan mengurus semua pengguna, mengambil kiriman mereka, dan mengirim sebuah surel dengan tabel berisi kiriman dan jumlah pengunjung.

Mari ubah model Post sehingga kita bisa mengakomodasi skenario jumlah pengunjung-nya.

Seperti biasa, ketika kita mengganti sebuah model, kita harus migrasikan database-nya.

Mari modifikasi view_post dari Django view untk menghitung pengunjung.

Akan berguna untuk menampilkan view_count-nya dalam template-nya. Tambahkan <p>Viewed {{ post.view_count }} times </p> di dalam publisher/templates/post.html. Buat kunjungan beberapa kali dan lihat penghitungnya bertambah.

Mari buat sebuah tugas Celery. Karena ini mengenai kiriman, saya akan meletakkannya di dalam publisher/tasks.py:

Setiap kali kamu melakukan perubahan ke tugas Celery, ingat untuk mengulan proses Celery-na. Celery harus mengeksploarasi dan memuat tugas-tugas kembali. Sebelum membuat tugas periodik, kita harus mengetes di Django shell untuk memastikan semuanya sesuai yang diharapkan:

Semoga, kamu menerima laporan yang bagus di surelmu.

Sekarang mari buat sebuah tugas periodik. buka quick_publisher/celery.py dan daftarkan tugas periodik-nya:

Sejauh ini, kita telah membuat sebuah jadwal yang akan menjalankan tugas publisher.tasks.send_view_count_report tiap menit seperti yang diindikasikan notasi crontab(). Kamu juga bisa menspesifikasikan aneka Jadwal Celery Crontab.

Buak konsol lainnya, aktifkan environment yang tepat, dan mulai layanan Celery Beat-nya.

Tugas layanan Beat adalah untuk mendorong tugas-tugas di Celery sesuai jadwalnya. Perhatikan bahwa jadwal-nya membuat tugas send_view_count_report berjalan tiap menit berdasarkan pengaturannya. Ini bagus untuk mengetes tapi tidak direkomendasikan utnuk aplikasi web sungguhan.

Membuat Tugas yang Lebih Dapat Diandalkan

Tugas-tugas biasanya digunakan untuk menjalankan operasi yang tidak dapat diandalkan, operasi yang bergantung pada sumber eksternal atau dapat gagal dengan mudah karena aneka alasan. Ini adlah panduan untuk membuatnya lebih dapat diandalkan:

  • Buat tugas-tugas idempotent. Sebuah tugas idempotent adalah tugas yang jika berhenti di tengah-tengah tidak akan merubah keadaan dari sistem-nya. Tugasnya hanya akan membuat perubahan penuh ke sistemnya atau tidak sama sekali.
  • Mencoba tugasnya kembali. Jika tugasnya gagal, tidak ada salahnya untuk mencoba lagi dan lagi hingga dia dieksekusi dengan benar. Kamu bisa melakukannya di Celery dengan Celery Retry. Satu hal menarik lainnya untuk dilihat adalah pada algoritma Exponential Backoff. Ini bisa berguna ketika berpikir mengenai membatasi muatan tak diperlukan di server dari tugas-tugas yang dicoba kembali.

Kesimpulan

Saya harap ini menjadi panduan yang berguna bagimu dan pengantar yang bagus ke penggunaan Celery dengan Django.

Ini adalah beberapa kesimpulan yang bisa kita tarik:

  • Adalah hal yang bagus untuk menjaga tugas-tugas yang tidak dapat diandalkan dan menghabiskan waktu di luar request time.
  • Tugas yang berjalan panjang harus dieksekusi di latarbelakang oleh worker processes (atau paradigma lainnya).
  • Tugas-tugas latarbelakang bisa digunakan untuk aneka tugas yang tidak kritis untuk fungsi dasar dari aplikasi.
  • Celery juga bisa menangani tugas periodik menggunakan layanan celery beat.
  • Tugas-tugas bisa lebih diandalkan jika dibuat idempotent dan dicoba kemnali (mungkin menggunakan exponential backoff).
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.