Несколько сайтов с одним IP: настройки с прокси-сервером и кешем прокси (flask, uwsgi, nginx)

Я хочу разрешить моему серверу nginx обслуживать несколько поддоменов. Каждый сайт обслуживается флягой + uwsgi, слушая собственные порты.

Все сайты имеют много конечных точек с одинаковыми именами, а ответы кешируются в разных зонах: я хочу обслуживать правильный кеш (или правильный сайт) с прокси-сервера.

Я прочитал https://askubuntu.com/questions/766352/multiple-websites-on-nginx-one-ip : в моей конфигурации домен2 перенаправляется на домен1. Я не могу найти правильную конфигурацию для прослушивания uwsgi и заставить прокси-сервер обслуживать правильный сайт.

Как правильно настроить порты и proxy_cache на proxy_server, чтобы позволить nginx обслуживать два флажковых сайта с одного сервера?

Ниже приведена моя текущая установка:

configuration domain_1
server {        
    server_name www.domain1.com;
    return 301 $scheme://domain1.com$request_uri;
}

server {
    listen 8000 default_server;
    server_name domain1.com;

    root /var/www/example_site_1;

    # common locations for all sites
    location / {
        include uwsgi_params;
        uwsgi_pass unix:/var/www/example_site_1/domain1.sock;
    }

    # API
    location /api {                     
        include uwsgi_params;
        uwsgi_param UWSGI_SCRIPT wsgi;
        uwsgi_pass unix:/var/www/example_site_1/domain1.sock;
    }
}



# Set cache directory for site

proxy_cache_path /tmp/nginx/domain1 levels=1:2 keys_zone=my_zone_domain_1:10m max_size=50m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";


# Virtualhost/server configuration
server {
    listen  80  default_server;
    server_name domain1;

    root /var/www/domain1;

    ## how to serve proxy_cache if locations of domain_1 and domain_2 are the same ?

    location / {        
        proxy_cache my_zone_domain_1;    
        add_header X-Proxy-Cache $upstream_cache_status;
        include proxy_params;
        proxy_pass http://domain1.com:8000;
    }

    location /api {
        add_header X-Proxy-Cache $upstream_cache_status;
        proxy_cache my_zone_domain_1;
        proxy_pass http://domain1.com:8000/api;
    }

}
configuration domain_2
server {        
    server_name www.domain2.com;
    return 301 $scheme://domain2.com$request_uri;
}

server {
    listen 3000;
    server_name domain2.com;

    root /var/www/example_site_2;

    # common locations for all sites
    location / {
        include uwsgi_params;
        uwsgi_pass unix:/var/www/example_site_2/domain2.sock;
    }

    # API
    location /api {                     
        include uwsgi_params;
        uwsgi_param UWSGI_SCRIPT wsgi;
        uwsgi_pass unix:/var/www/example_site_2/domain2.sock;
    }
}



# Set cache directory for site

proxy_cache_path /tmp/nginx/domain2 levels=1:2 keys_zone=my_zone_domain_2:10m max_size=50m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";


# Virtualhost/server configuration
server {

    # I tried listening on other ports than 80, but kept having redirects on domain_1     

    listen  80;
    server_name domain2;

    root /var/www/domain2;

    ## how to serve proxy_cache if locations of domain_1 and domain_2 are the same ?

    location / {        
        proxy_cache my_zone_domain_2;    
        add_header X-Proxy-Cache $upstream_cache_status;
        include proxy_params;
        proxy_pass http://domain2.com:3000;
    }

    location /api {
        add_header X-Proxy-Cache $upstream_cache_status;
        proxy_cache my_zone_domain_2;
        proxy_pass http://domain2.com:3000/api;
    }

}

person user305883    schedule 31.05.2017    source источник


Ответы (2)


В вашей конфигурации domain_2 используется proxy_pass http://domain2.com:8000, но только сервер domain_1 прослушивает порт 8000, поэтому он может обслуживать запросы, направленные на domain_2.

Я также рекомендую вам переосмыслить использование proxy_pass в вашей конфигурации, на самом деле это не обязательно.

person AlexD    schedule 31.05.2017
comment
моя опечатка: proxy_pass для местоположения /api прослушивает две разные двери (3000 и 8000), но все равно перенаправляет домен_2 на домен_1. Не могли бы вы уточнить, как переосмыслить использование proxy_pass? Мой вариант использования — кэшировать GET API с ответом 200 для конечных точек, таких как domain.com/entity/one (без учета domain.com/entity?q=one), и избегать конфликтов между domain_1 и domain_2, поскольку API носит одно и то же имя. Хотите опубликовать пример? - person user305883; 31.05.2017
comment
Другая проблема с конфигурацией domain2 для порта 80 заключается в том, что server_name domain2; не будет соответствовать запросам к domain2.com, эти запросы будут обрабатываться разделом сервера с параметром server_name domain1 default_server;' as it has default_server`. Вам не нужен proxy_pass, так как вместо него вы можете использовать uwsgi_pass в разделе сервера, который прослушивает порт 80, просто используйте uwsgi_cache вместо proxy_cache. - person AlexD; 01.06.2017
comment
Не работает: я удалил default_server из конфигурации domain_1 в первом блоке сервера. Теперь server { listen 8000; server_name domain1; ... }, server { listen 3000; server_name domain2; ... } и server { listen 80; domain1; } и server { listen 80; domain2; } я пробовал также последний прослушивать порт 8080, но безуспешно: curl localhost:3000/api продолжает перенаправлять на порт 8000. - person user305883; 01.06.2017
comment
Ваша проблема в том, что domain2 != domain2.com - person AlexD; 01.06.2017
comment
спасибо за помощь, Алекс, я установил правильное расширение для server_names. Пробовал заставить серверные блоки для домена1 и домена2 слушать и 80 и 8080, и установить для каждого default_server как описано в руководстве: It is possible to define servers listening on ports *:80 and *:8080, and direct that one will be the default server for port *:8080, while the other will be the default for port *:80 но не вышло. Вы доступны для чата, чтобы помочь исправить это? - person user305883; 01.06.2017
comment
Давайте продолжим обсуждение в чате. - person user305883; 01.06.2017

Я обнаружил, что виновником был Uwsgi: он был загружен из папки usr/bin, а не из папки виртуальной среды моего приложения.

Возможно, папка virtualenv была повреждена: когда я пытался переустановить uwsgi (pip install uwsgi), он продолжал говорить, что требования удовлетворены, пока я не заметил, что which uwsgi не загружается из virtualenv.

Мне пришлось удалить и переустановить папку virtualenv с модулями uwsgi и python.

Теперь приложения запустились (ответ на вопрос), но в моем случае требуется дополнительная настройка конфигурации proxy_server.

Следующее может быть полезно для людей, использующих директивы url_for() в flask: директива url_for() указывает абсолютный путь, который может конфликтовать с прокси-сервером nginx.

Пример: прокси-сервер nginx прослушивает домены domains2.com на порту 80, местоположение proxy_pass /path в http://domain2.com:3000; если flask перенаправляет маршрут на /pathurl_for()), результирующий URL-адрес будет http://domain2.com:3000/path (поскольку он следует за портом, указанным в абсолютном пути) вместо http://domain2.com/path (URL-адрес прокси-сервера).

Добавьте proxy_set_header Host $http_host; в /path местоположение, чтобы позволить прокси-серверу nginx следовать правильному перенаправлению вашего приложения flask.

person user305883    schedule 07.06.2017