CDN на коленке: Часть 2. Проксирующий веб-сервер

В предыдущей записи было рассмотрено создание geo dns, который отдает пользователю адрес наиболее близкого к нему сервера. Теперь поговорим о том как контент будет попадать на этот сервер и какими средствами он будет отдавать его пользователю.

Начнем с последнего. Так как нашей целью является отдача статического контента сайта, то вполне логично поручить это веб-серверу, например быстрому и не требующему много ресурсов Nginx.

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

Получив первый запрос на скачивание файла проксирующий сервер переправляет его на основной сервер, а после успешной обработки запроса этот файл попадает в локальный кэш. Остальные запросы на скачивание этого файла будут обрабатываться уже из локального кэша, без обращения к основному серверу. Кэширование является самым распространённым методом реализации CDN, поскольку позволяет максимально эффективно использовать узлы CDN, располагая на них не весь контент, а только наиболее востребованный.

От слов к делу, конфигурация проксирующего сервера Nginx:

proxy_cache_path /var/cache/nginx/static levels=1:2 keys_zone=static:32m inactive=1d max_size=1g;

upstream backend {
    server 192.168.0.1:80;
}

server {
        listen   80;

        server_name rascal.su www.rascal.su cdn.rascal.su;

        location / {
            proxy_pass http://backend;
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_buffer_size 16k;
            proxy_buffers 32 16k;
            proxy_cache off;
        }

        location ~* \.(jpg|jpeg|gif|png|ico|css|midi|wav|bmp|js|swf|flv|avi|djvu|mp3|xml|zip)$ {
            proxy_pass http://backend;
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_buffer_size 16k;
            proxy_buffers 32 16k;

            if ($request_uri ~* "\?[0-9]+$") {
                expires max;
                break;
            }

            proxy_cache static;
            proxy_cache_valid 1d;
            proxy_ignore_headers "Cache-Control" "Expires";
            proxy_cache_key "$uri$is_args$args";
            proxy_cache_lock on;
        }
}