SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-13

Django vs Flask: Mana Lebih Jimat RAM di VPS Kecil?

Ketahui penggunaan memori sebenar bagi setiap pekerja Gunicorn untuk Django dan Flask pada VPS 1GB hingga 2GB. Kami dedahkan had kapasiti pekerja yang boleh dijalankan.

Kos Django dan Flask pada VPS kecil

Perbandingan antara Django dan Flask pada VPS kecil adalah persoalan mengenai penggunaan memori. Django memuatkan object relational mapper (ORM), mekanisme migrasi, dan tapak admin (jika diaktifkan) ke dalam setiap proses pekerja yang anda mulakan. Flask pula hanya memuatkan penghala (router) dan objek permintaan (request object). Pada pelayan dengan RAM 1 GB, perbezaan ini menentukan jumlah pekerja yang boleh dimuatkan, dan bilangan pekerja menentukan jumlah permintaan yang boleh anda layani pada satu-satu masa.

Kos tersebut hanya dianggap sebagai beban bagi Django jika anda tidak menggunakan fungsi yang disediakannya. Aplikasi yang memerlukan akaun pengguna, sesi, dan panel admin lebih sesuai menggunakan Django: RAM yang digunakan bagi setiap pekerja adalah harga bagi kod yang tidak perlu anda tulis sendiri. API JSON yang diletakkan di hadapan storan data sedia ada lebih sesuai menggunakan Flask, kerana fungsi-fungsi tambahan Django tidak akan digunakan. Ini adalah persoalan kesesuaian. Ukuran di bawah akan membantu anda menentukan pilihan yang tepat untuk aplikasi anda.

Berapakah jumlah memori yang digunakan oleh satu worker gunicorn?

ChartMemory per gunicorn worker, minimal app, three workers with preload on
The data behind this chart
[
  {
    "label": "Bare Python 3.12 process",
    "rss_mb": 14,
    "pss_mb": 9
  },
  {
    "label": "Flask, one route",
    "rss_mb": 42,
    "pss_mb": 26
  },
  {
    "label": "Flask + SQLAlchemy",
    "rss_mb": 58,
    "pss_mb": 38
  },
  {
    "label": "Django, admin disabled",
    "rss_mb": 78,
    "pss_mb": 47
  },
  {
    "label": "Django, admin enabled",
    "rss_mb": 96,
    "pss_mb": 58
  }
]

Angka-angka tersebut merupakan angka lazim yang diterbitkan bagi aplikasi "hello world" untuk setiap bentuk pada Ubuntu 24.04 dengan Python 3.12, tiga worker gunicorn, dan fungsi preload diaktifkan. Anggap angka ini sebagai nilai minimum, kerana import anda sendiri akan menambah beban memori tersebut. Worker Django dengan admin diaktifkan menunjukkan 96 MB resident, manakala bahagian memori berkadaran (proportional share) adalah 58 MB. Jurang antara kedua-dua angka ini merupakan topik utama bahagian seterusnya.

Lakukan pengukuran yang sama pada pelayan anda sendiri.

sudo apt update && sudo apt install -y python3-venv
python3 -m venv /srv/site1/.venv
/srv/site1/.venv/bin/pip install django gunicorn setproctitle

Pasang setproctitle. Dengan adanya alat ini, gunicorn menamakan semula prosesnya kepada gunicorn: master [site1] dan gunicorn: worker [site1], yang membolehkan arahan seterusnya mencari worker berdasarkan nama dan bukannya meneka.

pgrep -af gunicorn
ps -o pid,rss,args -p $(pgrep -d, -f 'gunicorn: worker')

Lajur rss ialah resident set size dalam kilobait: setiap halaman memori yang sedang dipegang oleh proses dalam RAM. Menjumlahkannya merentasi semua worker akan memberikan angka yang terlalu tinggi, kerana worker yang di-fork berkongsi halaman dengan induk dan adik-beradiknya, jadi halaman yang sama dikira beberapa kali. Minta kernel untuk memberikan proportional set size (PSS) sebaliknya, yang membahagikan setiap halaman yang dikongsi merentasi proses yang memetakannya.

for pid in $(pgrep -f 'gunicorn: worker'); do awk -v p="$pid" '/^Pss:/ {printf "%s  %d MB\n", p, $2/1024}' /proc/$pid/smaps_rollup; done

Jalankan arahan tersebut sebagai pengguna yang memiliki worker, atau dengan sudo. PSS ialah lajur yang perlu digunakan untuk belanjawan memori, kerana PSS menjumlahkan nilai dengan tepat manakala RSS tidak.

Django lebih besar disebabkan oleh tindakan django.setup(). Ia mengimport setiap entri dalam INSTALLED_APPS, membina pendaftaran aplikasi, dan menginstansiasi setiap kelas model berserta objek Python untuk setiap medan di dalamnya. Menambah django.contrib.admin akan menjalankan penemuan automatik admin, yang mengimport modul admin setiap aplikasi dan menarik lapisan borang serta templat bersamanya. Worker Flask hanya mengimport Werkzeug dan Jinja2, kemudian berhenti.

Satu peringatan jujur: kerangka kerja (framework) selalunya merupakan bahagian yang kecil. Worker yang mengimport SDK awan atau sebarang pustaka numerik membawa beban yang lebih besar daripada Django. Ukur aplikasi sebenar anda sebelum membuat kesimpulan bahawa kerangka kerja adalah puncanya.

Copy on write, dan sebab preload mengubah nombor tersebut

Proses induk Gunicorn melakukan fork kepada pekerja (workers). Sejurus selepas fork(), proses anak berkongsi setiap halaman memori dengan induk, dan kernel hanya menyalin halaman apabila salah satu pihak menulis kepadanya. Jadi, sama ada pendaftaran model Django wujud sekali atau empat kali pada pelayan bergantung pada bahagian fork mana ia dibina.

Dengan preload_app dimatikan, setiap pekerja mengimport aplikasi anda selepas ia di-fork, jadi setiap satu membina salinan peribadi masing-masing. Dengan ia dihidupkan, induk mengimport aplikasi sekali dan pekerja mewarisi halaman tersebut.

import gc

bind = "unix:/run/site1/gunicorn.sock"
umask = 0o007
workers = 3
timeout = 30
preload_app = True
max_requests = 500
max_requests_jitter = 50

def when_ready(server):
    gc.freeze()

CPython bertindak bertentangan dengan copy on write. Setiap pengepala objek memegang kiraan rujukan (reference count), dan menyentuh objek akan menulis pada pengepala tersebut, jadi halaman yang dikongsi akan disalin semula satu demi satu apabila pengumpul sampah (garbage collector) melayari heap. gc.freeze() memindahkan semua yang diperuntukkan setakat ini ke dalam generasi kekal yang tidak lagi dilawati oleh pengumpul, yang mengekalkan lebih banyak halaman tersebut untuk dikongsi. when_ready adalah hook yang betul kerana ia berjalan selepas preload dan sebelum pekerja pertama di-fork. Ukur PSS sebelum dan selepas anda menambahnya, kerana penjimatan bergantung pada berapa banyak keadaan masa import (import time state) aplikasi anda.

Preload mempunyai satu kos yang mengejutkan orang ramai pada hari pelancaran. systemctl reload menghantar HUP, dan tingkah laku Gunicorn yang didokumentasikan pada HUP adalah untuk memuat semula konfigurasinya dan memulakan pekerja baharu. Apabila aplikasi di-preload, ia tidak mengimport semula kod anda, jadi keluaran baharu anda tidak berjalan walaupun proses pekerja adalah baharu. Gunakan systemctl restart selepas perubahan kod, atau urutan USR2 kemudian WINCH jika anda perlu pekerja lama selesai menjalankan tugas terlebih dahulu.

Berapakah bilangan pekerja yang boleh dijalankan oleh VPS 1 GB secara realistik?

ChartWhere a 1 GB VPS goes, typical idle figures before any traffic
The data behind this chart
[
  {
    "label": "Ubuntu 24.04 base",
    "ram_mb": 190
  },
  {
    "label": "nginx",
    "ram_mb": 12
  },
  {
    "label": "PostgreSQL, default config",
    "ram_mb": 120
  },
  {
    "label": "Headroom you must leave",
    "ram_mb": 150
  },
  {
    "label": "Left for gunicorn workers",
    "ram_mb": 550
  }
]

Angka tersebut adalah untuk keadaan melahu pada pelayan yang tidak melayani sebarang trafik. Kira-kira 550 MB sahaja yang tinggal untuk pekerja aplikasi, dan itu adalah sebelum permintaan pertama tiba.

Sekarang, buat pembahagian dengan jangkaan yang pesimis. Sesuatu permintaan menggunakan memori semasa ia berjalan: queryset yang memuatkan beberapa ribu baris, kemudian proses render templat. Puncak penggunaan bagi setiap pekerja biasanya hampir dua kali ganda angka melahu, jadi buat bajet berdasarkan angka tersebut. Django dengan admin pada 58 MB melahu memberikan anda empat pekerja pada pelayan ini. Flask dengan SQLAlchemy pada 38 MB memberikan anda tujuh.

Cadangan (2 x cores) + 1 daripada Gunicorn mengandaikan CPU sebagai sumber yang terhad dan RAM tidak. Pada VPS kecil, keadaan adalah sebaliknya. Satu vCPU kongsi juga memberikan anda kurang daripada satu teras kuasa pemprosesan apabila hos sibuk, perkara yang perlu difahami sebelum anda menyalahkan kod anda: CPU steal time daripada jiran yang bising akan muncul dalam top sebagai angka st.

Jika view anda kebanyakannya menunggu pangkalan data atau API hulu, thread lebih baik daripada proses dalam situasi ini. --worker-class gthread --workers 2 --threads 4 memberikan lapan permintaan serentak dengan kos memori sebanyak dua pekerja, kerana thread berkongsi satu salinan interpreter dan framework yang dimuatkan. Global interpreter lock bermakna thread tidak membantu view yang menggunakan banyak CPU.

Sediakan swap untuk pelayan tersebut. VPS 1 GB tanpa swap akan menyebabkan lonjakan memori mengakibatkan proses dimatikan (killed), manakala swapfile akan menukarkan lonjakan yang sama kepada permintaan yang perlahan.

sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
echo 'vm.swappiness = 10' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system

Kemudian, tetapkan had untuk aplikasi itu sendiri. MemoryMax=600M pada unit gunicorn bermakna kernel akan mengambil semula memori daripada cgroup aplikasi anda dan bukannya memilih mangsa di seluruh pelayan, jadi permintaan yang tidak terkawal tidak akan menyebabkan sesi SSH anda terputus.

Kelakuan permulaan sejuk dan mula semula

ChartImport to ready, minimal app, one shared vCPU
The data behind this chart
[
  {
    "label": "Flask, one route",
    "cold_start_ms": 90
  },
  {
    "label": "Flask + SQLAlchemy",
    "cold_start_ms": 260
  },
  {
    "label": "Django, admin disabled",
    "cold_start_ms": 480
  },
  {
    "label": "Django, admin enabled",
    "cold_start_ms": 720
  }
]

Kos but perlu dibayar dua kali: pada setiap deploy, dan pada setiap mula semula automatik selepas kegagalan (crash). Aplikasi Flask yang minimum sedia dalam masa kira-kira 90 ms, dan Django dengan admin diaktifkan mengambil masa kira-kira 720 ms pada vCPU kongsi yang sama. Kedua-duanya adalah angka tipikal yang diterbitkan. Ukur sendiri, kerana dependensi anda adalah faktor utama.

cd /srv/site1
DJANGO_SETTINGS_MODULE=site1.settings /srv/site1/.venv/bin/python -X importtime -c "import django; django.setup()" 2>&1 | tail -20

Baris terakhir menyenaraikan import paling perlahan dengan mikrosaat kumulatif. Untuk Flask, jalankan flag yang sama terhadap modul anda: python -X importtime -c "import app".

Dengan preload diaktifkan, master membayar kos tersebut sekali sahaja dan setiap worker yang di-fork bermula serta-merta. Dengan preload dimatikan, setiap worker membayarnya, dan timeout gunicorn meliputi proses but serta permintaan. Worker yang tidak melapor diri dalam tempoh timeout saat akan dimatikan dan diganti, jadi aplikasi berat pada vCPU kongsi yang perlahan boleh terperangkap dalam gelung mula semula yang tidak pernah melayan sebarang permintaan. Log menyatakan:

[2026-08-09 09:14:02 +0000] [981] [CRITICAL] WORKER TIMEOUT (pid:1004)

Migrasi perlu diletakkan dalam unit, bukan dalam kod permulaan aplikasi. ExecStartPre berjalan sekali sebelum mana-mana worker wujud. Meletakkan migrate di dalam aplikasi anda bermakna tiga worker akan berlumba sesama sendiri untuk mendapatkan kunci skema yang sama.

Bentuk penempatan adalah hampir sama

Pengurus proses

Kedua-dua rangka kerja berjalan di bawah gunicorn, dan gunicorn berjalan di bawah systemd.

[Unit]
Description=gunicorn for site1
After=network.target

[Service]
User=site1
Group=www-data
WorkingDirectory=/srv/site1
RuntimeDirectory=site1
Environment="PATH=/srv/site1/.venv/bin"
ExecStartPre=/srv/site1/.venv/bin/python manage.py migrate --noinput
ExecStart=/srv/site1/.venv/bin/gunicorn -c /srv/site1/gunicorn.conf.py site1.wsgi:application
Restart=on-failure
RestartSec=3
MemoryMax=600M

[Install]
WantedBy=multi-user.target

RuntimeDirectory=site1 mencipta /run/site1 semasa permulaan dan memadamkannya semasa berhenti, jadi laluan soket sentiasa wujud dengan pemilik yang betul. Baris umask = 0o007 dalam konfigurasi gunicorn adalah perkara yang menjadikan soket tersebut boleh ditulis oleh kumpulan www-data, iaitu cara nginx mencapainya.

Unit Flask adalah fail yang sama dengan satu baris diubah: ExecStart=... gunicorn -c /srv/site1/gunicorn.conf.py app:app, dan tiada ExecStartPre. Argumen app:app ialah modul diikuti oleh callable, jadi ralat Failed to find attribute 'app' in 'app'. bermakna modul anda tidak mentakrifkan pemboleh ubah dengan nama tersebut. Kerja berjadual mengikut corak yang sama, dan pemasa systemd menggantikan cron untuk arahan pengurusan Django tanpa menambah baris gilir tugas pada kotak sebesar ini.

Fail statik

Django dengan DEBUG = False tidak menghidangkan sebarang fail statik. Tetapkan STATIC_ROOT, jalankan python manage.py collectstatic, dan halakan pelayan web ke direktori output. Langkau langkah itu dan admin akan dimuatkan tanpa penggayaan sementara log dipenuhi dengan Not Found: /static/admin/css/base.css.

Terdapat dua cara yang munasabah untuk menghidangkannya. Blok alias nginx tidak membebankan aplikasi anda. WhiteNoise, yang ditambah sebagai middleware, menghidangkan fail daripada worker dan menjimatkan blok nginx anda, dengan kos sedikit masa worker bagi setiap fail. Flask menghidangkan folder static/ sendiri dalam pembangunan, dan dalam pengeluaran anda menghalakan proksi ke folder tersebut atas sebab yang sama.

Reverse proxy

server {
    listen 80;
    server_name example.com;

    location /static/ {
        alias /srv/site1/static/;
        expires 30d;
    }

    location / {
        proxy_pass http://unix:/run/site1/gunicorn.sock;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Di sebalik mana-mana proksi, Django perlu diberitahu bahawa permintaan asal adalah HTTPS atau semakan cross site request forgery (CSRF) akan menolak borang anda sendiri.

ALLOWED_HOSTS = ["example.com"]
CSRF_TRUSTED_ORIGINS = ["https://example.com"]
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

Jika kotak tersebut sudah menjalankan kontena, Traefik di hadapan beberapa aplikasi Docker Compose melakukan tugas yang sama dengan label pada kontena dan bukannya satu fail bagi setiap tapak.

Pangkalan data mana yang perlu dipilih

SQLite sebenarnya sesuai untuk pelayan aplikasi tunggal dengan kadar penulisan yang diukur dalam beberapa saat, dan ia membuang keseluruhan daemon daripada bajet memori. Hidupkan write ahead logging (WAL) dan berikan pemacu (driver) masa tamat sibuk (busy timeout).

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
        "OPTIONS": {
            "timeout": 20,
            "init_command": "PRAGMA journal_mode=WAL;",
        },
    }
}

Tanpa dua pilihan tersebut, anda akan menemui django.db.utils.OperationalError: database is locked pada kali pertama dua worker menulis serentak, kerana mod jurnal lalai menyekat pembaca semasa penulisan dan masa tamat lalai akan berhenti hampir serta-merta. Hujah yang lebih panjang, termasuk di mana SQLite berhenti menjadi jawapan yang tepat, ada dalam menjalankan SQLite dalam pengeluaran pada VPS.

PostgreSQL pada kotak 1 GB yang sama menelan kos 120 MB dalam bajet di atas, ditambah satu proses backend bagi setiap sambungan berterusan. CONN_MAX_AGE Django mengekalkan satu sambungan terbuka bagi setiap worker, jadi empat worker bermakna empat backend. Itu biasanya pertukaran yang berbaloi. Kira sahaja jumlahnya sebelum anda menetapkan bilangan worker. Jika anda lebih suka menyimpan pangkalan data dalam kontena di sebelah aplikasi, menjalankan Docker pada VPS adalah pertukaran yang sama pada tahap yang lebih tinggi, memandangkan daemon dan setiap kontena menambah overhead yang penting pada saiz ini.

Apa yang diperoleh dan kos yang ditanggung

Megabait tambahan dalam Django terdiri daripada senarai komponen yang sedia ada dan berfungsi secara bersepadu: ORM dengan migrasi, sistem sesi dan pengesahan, model kebenaran, lapisan borang dengan perlindungan CSRF, enjin templat, arahan pengurusan, serta panel admin. Panel admin merupakan komponen yang sering dipandang rendah. Ia merupakan penyunting pangkalan data yang berfungsi sepenuhnya untuk model anda, lengkap dengan fungsi carian dan penapis, hanya dengan satu baris kod dalam INSTALLED_APPS.

Flask pula adalah sebaliknya. Anda mendapat penghalaan (routing), objek permintaan, templat Jinja2, dan objek konfigurasi. Segala komponen lain adalah pilihan anda sendiri, yang memberikan nilai sebenar apabila aplikasi bersaiz kecil, kerana tiada ORM yang dimuatkan jika anda tidak mengimportnya.

Perangkapnya terletak pada jalan tengah. Jika anda menambah SQLAlchemy untuk model, Alembic untuk migrasi, Flask-Login untuk sesi, Flask-WTF untuk borang dan CSRF, serta sambungan admin untuk pejabat belakang, anda telah membina sesuatu yang mempunyai profil memori seperti Django tetapi tanpa kesepaduan yang sama. Setiap komponen mempunyai kitaran keluaran (release cycle) tersendiri dan pandangan berbeza tentang cara aplikasi harus disambungkan. Pada tahap itulah Django menjadi pilihan yang lebih murah, dari segi penggunaan RAM dan jam yang anda habiskan untuk kerja-kerja naik taraf.

Django lwn Flask: peraturan membuat keputusan

Gunakan Django apabila aplikasi mempunyai akaun, kandungan yang boleh disunting, skema yang akan sentiasa berubah, dan pejabat belakang (back office) yang akan digunakan oleh seseorang. Gunakan Flask apabila aplikasi tersebut merupakan antara muka JSON di atas storan data yang sedia ada, atau penerima webhook yang tidak mengandungi HTML.

Penentu keputusan ialah senarai bertulis. Tuliskan setiap pakej yang anda akan pasang dalam Flask untuk mencapai set ciri yang anda perlukan. Jika senarai itu mengandungi ORM dan alat migrasi, anda sebenarnya telah memilih Django dan anda membayar lebih untuk sampai ke tahap itu dengan perlahan.

Satu kes yang benar-benar memihak kepada Flask pada perkakasan kecil ialah: beberapa servis kecil pada satu kotak. Setiap servis Flask merupakan proses murah di bawah unitnya sendiri. Tiga tapak Django pada satu VPS 1 GB bermakna tiga salinan kerangka kerja (framework) yang menetap serentak, dan pengiraan di atas tidak lagi berkesan. Jika ia sentiasa tidak mencukupi, pelan yang lebih besar sering kali merupakan penyelesaian yang jujur, dan kos sebenar VPS sebulan adalah perbincangan yang lebih singkat berbanding menulis semula aplikasi yang sedang berfungsi.

Mod kegagalan dengan rentetan yang akan anda lihat

Worker hilang dan muncul semula. Gunicorn mencetak [ERROR] Worker (pid:1234) was sent SIGKILL! Perhaps out of memory?. Ia mencetak mesej ini apabila ia mematikan worker yang terlepas heartbeat tamat masa, dan apabila kernel mematikan proses tersebut. Bezakan kedua-duanya dengan dmesg -T | grep -i "killed process". Baris di situ bermaksud masalah memori, jadi kurangkan bilangan worker atau tambah swap.

Setiap halaman mengembalikan 400 dan log menyatakan Invalid HTTP_HOST header. Mesej penuhnya ialah Invalid HTTP_HOST header: 'example.com'. You may need to add 'example.com' to ALLOWED_HOSTS.. Django menolak permintaan tersebut sebelum ia sampai ke kod anda, kerana ALLOWED_HOSTS kosong atau tidak menyertakan nama yang dihantar oleh proksi dalam Host.

Borang gagal dengan Origin checking failed. Halaman menyatakan pengesahan CSRF gagal. Ini berlaku di sebalik proksi penamatan TLS: aplikasi melihat HTTP biasa, membina origin http://, dan membandingkannya dengan permintaan yang tiba melalui https://. Tetapkan SECURE_PROXY_SSL_HEADER dan CSRF_TRUSTED_ORIGINS, serta pastikan proksi benar-benar menghantar X-Forwarded-Proto.

nginx mengembalikan 502 serta-merta. Log ralat menamakan puncanya: connect() to unix:/run/site1/gunicorn.sock failed (2: No such file or directory) bermaksud unit tidak berjalan, dan (13: Permission denied) bermaksud soket wujud tetapi nginx tidak dapat membukanya, yang berpunca daripada tetapan umask dan kumpulan.

Admin tiada penggayaan. collectstatic belum dijalankan, atau laluan alias tidak sepadan dengan STATIC_ROOT. Log akses menunjukkan ralat 404 di bawah /static/admin/.

Penulisan gagal di bawah beban ringan. database is locked daripada SQLite bermaksud WAL dimatikan atau tamat masa sibuk (busy timeout) terlalu singkat untuk dua worker yang menulis pada saat yang sama.

FAQ

Adakah Django terlalu berat untuk VPS 1 GB?

Tidak. Django dengan bilangan worker yang kecil, Nginx di hadapan dan SQLite di belakang boleh berjalan dengan selesa pada 1 GB. Ia menjadi terhad apabila anda menambah PostgreSQL dengan tetapan lalai, cache, worker latar belakang dan Docker pada pelayan yang sama. Ukur proportional set size bagi satu worker, gandakan nilainya untuk menampung lonjakan permintaan, dan bandingkan jumlahnya dengan baki RAM selepas ditolak penggunaan sistem pengendalian dan pangkalan data.

Berapa banyak worker gunicorn yang perlu saya jalankan pada satu vCPU?

Mulakan dengan tiga dan buat ukuran. Memori biasanya menjadi kekangan utama pada VPS kecil, jadi bahagikan baki RAM selepas ditolak penggunaan sistem pengendalian dan pangkalan data dengan dua kali ganda proportional set size satu worker. Jika view anda kebanyakannya menunggu pangkalan data atau API hulu, tukar kepada kelas worker gthread dengan bilangan worker yang kecil dan beberapa thread bagi setiap satu, kerana thread berkongsi satu salinan framework yang dimuatkan dan menggunakan memori yang jauh lebih sedikit berbanding proses tambahan.

Adakah saya perlukan PostgreSQL, atau adakah SQLite mencukupi?

SQLite mencukupi untuk satu pelayan aplikasi dengan kadar penulisan yang sederhana, dan ia menjimatkan penggunaan memori kerana tidak memerlukan daemon tambahan. Aktifkan write ahead logging dan tetapkan busy timeout, atau penulisan serentak akan gagal dengan database is locked. Berpindah ke PostgreSQL apabila lebih daripada satu mesin perlu menulis, atau apabila anda memerlukan ciri yang tidak ditawarkan oleh SQLite seperti penulis berat yang serentak atau kawalan akses mengikut peranan.

Patutkah saya menjalankan uvicorn dan bukannya gunicorn?

Hanya jika anda mempunyai view async dan sesuatu yang benar-benar perlu ditunggu. Flask ialah aplikasi WSGI, jadi view async berjalan dalam event loop baharu di dalam thread worker dan selesai sebelum permintaan seterusnya bermula, yang tidak memberikan sebarang konkurensi tambahan. View async Django memerlukan pelayan ASGI untuk memberikan sebarang manfaat. Keluaran uvicorn terkini telah memindahkan kelas worker gunicorn mereka ke dalam pakej berasingan, jadi baca dokumentasi uvicorn semasa dan bukannya menyalin flag kelas worker lama daripada tutorial terdahulu.

Mengapa worker saya hilang tanpa sebarang traceback?

Proses yang dimatikan oleh kernel out of memory killer akan menerima SIGKILL dan tidak dapat merekodkan apa-apa sebelum ditamatkan, jadi log aplikasi anda terhenti begitu sahaja. Gunicorn mengesan jurang tersebut dan mencetak Worker (pid:1234) was sent SIGKILL! Perhaps out of memory?. Sahkan perkara ini dengan dmesg -T | grep -i "killed process". Penyelesaiannya ialah mengurangkan bilangan worker, atau menambah swapfile supaya lonjakan memori hanya menyebabkan permintaan menjadi perlahan dan bukannya mematikan proses.

#django#flask#python#gunicorn#deployment#vps