Как я могу заставить nginx возвращать статический ответ и отправлять заголовки запросов в приложение? - PullRequest
5 голосов
/ 04 декабря 2011

Я создаю высоконагруженную систему веб-статистики путем встраивания тега <img> на сайт.Вот что я хочу сделать:

  1. nginx получает запрос на изображение с какого-либо хоста
  2. и выдает в качестве ответа хосту небольшое 1px статическое изображение из файловой системы
  3. в настоящее время он каким-то образом передает заголовки запроса в приложение и закрывает соединение с хостом

Я работаю с Ruby и собираюсь создать приложение на основе чистого Rack, чтобы получить заголовки и поместить их вочередь для дальнейших вычислений.

Проблема, которую я не могу решить, состоит в том, как настроить sphinx для предоставления заголовков приложению Rack и вернуть статическое изображение в качестве ответа, не ожидая ответа от приложения Rack?

Кроме того, Rack не требуется, если есть более распространенное Ruby-решение.

Ответы [ 4 ]

2 голосов
/ 26 января 2012

После прочтения здесь о post_action и прочтения "Обслуживание статического контента через POST из Nginx" http://invalidlogic.com/2011/04/12/serving-static-content-via-post-from-nginx/ Я сделал это, используя:

server {
  # this is to serve a 200.txt static file 
  listen 8888;
  root /usr/share/nginx/html/;
}
server {
  listen 8999;
  location / {
    rewrite ^ /200.txt break;
  }

  error_page 405 =200 @405;
  location @405 {
    # post_action, after this, do @post
    post_action @post;
    # this nginx serving a static file 200.txt
    proxy_method GET;
    proxy_pass http://127.0.0.1:8888;
  }

  location @post {
    # this will go to an apache-backend server.
    # it will take a long time to process this request
    proxy_method POST;
    proxy_pass http://127.0.0.1/$request_uri;
  }
}
2 голосов
/ 18 декабря 2011

Простой вариант - разорвать клиентское соединение как можно скорее, продолжая процесс бэкэнда.

server {
    location /test {
        # map 402 error to backend named location
        error_page 402 = @backend;

        # pass request to backend
        return 402;
    }

    location @backend {
        # close client connection after 1 second
        # Not bothering with sending gif
        send_timeout 1;

        # Pass the request to the backend.
        proxy_pass http://127.0.0.1:8080;
    }
}

Опция, приведенная выше, хотя простой может привести к клиенту, получающему ошибкусообщение, когда соединение разорвано.Директива ngx.say гарантирует, что заголовок «200 OK» будет отправлен и, поскольку это асинхронный вызов, не будет задерживать события.Для этого нужен модуль ngx_lua.

server {
    location /test {
        content_by_lua '
            -- send a dot to the user and transfer request to backend
            -- ngx.say is an async call so processing continues after without waiting
            ngx.say(".")
            res = ngx.location.capture("/backend")

        ';
    }

    location /backend {
        # named locations not allowed for ngx.location.capture
        # needs "internal" if not to be public
        internal;

        # Pass the request to the backend.
        proxy_pass http://127.0.0.1:8080;
    }

}

Более краткий вариант на основе Lua:

server {
    location /test {
        rewrite_by_lua '
            -- send a dot to the user
            ngx.say(".")

            -- exit rewrite_by_lua and continue the normal event loop
            ngx.exit(ngx.OK)
        ';
        proxy_pass http://127.0.0.1:8080;
    }
}

Определенно интересная задача.

1 голос
/ 04 декабря 2011

Вы можете сделать это с помощью post_action (я не совсем уверен, что это будет работать, но это единственное, о чем я могу думать)

server {
  location / {
    post_action @post;
    rewrite ^ /1px.gif break;
  }

  location @post {
    # Pass the request to the backend.
    proxy_pass http://backend$request_uri;

    # Using $request_uri with the proxy_pass will preserve the original request,
    # if you use (fastcgi|scgi|uwsgi)_pass, this would need to be changed.
    # I believe the original headers will automatically be preserved.
  }
}
0 голосов
/ 19 декабря 2011

Почему бы не использовать X-Accel-Redirect, http://wiki.nginx.org/XSendfile,, чтобы вы могли перенаправить запрос в приложение ruby, а затем просто установить заголовок ответа, и nginx вернет файл.

Обновление , хорошо для прозрачного GIF-файла размером 1x1px, вероятно, проще хранить данные в переменной и возвращать их клиенту напрямую (честно говоря, это очень мало), поэтому я думаю, что X-Accel-Redirect в этом случае, вероятно, является излишним.

...