Konfigurasi Gunicorn Pada Django

Perlu dipahami apabila kita membuat sebuah aplikasi berbasis web, kita harus tau karakteristik dari aplikasi yang kita buat. Apakah aplikasi kita banyak menangani CPU bound atau I/O bound?

Berikut definisi singkat dan contoh dari masing-masing karakteristik tersebut.

  • I/O Bound.
    Aplikasi terfokus untuk melakukan proses input dan output.
    Contohnya seperti aplikasi website pendaftaran, web scrapper dan html to pdf converter.
  • CPU Bound.
    Aplikasi terfokus untuk melakukan proses komputasi.
    Contohnya seperti aplikasi yang melakukan proses machine learning, encoding video dan dashboard perhitungan statistik.

2 karakteristik ini juga memiliki konfigurasi yang berbeda agar dapat berjalan secara optimal. Kali ini saya ingin menuliskan catatan beberapa konfigurasi Gunicorn dan semoga mudah dipahami.

Dalam pembuatan aplikasi web dengan performa yang baik, sangat berkaitan dengan yang namanya concurrency. Ada 3 jenis concurrency yang harus kita pahami dalam konfigurasi Gunicorn.

  1. Workers atau Unix Process.
    Setiap worker akan berjalan di 1 process sendiri dan tidak melakukan sharing memory antar process.Sebagai bayangan jika belum paham, semisal kita menjalankan python manage.py runserver, maka kita telah menjalankan development server pada 1 process.Sehingga jika ada 10 worker itu sama dengan kita menjalankan python manage.py runserver di 10 terminal berbeda. Masing-masing akan berjalan sendiri-sendiri tanpa komunikasi antar process.Jumlah worker yang disarankan adalah (2 * Total CPU) + 1.

    $ gunicorn myproject.wsgi --workers=9 --bind=0.0.0.0:8000
    

    Sehingga jika server kita memiliki 4 CPU, maka total worker yang harus diset adalah 9 worker dari formula (2 * 4) + 1.

  2. Threads.
    Perlu diketahui bahwa pada 1 process bisa terdapat banyak thread. Gunicorn pun juga mensupport hal ini, sehingga 1 worker akan memanggil beberapa thread di dalam process nya dan masing-masing thread akan melakukan sharing memory antar thread didalam 1 process.Jika kita menggunakan thread pada Gunicorn, maka secara default Gunicorn akan memakai gthread sebagai worker class nya.

    $ gunicorn myproject.wsgi --workers=1 --threads=8 --bind=0.0.0.0:8000
    

    Atau secara eksplisit bisa ditulis lengkap menjadi.

    $ gunicorn myproject.wsgi --workers=1 --threads=8 --worker-class=gthread --bind=0.0.0.0:8000
    

    Untuk jumlah thread yang disarankan adalah 2 sampai 4 * Total CPU.

  3. Pseudo-threads.
    Saat ini ada ada banyak pilihan library yang menggunakan pseudo-threads seperti gevent, asyncio dan tornado.Gunicorn dapat dikombinasikan dengan library tersebut cukup dengan menambahkan parameter –worker-class.

    $ gunicorn myproject.wsgi --workers=9 --worker-class=gevent --bind=0.0.0.0:8000
    

Concurrency vs Parallelism

Pembahasan ini mungkin bisa dijelaskan di artikel berbeda, 2 hal ini cukup komplek untuk dijelaskan secara detail karena akan membahas Global Interpreter Lock atau GIL yang menjadi kelemahan python.

Concurrency adalah ketika 2 atau lebih pekerjaan dijalankan secara bersamaan, tetapi hanya ada 1 yang dapat di proses dan pekerjaan lainnya akan di pause untuk menunggu giliran dieksekusi.

Parallelism adalah ketika 2 atau lebih pekerjaan dijalankan secara bersamaan dan dapat diproses secara bersamaan di satu waktu yang sama.

Dari pengertian diatas juga dapat disimpulkan bahwa concurrency tidak berarti parallelism, namun parallelism itu pasti concurrency.

Pemilihan konfigurasi sesuai use case.

  1. Jika aplikasi banyak menangani I/O Bound maka gunakan konfigurasi pseudo-threads, karena proses I/O dapat ditangani secara async.
  2. Jika aplikasi banyak menangani CPU Bound maka gunakan konfigurasi Workers, karena di Python terdapat Global Interpreter Lock / GIL sehingga Threads dan Pseudo-threads tidak bisa berjalan secara parallel maka kita perlu memanggil banyak process agar dapat berjalan pada multicore CPU.
  3. Jika memiliki concern pada penggunaan memory pada aplikasi, konfigurasi Threads disarankan karena Threads lebih ringan dibanding kita memanggil sebuah Process.
  4. Jika belum yakin pada saat awal pembuatan aplikasi, maka gunakan konfigurasi paling sederhana yaitu Workers.

Pembahasan artikel ini adalah konsep dasar yang bisa dipahami sebelum kita melakukan konfigurasi Gunicorn pada project kita dan bisa menjadi acuan dasar.
Ada kalanya konfigurasi diatas perlu di-tuning lagi apabila masalah yang dihadapi lebih kompleks dari yang saya ilustrasikan.

NB:
Pembahasan pada artikel ini juga dapat diaplikasikan pada web framework python lainnya seperti Flask, cukup disesuaikan command line sesuai framework yang digunakan.

Referensi.
https://docs.gunicorn.org/en/stable/settings.html
https://docs.gunicorn.org/en/stable/design.html#how-many-threads
https://medium.com/building-the-system/gunicorn-3-means-of-concurrency-efbb547674b7
https://stackoverflow.com/a/41696500/1936697
https://medium.com/@genchilu/brief-introduction-about-the-types-of-worker-in-gunicorn-and-respective-suitable-scenario-67b0c0e7bd62

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.