SSD Nodes Learn 🎉 VPS $5.50/மாதம் முதல்
கல்வி வழிகாட்டிகள் Matt Connorஆல் Matt Connor · புதுப்பிக்கப்பட்டது 2026-08-13

சிறிய VPS-ல் Django vs Flask: எது சிறந்தது?

1 GB முதல் 2 GB RAM கொண்ட VPS சர்வர்களில் Django மற்றும் Flask பயன்பாட்டின் உண்மையான RAM செலவு என்ன? Gunicorn worker எண்ணிக்கை மற்றும் செயல்திறன் குறித்த விரிவான ஒப்பீடு.

சிறிய VPS-ல் Django மற்றும் Flask-ன் பயன்பாட்டுச் செலவு

சிறிய VPS-ல் Django மற்றும் Flask-ஐ ஒப்பிடும்போது, முதன்மையான காரணி நினைவகம் (memory) ஆகும். நீங்கள் தொடங்கும் ஒவ்வொரு worker process-லும் Django தனது object relational mapper (ORM), migration கருவிகள் மற்றும் நீங்கள் செயல்படுத்தினால் admin site ஆகியவற்றையும் ஏற்றுகிறது. Flask ஒரு router மற்றும் ஒரு request object-ஐ மட்டுமே ஏற்றுகிறது. 1 GB அளவுள்ள server-ல், இந்த வேறுபாடு எத்தனை worker-களை இயக்க முடியும் என்பதைத் தீர்மானிக்கிறது; worker-களின் எண்ணிக்கையே ஒரே நேரத்தில் எத்தனை request-களை கையாள முடியும் என்பதைத் தீர்மானிக்கிறது.

Django வழங்கும் வசதிகளை நீங்கள் மீண்டும் உருவாக்கத் தேவையில்லை என்றால் மட்டுமே, இந்த நினைவகப் பயன்பாடு ஒரு செலவாகக் கருதப்படும். பயனர் கணக்குகள், sessions மற்றும் admin panel கொண்ட ஒரு application-க்கு Django சிறந்தது: ஒவ்வொரு worker-க்கும் தேவைப்படும் RAM என்பது, நீங்கள் எழுத வேண்டிய அவசியமில்லாத குறியீட்டிற்கான (code) விலையாகும். ஏற்கனவே இயங்கும் ஒரு datastore-க்கு முன்னால் ஒரு JSON API தேவைப்பட்டால், Flask-ஐத் தேர்ந்தெடுக்கலாம், ஏனெனில் அதில் தேவையற்ற வசதிகள் எதுவும் ஏற்றப்படாது. இது பயன்பாட்டிற்கு எது பொருத்தமானது என்ற கேள்வி. கீழே உள்ள அளவீடுகள் உங்கள் application எந்த வகையைச் சார்ந்தது என்பதைத் தெளிவுபடுத்தும்.

ஒரு gunicorn worker எவ்வளவு memory-ஐப் பயன்படுத்துகிறது?

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
  }
]

இவை Ubuntu 24.04 மற்றும் Python 3.12-ல், மூன்று gunicorn workers மற்றும் preload வசதியுடன் இயங்கும் ஒரு hello world application-க்கான பொதுவான புள்ளிவிவரங்கள். இவற்றை ஒரு அடிப்படை அளவீடாகக் கருதவும், ஏனெனில் உங்கள் சொந்த imports இதனுடன் கூடுதலாகச் சேரும். Django admin வசதி கொண்ட ஒரு worker 96 MB resident memory-ஐயும், அதன் விகிதாச்சார memory பங்காக 58 MB-யையும் பயன்படுத்துகிறது. இந்த இரண்டு எண்களுக்கும் இடையே உள்ள வித்தியாசமே அடுத்த பகுதியின் முக்கியப் பொருளாகும்.

உங்கள் சொந்த server-ல் இதே அளவீட்டைச் செய்து பாருங்கள்.

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

setproctitle-ஐ நிறுவுங்கள். இது இருந்தால், gunicorn தனது process-களுக்கு gunicorn: master [site1] மற்றும் gunicorn: worker [site1] எனப் பெயரிடும். இதன் மூலம், அடுத்தடுத்த கட்டளைகளில் process-களை அவற்றின் பெயரைக் கொண்டே கண்டறிய முடியும்.

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

rss column என்பது resident set size-ஐ kilobytes-ல் குறிக்கிறது: இது ஒரு process தற்போது RAM-ல் வைத்துள்ள ஒவ்வொரு memory page-ஐயும் குறிக்கும். அனைத்து workers-ன் மதிப்பையும் கூட்டினால் அது மிக அதிகமான எண்ணாகத் தோன்றும், ஏனெனில் forked worker தனது parent மற்றும் பிற siblings-உடன் memory pages-ஐப் பகிர்ந்து கொள்கிறது; எனவே ஒரே page பலமுறை கணக்கிடப்படுகிறது. இதற்குப் பதிலாக, kernel-இடம் proportional set size (PSS)-ஐக் கேளுங்கள். இது பகிரப்பட்ட ஒவ்வொரு page-ஐயும் அதை அணுகும் process-களுக்கு இடையே பிரித்துக் கணக்கிடுகிறது.

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

இதை workers-ஐ இயக்கும் user-ஆகவோ அல்லது sudo மூலமாகவோ இயக்கவும். PSS-ஐ அடிப்படையாகக் கொண்டு memory-ஐத் திட்டமிடுங்கள், ஏனெனில் PSS சரியாகக் கணக்கிடப்படும், ஆனால் RSS அவ்வாறு கணக்கிடப்படாது.

django.setup() செய்யும் வேலைகளால் Django-வின் அளவு அதிகமாகிறது. இது INSTALLED_APPS-ல் உள்ள ஒவ்வொரு entry-யையும் import செய்து, application registry-ஐ உருவாக்கி, ஒவ்வொரு model class-ஐயும், அதிலுள்ள ஒவ்வொரு field-க்கான Python object-உடன் சேர்த்து உருவாக்குகிறது. django.contrib.admin-ஐச் சேர்ப்பது admin autodiscovery-ஐ இயக்கும்; இது ஒவ்வொரு app-ன் admin module-ஐயும் import செய்து, அதனுடன் forms மற்றும் template layers-ஐயும் கொண்டு வரும். ஒரு Flask worker, Werkzeug மற்றும் Jinja2-ஐ மட்டும் import செய்துவிட்டு நின்றுவிடும்.

ஒரு முக்கியமான எச்சரிக்கை: பெரும்பாலும் framework-ன் பங்கு சிறியதுதான். ஒரு cloud SDK அல்லது ஏதேனும் numeric library-ஐ import செய்யும் worker, Django-வை விட அதிக memory-ஐப் பயன்படுத்தக்கூடும். framework தான் பிரச்சினை என்று முடிவெடுக்கும் முன், உங்கள் உண்மையான application-ஐ அளவீடு செய்யுங்கள்.

Copy on write மற்றும் preload ஏன் எண்ணிக்கையை மாற்றுகிறது

Gunicorn-ன் master process, worker-களை fork செய்கிறது. fork()-க்கு பிறகு, child process-ஆனது parent-உடன் அனைத்து memory page-களையும் பகிர்ந்து கொள்கிறது. ஏதேனும் ஒரு பக்கம் அதில் எழுதும்போது மட்டுமே kernel அந்தப் பக்கத்தை நகல் (copy) எடுக்கும். எனவே, Django-வின் model registry அந்த server-ல் ஒருமுறை உள்ளதா அல்லது நான்கு முறை உள்ளதா என்பது, fork-க்கு முன்னால் அது உருவாக்கப்பட்டதா அல்லது பின்னால் உருவாக்கப்பட்டதா என்பதைப் பொறுத்தது.

preload_app முடக்கப்பட்டிருந்தால் (off), ஒவ்வொரு worker-உம் fork செய்யப்பட்ட பிறகு உங்கள் application-ஐ import செய்யும்; எனவே ஒவ்வொன்றும் தனக்கான தனிப்பட்ட நகலை உருவாக்கும். அது இயக்கப்பட்டிருந்தால் (on), master process ஒருமுறை மட்டுமே application-ஐ import செய்யும், worker-கள் அந்தப் பக்கங்களை அப்படியே பெற்றுக்கொள்ளும்.

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, copy on write முறைக்கு எதிராகச் செயல்படுகிறது. ஒவ்வொரு object header-லும் ஒரு reference count இருக்கும். ஒரு object-ஐத் தொடும்போது அந்த header-ல் மாற்றம் ஏற்படும். எனவே, garbage collector heap-ஐ ஆய்வு செய்யும்போது, பகிரப்பட்ட பக்கங்கள் ஒவ்வொன்றாக நகலெடுக்கப்படும். gc.freeze(), இதுவரை ஒதுக்கப்பட்ட அனைத்தையும் ஒரு நிரந்தர தலைமுறைக்கு (permanent generation) மாற்றுகிறது. இதை collector இனி ஆய்வு செய்யாது என்பதால், அதிகப்படியான பக்கங்கள் பகிரப்பட்ட நிலையிலேயே இருக்கும். when_ready சரியான hook ஆகும், ஏனெனில் இது preload-க்கு பிறகும், முதல் worker fork செய்யப்படுவதற்கு முன்பும் இயங்கும். இதைச் சேர்த்த பிறகு PSS-ஐ அளந்து பாருங்கள், ஏனெனில் சேமிக்கப்படும் அளவு உங்கள் application-ன் import time state-ஐப் பொறுத்தது.

Preload-ல் உள்ள ஒரு அம்சம் deploy நாளில் பலரை ஆச்சரியப்படுத்தும். systemctl reload, HUP சிக்னலை அனுப்புகிறது. HUP-ல் gunicorn-ன் ஆவணப்படுத்தப்பட்ட செயல்பாடு என்னவென்றால், அது தனது configuration-ஐ மீண்டும் ஏற்றி (reload) புதிய worker-களைத் தொடங்கும். Application preload செய்யப்பட்டிருக்கும்போது, அது உங்கள் code-ஐ மீண்டும் import செய்யாது. எனவே, worker process-கள் புதியதாக இருந்தாலும், உங்கள் புதிய release இயங்காது. Code மாற்றத்திற்குப் பிறகு systemctl restart-ஐப் பயன்படுத்தவும். அல்லது பழைய worker-கள் முழுமையாக வெளியேற வேண்டும் என்றால், USR2 மற்றும் அதைத் தொடர்ந்து WINCH என்ற வரிசையைப் பயன்படுத்தவும்.

1 GB VPS-ல் எத்தனை workers-களை தாராளமாக இயக்க முடியும்?

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
  }
]

இவை எந்தப் பணியும் செய்யாத, idle நிலையில் உள்ள கணக்கீடுகள். பயன்பாட்டு workers-களுக்காக சுமார் 550 MB மட்டுமே எஞ்சியுள்ளது; இது முதல் request வருவதற்கு முன்பே உள்ள நிலை.

இப்போது, pessimistically பிரித்துப் பார்க்கவும். ஒரு request இயங்கும்போது அதற்கு memory தேவைப்படும்: சில ஆயிரம் rows-களை ஏற்றும் queryset மற்றும் template render போன்றவை இதற்கு உதாரணம். ஒரு worker-ன் உச்சகட்ட memory பயன்பாடு, அதன் idle அளவை விட இருமடங்காக இருக்கும் என்பதால், அதற்கேற்ப திட்டமிடவும். Django admin-ஐப் பயன்படுத்தும்போது 58 MB idle memory இருந்தால், இந்த server-ல் நான்கு workers-களை மட்டுமே இயக்க முடியும். SQLAlchemy உடன் Flask பயன்படுத்தினால் 38 MB வீதம் ஏழு workers-களை இயக்கலாம்.

Gunicorn-ன் (2 x cores) + 1 பரிந்துரை, CPU மட்டுமே பற்றாக்குறையான வளம் என்றும் RAM தாராளமாக உள்ளது என்றும் கருதுகிறது. சிறிய VPS-ல் இது தலைகீழானது. Host பிஸியாக இருக்கும்போது, ஒரு shared vCPU உங்களுக்கு ஒரு முழு core-ன் திறனைத் தராது. உங்கள் code-ஐக் குறை கூறுவதற்கு முன் இதைத் தெரிந்துகொள்வது அவசியம்: noisy neighbour-ஆல் ஏற்படும் CPU steal time என்பது top-ல் st மதிப்பாகக் காட்டப்படும்.

உங்கள் views பெரும்பாலும் database அல்லது upstream API-க்காகக் காத்திருந்தால், processes-ஐ விட threads சிறந்தது. --worker-class gthread --workers 2 --threads 4, இரண்டு workers-களுக்கான memory செலவில் எட்டு concurrent requests-களைக் கையாள அனுமதிக்கிறது. ஏனெனில், threads ஒரே interpreter மற்றும் framework-ன் நகலைப் பகிர்ந்து கொள்கின்றன. Global interpreter lock இருப்பதால், CPU-வை அதிகம் பயன்படுத்தும் view-களுக்கு threads உதவாது.

Server-ல் swap-ஐச் சேர்க்கவும். Swap இல்லாத 1 GB VPS-ல் memory spike ஏற்பட்டால், அந்த process கொல்லப்படும். ஆனால் swapfile இருந்தால், அதே spike மெதுவான request-ஆக மட்டுமே மாறும்.

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

பிறகு, application-ன் பயன்பாட்டைக் கட்டுப்படுத்தவும். Gunicorn unit-ல் MemoryMax=600M-ஐ அமைப்பதன் மூலம், kernel உங்கள் app-ன் cgroup-லிருந்து memory-ஐத் திரும்பப் பெறும். மாறாக, server-ல் உள்ள மற்ற process-களை அது பாதிக்காது. இதனால், ஒரு runaway request-ஆல் உங்கள் SSH session துண்டிக்கப்படாது.

Cold start மற்றும் restart நடத்தை

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
  }
]

Boot செலவு இரண்டு முறை ஏற்படுகிறது: ஒவ்வொரு deploy-ன் போதும், மற்றும் crash-க்கு பின் நடக்கும் ஒவ்வொரு automatic restart-ன் போதும். ஒரு சிறிய Flask app சுமார் 90 ms-ல் தயாராகிவிடும், அதே shared vCPU-வில் Django admin-உடன் இயங்க சுமார் 720 ms எடுத்துக்கொள்ளும். இவை இரண்டும் பொதுவான புள்ளிவிவரங்கள். உங்கள் dependencies-ன் அளவைப் பொறுத்து இது மாறுபடும் என்பதால், நீங்களே அளவிடுவது சிறந்தது.

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

கடைசி வரிகள் மிக மெதுவான imports-ஐ cumulative microseconds-ல் பட்டியலிடும். Flask-க்கு, உங்கள் module-ல் அதே flag-ஐப் பயன்படுத்தவும்: python -X importtime -c "import app".

Preload ஆன் செய்யப்பட்டிருந்தால், master process அந்தச் செலவை ஒருமுறை மட்டுமே ஏற்கும், அதன் பிறகு forked workers உடனடியாகத் தொடங்கும். Preload ஆஃப் செய்யப்பட்டிருந்தால், ஒவ்வொரு worker-ம் அந்தச் செலவை ஏற்கும், மேலும் gunicorn-ன் timeout boot மற்றும் request ஆகிய இரண்டையும் உள்ளடக்கும். timeout வினாடிகளுக்குள் check-in செய்யாத worker கொல்லப்பட்டு மாற்றப்படும், எனவே மெதுவான shared vCPU-வில் இயங்கும் ஒரு கனமான app, எதையும் சேவை செய்யாமல் restart loop-ல் சிக்கிக்கொள்ளலாம். Log இவ்வாறு காட்டும்:

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

Migrations என்பது unit-ன் ஒரு பகுதி, application startup code-ல் இருக்கக்கூடாது. ExecStartPre எந்தவொரு worker-ம் தொடங்குவதற்கு முன்பே ஒருமுறை இயங்கும். migrate-ஐ உங்கள் app-க்குள் வைத்தால், மூன்று workers ஒரே schema lock-க்காகப் போட்டியிடும்.

Deployment வடிவம் ஏறக்குறைய ஒரே மாதிரியானது

Process manager

இரண்டு frameworks-ம் gunicorn-ன் கீழ் இயங்குகின்றன, gunicorn 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 தொடங்கும் போது /run/site1-ஐ உருவாக்கி, நிறுத்தும் போது அதை நீக்குகிறது, எனவே socket path எப்போதும் சரியான உரிமையாளருடன் இருக்கும். gunicorn config-ல் உள்ள umask = 0o007 வரிதான் அந்த socket-ஐ www-data group-ஆல் எழுதக்கூடியதாக மாற்றுகிறது, இதன் மூலமே nginx அதை அணுகுகிறது.

Flask unit கோப்பும் அதேதான், ஒரு வரியில் மட்டும் மாற்றம்: ExecStart=... gunicorn -c /srv/site1/gunicorn.conf.py app:app, மற்றும் ExecStartPre கிடையாது. app:app argument என்பது module மற்றும் callable ஆகும், எனவே Failed to find attribute 'app' in 'app'. பிழை ஏற்பட்டால், உங்கள் module-ல் அந்தப் பெயரில் variable வரையறுக்கப்படவில்லை என்று அர்த்தம். Scheduled work-ம் இதே முறையைப் பின்பற்றுகிறது, மேலும் Django management command-க்கு cron-க்கு பதிலாக systemd timer பயன்படுத்தலாம், இது சிறிய server-களில் task queue-ஐச் சேர்க்காமல் வேலையை முடிக்கும்.

Static files

DEBUG = False கொண்ட Django எந்த static கோப்புகளையும் வழங்காது. STATIC_ROOT-ஐ அமைத்து, python manage.py collectstatic-ஐ இயக்கி, அந்த output directory-ஐ web server-க்குச் சுட்டிக்காட்டவும். அந்தப் படியைத் தவிர்த்தால், admin பக்கம் styling இல்லாமல் தோன்றும் மற்றும் log-ல் Not Found: /static/admin/css/base.css பிழைகள் நிரம்பும்.

இவற்றை வழங்க இரண்டு முறைகள் உள்ளன. ஒரு nginx alias block உங்கள் app-க்கு எந்தச் சுமையையும் தராது. Middleware-ஆகச் சேர்க்கப்படும் WhiteNoise, worker மூலமாகவே கோப்புகளை வழங்கும், இது nginx block-ஐத் தவிர்க்க உதவும், ஆனால் ஒவ்வொரு கோப்பிற்கும் சிறிது worker நேரம் செலவாகும். Flask development-ல் அதன் சொந்த static/ folder-ஐ வழங்குகிறது, production-ல் அதே காரணத்திற்காக proxy-ஐ அந்த folder-க்குச் சுட்டிக்காட்ட வேண்டும்.

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;
    }
}

எந்த proxy-க்கு பின்னாலும், அசல் கோரிக்கை HTTPS-ல் வந்தது என்பதை Django-க்குத் தெரிவிக்க வேண்டும், இல்லையெனில் அதன் cross site request forgery (CSRF) சோதனைகள் உங்கள் forms-ஐ நிராகரிக்கும்.

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

server-ல் ஏற்கனவே containers இயங்கினால், பல Docker Compose apps-க்கு முன்னால் Traefik பயன்படுத்துவது, ஒவ்வொரு தளத்திற்கும் தனித்தனி கோப்புகளை உருவாக்குவதற்குப் பதிலாக, container-ல் உள்ள labels மூலமாகவே அதே வேலையைச் செய்யும்.

எந்த database

வினாடிக்குச் சில முறை மட்டுமே எழுதும் (write) வசதி கொண்ட ஒற்றை application server-க்கு SQLite போதுமானது, இது memory-யிலிருந்து ஒரு முழு daemon-ஐ நீக்குகிறது. Write ahead logging (WAL)-ஐ இயக்கி, driver-க்கு busy timeout-ஐ வழங்கவும்.

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

இந்த இரண்டு விருப்பங்கள் இல்லையென்றால், இரண்டு workers ஒரே நேரத்தில் எழுதும் போது django.db.utils.OperationalError: database is locked பிழையைச் சந்திப்பீர்கள். ஏனெனில், இயல்பான journal mode எழுதும் போது வாசிப்பதைத் தடுக்கும் (blocks readers) மற்றும் இயல்பான timeout உடனடியாகச் செயலிழந்துவிடும். SQLite எப்போது பொருத்தமற்றதாகிறது என்பது குறித்த விரிவான விளக்கம் VPS-ல் SQLite-ஐ production-ல் இயக்குதல் பகுதியில் உள்ளது.

அதே 1 GB server-ல் PostgreSQL பயன்படுத்தினால், மேலே குறிப்பிட்ட budget-ல் 120 MB செலவாகும், மேலும் ஒவ்வொரு persistent connection-க்கும் ஒரு backend process தேவைப்படும். Django-ன் CONN_MAX_AGE ஒவ்வொரு worker-க்கும் ஒரு connection-ஐத் திறந்து வைத்திருக்கும், எனவே நான்கு workers-க்கு நான்கு backends தேவைப்படும். இது பொதுவாகச் சிறந்த மாற்றாகும். worker எண்ணிக்கையை அமைக்கும் முன் இதைக் கணக்கிடுங்கள். database-ஐ app-க்கு அருகில் container-ல் வைத்திருக்க விரும்பினால், VPS-ல் Docker-ஐ இயக்குதல் அதே பலனைத் தரும், ஆனால் daemon மற்றும் ஒவ்வொரு container-ம் கூடுதல் சுமையைச் சேர்க்கும், இது சிறிய server-களில் கவனிக்கத்தக்கது.

பேட்டரிகள் எதை வாங்குகின்றன, அவற்றின் விலை என்ன

Django-வின் கூடுதல் மெகாபைட்டுகள் ஏற்கனவே இருக்கும் மற்றும் ஒன்றாகச் செயல்படும் அம்சங்களின் தொகுப்பாகும்: migrations வசதியுடன் கூடிய ORM, session மற்றும் authentication அமைப்பு, permission model, CSRF பாதுகாப்புடன் கூடிய form layer, template engine, management commands மற்றும் admin. இதில் admin என்பது மக்கள் குறைவாக மதிப்பிடும் ஒரு பகுதியாகும். இது உங்கள் models-க்கான ஒரு முழுமையான database editor ஆகும்; இதில் search மற்றும் filters வசதிகள் உள்ளன, மேலும் இதைச் செயல்படுத்த INSTALLED_APPS-ல் ஒரே ஒரு வரி மட்டுமே தேவைப்படும்.

Flask இதற்கு நேர்மாறானது. இதில் routing, request object, Jinja2 templates மற்றும் config object மட்டுமே கிடைக்கும். மற்ற அனைத்தும் உங்கள் விருப்பம். application சிறியதாக இருக்கும்போது இது உண்மையான நன்மையைத் தருகிறது, ஏனெனில் நீங்கள் எதையும் import செய்யாதவரை எந்த ORM-ம் load ஆகாது.

இடைப்பட்ட நிலையில் இருப்பதுதான் ஆபத்தானது. models-க்கு SQLAlchemy, migrations-க்கு Alembic, sessions-க்கு Flask-Login, forms மற்றும் CSRF-க்கு Flask-WTF, மற்றும் back office-க்கு ஒரு admin extension ஆகியவற்றைச் சேர்த்தால், Django-வின் memory பயன்பாட்டைக் கொண்ட, ஆனால் அதன் ஒருங்கிணைப்பு இல்லாத ஒரு அமைப்பை நீங்கள் உருவாக்கிவிடுவீர்கள். ஒவ்வொரு பகுதிக்கும் தனித்தனி release cycle மற்றும் application எவ்வாறு இயங்க வேண்டும் என்பது குறித்த தனித்தனி கருத்துகள் இருக்கும். அந்த நிலையில்தான், RAM பயன்பாடு மற்றும் மேம்படுத்தல்களுக்கு (upgrades) செலவிடும் நேரம் ஆகியவற்றைக் கணக்கிடும்போது, Django மலிவான தீர்வாகிறது.

Django மற்றும் Flask: முடிவெடுப்பதற்கான விதி

பயனர் கணக்குகள், திருத்தக்கூடிய உள்ளடக்கம், அடிக்கடி மாறக்கூடிய schema மற்றும் நிர்வாகக் குழு (back office) தேவைப்படும் செயலிகளுக்கு Django-வை பயன்படுத்தவும். ஏற்கனவே உள்ள தரவுத்தளத்தின் மீது JSON interface-ஆகச் செயல்படும் செயலிகளுக்கோ அல்லது HTML இல்லாத webhook receiver-களுக்கோ Flask-ஐ பயன்படுத்தவும்.

முடிவெடுக்க முடியாத சூழலில், ஒரு பட்டியலை எழுதவும். உங்களுக்குத் தேவையான வசதிகளைப் பெற Flask-ல் நீங்கள் நிறுவ வேண்டிய அனைத்து package-களையும் பட்டியலிடுங்கள். அந்தப் பட்டியலில் ஒரு ORM மற்றும் migration tool இருந்தால், நீங்கள் ஏற்கனவே Django-வை தேர்வு செய்துவிட்டீர்கள் என்று அர்த்தம்; அதை மெதுவாக அடைவதற்கு நீங்கள் கூடுதல் உழைப்பைச் செலவிடுகிறீர்கள்.

குறைந்த திறன் கொண்ட வன்பொருளில் (small hardware) Flask-க்கு சாதகமான ஒரு சூழல் உள்ளது: ஒரே server-ல் பல சிறிய சேவைகளை இயக்குவது. ஒவ்வொரு Flask சேவையும் அதன் சொந்த unit-ன் கீழ் இயங்கும் ஒரு மலிவான process ஆகும். 1 GB VPS-ல் மூன்று Django தளங்களை இயக்குவது என்பது, framework-ன் மூன்று பிரதிகளை ஒரே நேரத்தில் நினைவகத்தில் வைத்திருப்பதைக் குறிக்கும்; அப்போது மேலே சொன்ன கணக்கீடு பலனளிக்காது. வன்பொருள் திறன் பற்றாக்குறையாக இருந்தால், ஒரு பெரிய திட்டத்திற்கு மாறுவதே சரியான தீர்வாகும். ஒரு VPS-ன் மாதந்திர கட்டணம் எவ்வளவு என்பது, ஏற்கனவே இயங்கும் ஒரு செயலியை மீண்டும் எழுதுவதை விட எளிமையான விவாதமாகும்.

நீங்கள் காணக்கூடிய சரங்களுடன் தோல்வி முறைகள்

Workers மறைந்து மீண்டும் வருகின்றன. Gunicorn [ERROR] Worker (pid:1234) was sent SIGKILL! Perhaps out of memory?-ஐ அச்சிடுகிறது. ஒரு worker தனது timeout heartbeat-ஐத் தவறவிட்டபோது அதை நீக்கும்போதும், kernel அந்த process-ஐ நீக்கும்போதும் இது நிகழ்கிறது. dmesg -T | grep -i "killed process" மூலம் இரண்டிற்கும் உள்ள வித்தியாசத்தைக் கண்டறியலாம். அங்கு ஒரு வரி இருந்தால், அது நினைவகப் பற்றாக்குறையைக் குறிக்கிறது; எனவே worker எண்ணிக்கையைக் குறைக்கவும் அல்லது swap-ஐச் சேர்க்கவும்.

ஒவ்வொரு பக்கமும் 400 பிழையைத் தருகிறது மற்றும் பதிவில் Invalid HTTP_HOST header என்று உள்ளது. முழுமையான செய்தி Invalid HTTP_HOST header: 'example.com'. You may need to add 'example.com' to ALLOWED_HOSTS. ஆகும். உங்கள் குறியீட்டை அடையும் முன்பே Django கோரிக்கையை நிராகரிக்கிறது, ஏனெனில் ALLOWED_HOSTS காலியாக உள்ளது அல்லது Host-ல் proxy அனுப்பிய பெயரை அது கொண்டிருக்கவில்லை.

படிவங்கள் Origin checking failed பிழையுடன் தோல்வியடைகின்றன. CSRF சரிபார்ப்பு தோல்வியடைந்ததாகப் பக்கம் காட்டுகிறது. TLS termination செய்யும் proxy-க்கு பின்னால் இது நிகழ்கிறது: application சாதாரண HTTP-ஐப் பார்க்கிறது, ஒரு http:// origin-ஐ உருவாக்குகிறது, மேலும் https:// வழியாக வந்த கோரிக்கையுடன் அதை ஒப்பிடுகிறது. SECURE_PROXY_SSL_HEADER மற்றும் CSRF_TRUSTED_ORIGINS ஆகியவற்றை அமைக்கவும், மேலும் proxy உண்மையில் X-Forwarded-Proto-ஐ அனுப்புகிறதா என்பதை உறுதிப்படுத்தவும்.

nginx உடனடியாக 502 பிழையைத் தருகிறது. பிழைப் பதிவேடு அதற்கான காரணத்தைக் குறிப்பிடுகிறது: connect() to unix:/run/site1/gunicorn.sock failed (2: No such file or directory) என்பது unit இயங்கவில்லை என்று பொருள், (13: Permission denied) என்பது socket உள்ளது ஆனால் nginx-ஆல் அதைத் திறக்க முடியவில்லை என்று பொருள், இது umask மற்றும் group அமைப்பால் ஏற்படுகிறது.

நிர்வாகப் பக்கத்தில் (admin) வடிவமைப்பு இல்லை. collectstatic இயக்கப்படவில்லை, அல்லது alias பாதை STATIC_ROOT-உடன் பொருந்தவில்லை. அணுகல் பதிவேடு (access log) /static/admin/-ன் கீழ் 404 பிழைகளைக் காட்டுகிறது.

குறைந்த சுமையின் கீழ் எழுதும் செயல்பாடுகள் (writes) தோல்வியடைகின்றன. SQLite-லிருந்து வரும் database is locked என்பது WAL முடக்கப்பட்டுள்ளது அல்லது ஒரே நேரத்தில் இரண்டு workers எழுதும் போது busy timeout மிகக் குறைவாக உள்ளது என்று பொருள்.

FAQ

1 GB VPS-க்கு Django மிக அதிக சுமையா?

இல்லை. குறைவான workers, முன்னால் Nginx மற்றும் பின்னால் SQLite கொண்டு Django-வை 1 GB-ல் தாராளமாக இயக்கலாம். PostgreSQL-ஐ அதன் இயல்புநிலை அமைப்புகளுடன், ஒரு cache, background worker மற்றும் Docker ஆகியவற்றை ஒரே server-ல் சேர்க்கும்போதுதான் நினைவகப் பற்றாக்குறை ஏற்படும். ஒரு worker-ன் proportional set size-ஐக் கணக்கிட்டு, கோரிக்கைகள் அதிகரிக்கும் நேரத்தைக் கருத்தில் கொண்டு அதை இருமடங்காக்கி, operating system மற்றும் database-க்குச் சென்றது போக மீதமுள்ள நினைவகத்துடன் ஒப்பிட்டுப் பார்க்கவும்.

ஒரு vCPU-ல் எத்தனை gunicorn workers-ஐ இயக்க வேண்டும்?

மூன்று workers-ல் தொடங்கிச் சோதிக்கவும். சிறிய VPS-களில் நினைவகமே முக்கியத் தடையாக இருக்கும். எனவே, operating system மற்றும் database-க்குச் சென்றது போக மீதமுள்ள RAM-ஐ, ஒரு worker-ன் proportional set size-ஐப் போல இருமடங்கு மதிப்பால் வகுக்கவும். உங்கள் views பெரும்பாலும் database அல்லது upstream API-க்காகக் காத்திருந்தால், gthread worker class-க்கு மாறவும். இதில் குறைவான workers மற்றும் பல threads-ஐப் பயன்படுத்தலாம். ஏனெனில், threads ஒரே framework நகலைப் பகிர்ந்துகொள்வதால், கூடுதல் processes-ஐ விட மிகக் குறைந்த நினைவகத்தையே எடுத்துக்கொள்ளும்.

எனக்கு PostgreSQL தேவையா அல்லது SQLite போதுமா?

குறைவான எழுதும் வேகத்தைக் கொண்ட ஒரு application server-க்கு SQLite போதுமானது. இது ஒரு தனி daemon-ஐ நினைவகத்திலிருந்து நீக்குவதால் சுமை குறையும். Write ahead logging-ஐ enable செய்து, busy timeout-ஐ அமைக்கவும்; இல்லையெனில், ஒரே நேரத்தில் நடக்கும் எழுதும் செயல்பாடுகள் database is locked பிழையுடன் தோல்வியடையும். ஒன்றுக்கும் மேற்பட்ட machines தரவுகளை எழுத வேண்டியிருந்தாலோ, அல்லது SQLite-ல் இல்லாத கூடுதல் வசதிகள் (எ.கா: அதிகப்படியான எழுதும் செயல்பாடுகள் அல்லது per-role access control) தேவைப்பட்டாலோ PostgreSQL-க்கு மாறவும்.

நான் gunicorn-க்கு பதிலாக uvicorn-ஐப் பயன்படுத்த வேண்டுமா?

உங்களிடம் async views இருந்து, அவை எதற்காவது காத்திருக்க வேண்டியிருந்தால் மட்டுமே இதைப் பயன்படுத்தவும். Flask ஒரு WSGI application என்பதால், ஒரு async view என்பது worker thread-க்குள் ஒரு புதிய event loop-ல் இயங்கி, அடுத்த கோரிக்கை வருவதற்கு முன்பே முடிந்துவிடும்; இது கூடுதல் concurrency-ஐத் தராது. Django async views-க்கு ASGI server கட்டாயம் தேவை. சமீபத்திய uvicorn releases-ல் அவற்றின் gunicorn worker class தனி package-ஆக மாற்றப்பட்டுள்ளது. எனவே, பழைய tutorial-களில் உள்ள worker class flag-ஐப் பயன்படுத்தாமல், தற்போதைய uvicorn ஆவணங்களைப் படிக்கவும்.

traceback ஏதுமின்றி எனது worker ஏன் மறைந்துவிட்டது?

நினைவகம் தீர்ந்துபோனதால் kernel-ஆல் கொல்லப்படும் (out of memory killer) ஒரு process, SIGKILL சிக்னலைப் பெறும். அது வெளியேறும்போது எதையும் log செய்ய முடியாது, எனவே உங்கள் application log திடீரென நின்றுவிடும். இந்த இடைவெளியைக் கவனிக்கும் Gunicorn, Worker (pid:1234) was sent SIGKILL! Perhaps out of memory?-ஐ அச்சிடும். இதை dmesg -T | grep -i "killed process" மூலம் உறுதிப்படுத்தவும். இதற்குத் தீர்வாக, workers எண்ணிக்கையைக் குறைக்கவும் அல்லது swapfile-ஐ உருவாக்கவும். இது நினைவகப் பயன்பாடு அதிகரிக்கும்போது process-ஐக் கொல்லாமல், கோரிக்கையை மெதுவாகச் செயலாக்க உதவும்.

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