На нескольких серверах время от времени появляется новые файлы, при этом
заранее не известно на каком именно сервере появится новый файл. Клиенты в
случайном порядке попадают на все серверы.
Задача сделать так, чтоб клиенту всегда отдавался новый файл, даже если его нет
в момент запроса на сервере. Чтобы клиент не видел 404. rsync не подходит,
точнее он может использоваться как дополнение.
Предположим дано 3 физических сервера и они отдают одну и туже статику для
одного домена stat.domain.com. Серверов может быть больше, решение легко маcштабируется.
Введем дополнительные доменные имена для обращения к конкретному серверу:
stat.front-01.domain.com
stat.front-02.domain.com
stat.front-03.domain.com
Решение.
Решение будем строить на NGINX, используя proxy_pass + proxy_store.
Каждый сервер должен иметь 2 конфигурации с одинаковым корнем (root).
Первый блок конфигурации - "тупиковый", отвечает только по дополнительному
имени stat.front-XX.domain.com и если нет файла отдает 404.
Второй блок конфигурации - "проксирующий", обращаются клиенты по имени хоста
stat.domain.com, и если файл не найден он будет искать на других серверах.
Итого, имеем:
# тупиковый
server {
listen 80;
server_name stat.front-01.domain.com;
access_log off;
location / {
root /opt/www/stat.domain.com/;
}
}
# проксирующий
# может показаться что это решение, см. дальше.
server {
listen 80;
server_name stat.domain.com;
access_log off;
location / {
root /opt/www/stat.domain.com/;
try_files $uri @front-02 @front-03; # кроме front-01
}
location @front-02{
internal;
proxy_pass http://stat.front-02.domain.com; # забираем из "тупиковой" конфигурации
proxy_set_header Host stat.front-02.domain.com;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_temp_path /opt/www/tmp;
root /opt/www/stat.domain.com/;
break;
}
location @front-03{
internal;
proxy_pass http://stat.front-03.domain.com; # забираем из "тупиковой" конфигурации
proxy_set_header Host stat.front-03.domain.com;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_temp_path /opt/www/tmp;
root /opt/www/stat.domain.com/;
break;
}
}
здесь ключевым моментом является
try_files $uri @front-02 @front-03; # кроме front-01
Кажется что все ок, и будет работать красиво но вот в чем проблема:
try_files в аргументах может иметь кучу файлов и только 1 URL, так что это
конфигурация НЕ РАБОТАЕТ..
Посмотрим на директиву proxy_next_upstream.
Вот в итоге что получилось:
(блок конфигурации универсальный и подходит для всех фронтов)
# тупиковый
server {
listen 80;
server_name stat.stat.domain.com; #stat.front-01.domain.com - можно тоже добавить
access_log off;
location / {
root /opt/www/stat.domain.com/;
}
}
# проксирующий
upstream stat_backend {
# server stat.front-01.domain.com ; # себя комментируем
server stat.front-02.domain.com ;
server stat.front-03.domain.com ;
}
server {
listen 80;
server_name stat.domain.com;
access_log off;
location / {
root /opt/www/stat.domain.com/;
try_files $uri @front-stat;
}
location @front-stat{
internal;
proxy_pass http://stat_backend;
proxy_next_upstream http_404;
proxy_set_header Host stat.stat.domain.com;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_temp_path /opt/www/tmp;
root /opt/www/stat.domain.com;
break;
}
}
|