Архивы по Категориям: man

Запускаем Django на uwsgi + nginx

Число проектов на сервере росло, а оперативная память не добавлялось так получилось что старый метод на большом числе проектов поедает много оперативной памяти. и вот пришло время разобраться с uwsgi – это WSGI сервер с некоторыми фенями, сам умеет пере запускаться когда обновляется код проекта (как в devserver) умеет сам убивать потомком если они начинают “тупить”.

Теперь по порядку
[cc lang=”bash”]aptitude install python-pip build-essential python-dev libxml2-dev
easy_install install uwsgi[/cc]

Для виртуал хоста используем примерно вот такой конфг, найденный на просторах тырнета

[cc lang=”bash”]
server {
listen 80;
listen 443;

# указываем свой домен
server_name odmin4eg.org www.odmin4eg.org;

# здесь мы задаем абсолютные пути к логам.
# как я упоминал уже выше, каталог с логами у меня хранится в каталоге
# с проектом, поэтому пути следующие:
access_log /home/odmin4eg.org/logs/nginx_access.log;
error_log /home/odmin4eg.org/logs/nginx_error.log;

# ниже указывается каталог с django-проектом. как я указывал выше,
# я храню его в подкаталоге www, поэтому путь такой:
root /home/odmin4eg.org/www/;

location /
{
# ниже надо указать путь к socket’у, при помощи которого
# nginx и uwsgi будут сообщаться.
# в данном случае путь это ‘/var/tmp/odmin4eg_uwsgi.sock’
uwsgi_pass unix:///var/tmp/odmin4eg_uwsgi.sock;
include uwsgi_params;

# 8 — число буфферов
# 128k — размер буфера
# фактически, мы сможем передать от Django в nginx только 1 мб информации.
# играйтесь с этим значением при поднятии своего проекта
uwsgi_buffers 8 128k;
}

# ниже описывается директория со статическими файлами проекта (css,js,etc)
# /static/ — это STATIC_URL, который вы должны посмотреть в
# в settings.py своего django проекта.
location /static/ {
# а вот здесь указываем абсолютный путь к директории со
# статическими файлами
alias /home/odmin4eg.org/www/static/;
expires 30d;
}
# Это уже у кого как статика для админки
location /media_admin {
alias /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media;
}

}[/cc]

Дальше конфигурируем uwsgi – создаём файл
/home/odmin4eg.org/www/uwsgi.yaml
[cc lang=”bash”]
uwsgi:
# указываем socket, при помощи которого будет происходить
# взаимодействие между nginx и uwsgi
socket: /var/tmp/odmin4eg_uwsgi.sock
# здесь указываем путь к django-проекту
pythonpath: /home/odmin4eg.org/www
# устанавливаем переменную окружения, которая хранит имя settings файла
env: DJANGO_SETTINGS_MODULE=settings
# это имя модуля, который будет запускаться на выполнение
# в такой постановке, будет запускаться wsgi.py из директории
# указанной выше в ‘pythonpath’
module: wsgi
# путь к лог файлу
daemonize: /home/odmin4eg.org/logs/uwsgi.log
# прочие настройки, значения который можно посмотреть на сайте uWSGI
max-requests: 5000
buffer-size: 32768
harakiri: 30
reload-mercy: 8
master: 1
no-orphans: 1
# если выполнить команду “touch <имя ниже указанного файла>“,
# то произойдет перезапуск uwsgi демона.
touch-reload: /home/odmin4eg.org/uwsgi[/cc]

ну и создаём файлик который будем пинать для перезагрузки демона
[cc lang=”bash”]touch /home/odmin4eg.org/uwsgi[/cc]

ну и последнее осталось написать wsgi.py и положить его в каталог указанный в pythonpath (i.g., в /home/odmin4eg.org/www). wsgi.py выглядит до безумия просто:

[cc lang=”python”]
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()[/cc]

запускаем
[cc lang=”bash”]
service nginx restart
uwsgi -y /home/odmin4eg.org/conf/uwsgi.yaml[/cc]

У меня всё поехало после этого.
по мативам kalnitsky.org

Запускаем django на nginx

Давным давно, я писал как установить nginx

там же в комментариях подсказали ещё способ
[cc lang=”bash”]
nginx=stable # use nginx=development for latest development version
add-apt-repository ppa:nginx/$nginx
apt-get update
apt-get install nginx[/cc]

получаем последний nginx.

Напомню, что у меня за nginx стоят разные “бэк-энды”
для самого нагруженного сайта я использую php5-fpm
для остальных сайтов я использую apache2
для Django проектов я использовал Apache2 + mod_python но его прожорливость, давала повод задуматься.

в итоге я искал способ освободить ресурсы занимаемые Индейцем.

Такой способ нашёлся 🙂

создаю конфигурационный файл хоста nginx.

[cc lang=”bash”]touch djangosite[/cc]

у меня они лежат в /etc/nginx/sites-available и уже от туда симлинками идут в /etc/nginx/sites-enabled

Конфигурационный файл такого содержания

[cc lang=”bash”]server {
listen 80;
server_name sitename.ru www.sitename.ru;

charset utf-8;

access_log /var/log/nginx/sitename-access.log;
error_log /var/log/nginx/sitename-error.log;
client_max_body_size 300m;

# Это, чтоб стили и статические файлы админки подгружались, проверьте у себя,
# в разных версиях Ubuntu могут быть разные версии Питона.
# ну и в настройках джанго проекта разумеется у нас тоже указан ADMIN_MEDIA как media_admin

location /media_admin {
alias /usr/lib/python2.5/site-packages/django/contrib/admin/media;
}
location / {
#Это как пример как мы запускаем джангоСервер
#python ./manage.py runfcgi method=prefork socket=/tmp/sitemane.sock pidfile=/tmp/sitename.pid
# Общаться будем по сокету, хотя можно и по 127.0.0.1:8000
fastcgi_pass unix:/tmp/sitename.sock;
#Ага и вот этот файлик не забудем создать, о нём ниже
include fastcgi_params_django;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
[/cc]

так же создаём файл

[cc lang=”bash”]touch /etc/nginx/fastcgi_params_django[/cc]

и в него вкладываем вот такие параметры

[cc lang=”bash”]
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;

fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;

fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PROTOCOL $server_protocol;

# PHP only, required if PHP was built with –enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
[/cc]

проверяем верность конфигурации
[cc lang=”bash”]nginx -t[/cc]
если всё ОК идём дальше.

проекты джанго у меня лежат в /home/django

Заходим в нужный нам проект и создадим там скрипт сервера.

[cc lang=”bash”]touch server.sh[/cc]
Вот с таким содержанием

[cc lang=”bash”]#!/bin/bash

case “$1” in
“start”)
#есть 2 варианта запуска сервера, по сети и через unix сокеты
# последний выигрывает по производительности
#python ./manage.py runfcgi method=prefork host=127.0.0.1 port=8000 pidfile=/tmp/sitename.pid
python ./manage.py runfcgi method=prefork socket=/tmp/sitename.sock pidfile=/tmp/sitename.pid
# не забываем, про то, что сокет у нас мог прочитать фронт-энд
# а nginx у меня работает с правами www-data
chown www-data:www-data /tmp/sitename.sock
;;
“stop”)
kill -9 `cat /tmp/sitemane.pid`
;;
“restart”)
$0 stop
sleep 1
$0 start
;;
*) echo “Usage: ./server.sh {start|stop|restart}”;;
esac
[/cc]

Вот и весь скрипт, не забываем только поменять sitename на имя вашего сайта, а то получится, что на один pid или сокет у вас будет ссылаться несколько серверов.

чтоб запустить сервер
[cc lang=”bash”]./server.sh start[/cc]

А вот он и не запустился ругается на Flup

[cc lang=”bash”]No module named flup[/cc]

нам понадобится пакет flup это питоновский пакет, поэтому его я устанавливаю вот так
[cc lang=”bash”]easy_install flup[/cc]
Можно попробовать поставить его из репозитория убунты
[cc lang=”bash”]apt-get install python-flup[/cc]
Но я так не пробовал 😉

Всё сервер запустился, можно перезапустить nginx для применения новой конфигурации

[cc lang=”bash”]/etc/init.d/nginx restart[/cc]

Всё готово, наш сервер запустился.

Теперь по хорошему добавить скрипт запуска сервера в автозагрузку.

squid на два внешних интерфейса

Начал я играться с сервером, у которого два внешних интерфейса, обязательно опишу чуть позже что и как делал, а то факт – забуду.

И так, что надо сделать для Squid чтоб  он использовал оба внешних канала.

Мне нужно было зарулить только определённый набор ИП адресов внутренней сети.

Объявим 2 списка, укажем в каждом диапазон ип адресов, которые куда будем отправлять.
[cc lang=”bash”]
acl provider1 src 10.0.0.0/24
acl provider2 src 16.0.0.0/24
[/cc]

Чуть ниже скажем что нам можно что не можно

[cc lang=”bash”]http_access allow provider1
http_access allow provider2[/cc]

И дальше
[cc lang=”bash”]
tcp_outgoing_address 10.1.0.1 provider1
tcp_outgoing_address 10.1.0.2 provider2
[/cc]
10.1.0.1 10.1.0.2 – это внешние адреса сервера с разными интерфейсами.

Собственно всё, после этого всё будет как нам хочется.

Связанные списки select в django (ajax select linked)


Потратив часа 3 на поиск рабочего решения связанных полей (Это когда в зависимости от категории нужно показывать под категорию) спешу поделиться чтоб не забыть

в urls.py

[cc lang=”python”](r’^ajax/categ/$’, ‘proj.list.views.feeds_subcat’),[/cc]

во Вьюхе
[cc lang=”python”]
def feeds_subcat(request):
from django.core import serializers
json_subcat = serializers.serialize(“json”, SubCategory.objects.filter(category_name=request.GET[‘id’]))
return HttpResponse(json_subcat, mimetype=”application/javascript”)[/cc]

Примерно рассказываю что там происходит
В модели SubCategory выбираем имя субкатегории, которая соответствует ид_категории, что к нам привалило.
всё это оборачиваем в JSON попутно подгружаем библиотеки для этих дел.
и отправляем прямо в формате js всё обратно.

теперь создаём ещё один js файл называем его как душе угодно (и не забываем подключить)
[cc lang=”html”][/cc]
[cc lang=”JavaScript”]
$(function(){
$(“select#id_categ”).change(function(){
$.getJSON(“/ajax/categ/”,{id:+$(this).val()}, function(j) {
var options = ‘‘;
for (var i = 0; i < j.length; i++) { options += '‘;
}
$(“#id_sub”).html(options);
$(“#id_sub option:first”).attr(‘selected’, ‘selected’);
$(“#id_sub”).attr(‘disabled’, false);
})
$(“#id_categ”).attr(‘selected’, ‘selected’);
})
})[/cc]

Что он делает?
находит элемент select с id = “id_categ”
При изменении которого вызывает функцию $.getJSON, которая долбится по урле /ajax/categ/ гет запросом и параметром ?id=то_что_выбрано
Если всё отлично выполняется функция j
Которая и меняет значение во втором селекте.
#id_categ – ИД_селекта категории
#id_sub – ИД_селекта подкатегории

django devserver статические файлы ( django devserver static files)

Во время разработки нужно чтоб статика обрабатывалась dev сервером, всякие файлы стилей js и т.п.

Для решения этой задачи я использую вот это:

urls.py
[cc lang=”python”](r’^static/(?P.*)$’, ‘django.views.static.serve’, {‘document_root’: ‘/home/django/list/static’}),[/cc]
в корне проекта создаю каталог static, в котором создаю подкаталоги js images style и т.п