2011-12-04 18 views
5

Estoy creando un sistema de estadísticas web de alta carga mediante la inserción de la etiqueta <img> en el sitio. Lo que quiero hacer es:¿Cómo puedo hacer que nginx devuelva una respuesta estática y envíe encabezados de solicitud a la aplicación?

  1. nginx consigue solicitud de una imagen de algunas de acogida
  2. se da como respuesta a acoger pequeña imagen estática 1px del sistema de archivos
  3. en este momento que de alguna manera transfiere cabeceras de solicitud de aplicación y cierra la conexión al host

Estoy trabajando con Ruby y voy a hacer una aplicación de Rack puro para obtener los encabezados y ponerlos en una cola para realizar más cálculos.

El problema que no puedo resolver es, ¿cómo puedo configurar sphinx para dar encabezados a la aplicación Rack, y devolver una imagen estática como la respuesta sin esperar una respuesta de la aplicación Rack?

Además, Rack no es necesario si hay una solución de Ruby más común.

+1

Esto no es realmente una respuesta a su pregunta _specific_, pero si usted don' Para encontrar otra solución, puede considerar registrar las solicitudes en un archivo y luego analizar ese archivo más tarde con Ruby –

+0

Brandon, gracias, esta solución es bastante interesante, pero me temo que es muy escalable. – sandrew

+0

¿Por qué necesita una respuesta inmediata del servidor?Me refiero a que el cliente está esperando una imagen GIF 1x1px transparente, por lo que para la experiencia del usuario final es imperceptible ... – lwe

Respuesta

1

Usted puede ser capaz de lograr esto con post_action (no estoy del todo seguro de que esto va a funcionar, pero es lo único que se me ocurre)

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

Lo hago con post_action. http://wiki.nginx.org/HttpEmptyGifModule es más rápido para servir un gif de 1x1. – greg

2

Una opción sencilla es poner fin a la conexión del cliente CUANTO ANTES mientras procede con el proceso de backend.

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; 
    } 
} 

La opción anterior, aunque simple, puede resultado en el cliente que recibe un mensaje de error cuando se interrumpe la conexión. La directiva ngx.say asegurará que se envíe un encabezado "200 OK" y, como es una llamada asincrónica, no mantendrá las cosas en alto. Esto necesita el módulo 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; 
    } 

} 

A más sucinta opción basada 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; 
    } 
} 

Sin duda un reto interesante.

0

Por qué no hacer uso de X-Accel-Redirect, http://wiki.nginx.org/XSendfile, por lo que puede reenviar la solicitud a su aplicación de ruby ​​y luego simplemente establecer un encabezado de respuesta y nginx devuelve el archivo.

actualización, bien para un GIF transparente 1x1px archivo es probable que sea más fácil de almacenar los datos en una variable y devolverlo al cliente directamente (la verdad es que es tan pequeño), por lo que creo X-Accel-redirección es probablemente una exageración en este caso.

2

Después de leer aquí sobre post_action y la lectura "Sirviendo contenido estático a través de Correos De Nginx" http://invalidlogic.com/2011/04/12/serving-static-content-via-post-from-nginx/ he logrado esto usando:

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; 
    } 
} 
Cuestiones relacionadas