如何让nginx返回静态响应并将请求标头发送到应用程序?

时间:2011-12-04 08:10:20

标签: ruby nginx rack high-load

我正在通过将<img>标记嵌入网站来制作高负荷的网络统计系统。我想做的是:

  1. nginx从某个主机获取图像请求
  2. 它给出了从文件系统
  3. 托管小1px静态图像的答案
  4. 此时它以某种方式将请求的标头传输到应用程序并关闭与主机的连接
  5. 我正在使用Ruby,我将制作一个纯粹的Rack应用程序来获取标题并将它们放入队列中进行进一步计算。

    我无法解决的问题是,如何配置sphinx为Rack应用程序提供标头,并返回静态图像作为回复而无需等待Rack应用程序的响应?

    此外,如果有更常见的Ruby解决方案,则不需要Rack。

4 个答案:

答案 0 :(得分:2)

一个简单的选择是在继续后端进程时尽快终止客户端连接。

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 :(得分:2)

在这里阅读了关于post_action并阅读“通过Nginx的POST提供静态内容”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 :(得分:1)

你可以用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.
  }
}

答案 3 :(得分:0)

为什么不使用X-Accel-Redirecthttp://wiki.nginx.org/XSendfile,这样您就可以将请求转发到ruby应用程序,然后只需设置响应标头,nginx就会返回该文件。

更新,对于1x1px透明GIF文件,可能更容易将数据存储在变量中并直接将其返回给客户端(老实说它很小),所以我认为X-Accel-Redirect在这种情况下,这可能是一种矫枉过正。