Django Projesini Channels + Daphne + NGINX ile Deploying

Başlık konusuna takılmayalım, sonuçta benimde istemediğim bir durum. Bu yazıda Channels kullanan bir django projemizi dapne ile ayağa kaldıracağız. Tabi bu işlemleri yaparken python’ın nimetlerinden yararlanmaya devam edeceğiz ve supervisor ile sistemimizi servis haline getireceğiz. Servis haline getirmemizin bir nedeni zamanlanmış işler için kullanacağımız Django-q kütüphanesini sistemden bağımsız bir şekilde başlatmamız gerekmektedir.

Django Q, Python ile çoklu işlemeyi kullanan yerel bir Django görev kuyruğu, zamanlayıcı ve çalışan uygulamasıdır.

Biz bu projeyi neden daphne ile ayağa kaldırıyoruz. Django ile uğraşan herkes gunicorn sözcüğünü duymuştur. Bizde django projelerimizi ilk ürünleştirme safasında projelerimizi gunicorn ile ayağa kaldırdık. Bu oldukça kolay ve hızlıydı! Çok geçmeden sistemimizde websocket isteklerinin çalışmadığına şahit olduk! Google amcaya sorduğumuzda bize tek bir çözüm yolu gösteriyordu… DAPHNE!

Peki neydi bu daphne? Daphne; Django Channels’ı güçlendirmek için geliştirilmiş ASGI(Asynchronous Server Gateway Interface) ve ASGI-HTTP için, HTTP ve HTTP2 protokol sunucusudur. Protokellerin otomatik anlaşmasını destekler.

Hazır ASGI’in lafı geçmişken bir kaç nokta hakkında dikkatimi çeken hususları sizlerle paylaşmak isterim. Bir kaç hintli youtuber dan gördüğüm kadarıyla daphne ve gunicorn’u birlikte kullanmaktadır. WSGI(Web Server Gateway Interface) dosyası ile gunicorn başlatılırken Daphne ile ASGI dosyası çalıştırılmaktadır. Fakat sizde bizim gibi websocket isteklerinizi django’nun portu ile kullanıyorsanız sadece DAPHNE ile sistemi ayağa kaldırmanız yeterli olacaktır.

KURULUM

Sistemimizin çalıştığı virtualenv ortam değişkenine daphne kütüphanesi yüklenir.

pip install daphne

Daphne ile projemizi ayağa kaldıracağımız için artık bize bir web sunucusu gerekmetedir. Bu iş için nginx’i kullanacağız. Servis haline getirmek içinse supervisor’u kullanacağız. Şimdi bu iki paketin yükleme işlemini gerçekleştirelim.

sudo apt install nginx supervisor

Django Projemizde asgi.py dosyasında bir kaç modifiye yapmamız gerekmektedir. Çünkü artık channels kütüpanesinin yönledirmesini kullanacağız!

import os
import django
from channels.routing import get_default_application
from django.core.asgi import get_asgi_application
os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’, ‘mydjango.settings’)
django.setup()
application = get_default_application()

Şimdi static dosyaları ve websocket isteklerini nginx tarafından yönledirilmesini sağlamak için nginx in konfigurasyonunu yapalım.

Ben nginx sunucusun default ayarlarını bozmamak için kendi konfigurasyon dosyamı oluşturuyorum. Daha sonra bu ayarları okumasını sağlayacağım siz isterseniz varsayılan dosya üzerinde değişiklik yapabilirsiniz.

sudo nano /etc/nginx/sites-enabled/mydjango
map $http_upgrade $connection_upgrade{
default upgrade;
'' close;
}
upstream channels-backend {
server 0.0.0.0:8000;
}
server {
server_name localhost;
access_log off;
location / {
include proxy_params;
proxy_pass http://unix:/tmp/mydjango.sock;
}
location /static/ {
alias /opt/mydjango/static/;
}
location /ws/ {
proxy_pass http://channels-backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

Burayı kopyala yapıştır yapmadan önce durup bir düşünelim ben ne yapıyorum!! Static dosyalarınızın yerini doğru göstermeyi unutmayın!

Nginx sunucusunda ayarladığımız konfigürasyon dosyaları sistemde gösteriyoruz

sudo nano /etc/nginx/nginx.conf
include /etc/nginx/sites-enabled/mydjango;

Satırını ekleyip kaydediyoruz sunucuyu restart ediyoruz. Nginx de reload özelliği mevcut isterseniz restart etmeden ayarları okumasını sağlayabilirsiniz.

sudo systemctl restart nginx

Bu aşamadan sonra sistemi dapne ile başlatmak için systemd nin altına servis yazılabilir ama biz bir kere supervisor kullanacağız dedik…
Yukarıda supervisor yükleme işlemini gerçekleştirmiştik sistemimiz için supervisor conf oluşturuyoruz.

 sudo nano /etc/supervisor/conf.d/mydjango.conf
[program:mydjango]
socket=tcp://localhost:8000
directory=/opt/mydjango
command=/opt/venv/bin/python /opt/venv/bin/daphne -b 0.0.0.0 -p 8000 mydjango.asgi:application
numprocs=4
process_name=asgi%(process_num)d
autostart=true
autorestart=true
stdout_logfile=/opt/mydjango/asgi.log
redirect_stderr=true

command kısmında doğru ortam değişkenini gösterdiğinize emin olun!

django cluster için konfigurasyonlar;

 sudo nano /etc/supervisor/conf.d/qcluster.conf
[program:django-q]
directory=/opt/mydjango
command=/opt/venv/bin/python manage.py qcluster
Automatically start and recover processes
autostart=true
autorestart=true
Choose where you want your log to go
stdout_logfile=/opt/mydjango/cluster.log
redirect_stderr=true

Şimdi supervisor deki yaptığımız değişikleri sistemi update ettikten sonra ayağa kaldıralım…


sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status all


Şimdi servisleri ayağa kaldırıyoruz


sudo supervisorctl start all

SONUÇ

Daphne, öncelikle Django channels’ı desteklemek için geliştirildiğini söylemiştik, yani HTTP / HTTP2 Protokollerini, WebSocketlerini, Sohbet Protokollerini, IoT Protokollerini ve daha fazlasını işleyebilir. Ancak, kararlılık ve performans açısından HTTP isteklerini sunmak için Gunicorn / uwsgi’yi ve kalan istekleri işlemek için Daphne’yi kullanmamızı öneriyor hintli youtuberlar. Bir türk atasözününde dediği gibi “çalışıyorsa dokunma” şimdilik bu ayarlarla devam…