Nginx 做代理,如何实现先立即返回空内容并结束请求,然后后台再发请求到后端服务器?

2016-05-22 09:12:24 +08:00
 ZE3kr

有一个在自己服务器上的 Piwik 网页统计工具,服务器在纽约。日本已经有一个代理服务器,用作缓存。

统计原理就是发一个 GET 请求给 /piwik.php ,我想是当一个请求发送到 /piwik.php 的日本的代理服务器上时, nginx 立即响应这个请求,返回 204 空内容,然后再把这个请求发送给纽约,这个可以实现吗?

7224 次点击
所在节点    NGINX
18 条回复
pathletboy
2016-05-22 09:13:51 +08:00
当然可以,用 nginx_lua
gamexg
2016-05-22 09:14:00 +08:00
用 php 可以实现。
nginx 不清楚
ZE3kr
2016-05-22 09:21:15 +08:00
@pathletboy 请问是直接在 lua 里做请求吗? lua 如何实现先结束浏览器发出的请求然后再发请求?
littlepanzh
2016-05-22 10:51:47 +08:00
可以问问 @qgy18
他的博客统计就是服务端异步发的
https://imququ.com/post/summary-of-my-blog-optimization.html
canglaoshi
2016-05-22 11:11:39 +08:00
@littlepanzh 你的博客为毛那么快
buliugu
2016-05-22 11:16:45 +08:00
@canglaoshi 进去第一篇就说明了啊。。。大量优化
qgy18
2016-05-22 11:21:04 +08:00
@littlepanzh
其实只要让你的程序在 HTTP 响应结束之后还能运行就可以了。对于 Node.js 来说,天然就是这样的。例如这是我的服务端统计代码:

import { post } from 'request';

let ua = this.header('user-agent');

let data = {
v : '1',
t : 'pageview',
cid : u,
uip : ip
};

'dl,dt,dr,dp,ul,sd,sr,tid'
.split(',')
.forEach(name => data[name] = this.get(name));

let options = {
url : beaconURL,
form : data,
headers : {
'User-Agent' : ua
}
};

post(options); //这里是异步的

this.header('Cache-Control', 'no-cache');
this.status(204);
this.end();
littlepanzh
2016-05-22 11:26:34 +08:00
@qgy18 啊原来统计的请求是 nodejs 里面做的,那异步自然不是问题。我一直以为是 nginx 发的,所以感觉你用了什么其它黑科技~
qgy18
2016-05-22 11:29:13 +08:00
@littlepanzh
Nginx 中 proxy_pass 给统计收集地址也可以吧,实际上就是用反向代理加速。
littlepanzh
2016-05-22 11:31:52 +08:00
@qgy18
对,但是 proxy_pass 应该是同步的吧,没办法实现 lz 的要求了
qgy18
2016-05-22 11:35:26 +08:00
@littlepanzh
用 lua 在 Nginx 的 NGX_HTTP_LOG_PHASE 阶段异步发请求应该可以,不过我没试过。

还有一个办法:在 WEB 应用里生产日志,另外写一个后台程序去消费日志(发给第三方统计服务)。
littlepanzh
2016-05-22 11:43:20 +08:00
@qgy18
lua 楼上有人提到了~
读日志是个不错的主意
点赞~
Daniel65536
2016-05-22 15:27:44 +08:00
nginx 自带的功能就可以实现,具体是用 post_action 这个没有被非公开的功能。在 nginx 早期版本因为缺少线程池功能,用这个会堵塞 worker ,所以 nginx 的文档里都没有提到这个东西, 1.9.x 之后有了线程池,就可以比较安全地使用了。
https://darknode.in/network/nginx-google-analytics/ 介绍了在用户访问了页面之后让 nginx 向 ga 发送一个请求的方法,你这个需求参考下改改就好。
ZE3kr
2016-05-22 16:58:01 +08:00
@Daniel65536 竟然还有这个功能,现在非常好!

```
location @tracker {
internal;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_method GET;
proxy_pass http://backend;
proxy_set_header User-Agent $http_user_agent;
}

location /piwik.php {
post_action @tracker;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
return 204;
}

location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_hide_header Vary;
proxy_pass http://backend;
proxy_cache webserver;
}
```
soulteary
2016-05-22 17:43:03 +08:00
粗浅的做过公司统计服务的飘过。

方案一:直接使用 Nginx 之类的 proxy_pass 是最省事方案,就像你 #14L 做的那样。

---

方案二:使用脚本做接口代理,诸如 @qgy18 屈屈给的方案。这个方案适合直接使用三方服务的场景,后端分析代码可以定制程度有限,接触不到数据库,或者定制比较麻烦。

---

方案三:分析日志并导入统计应用数据库。适合不能保障网站和统计服务器连通性的情况,或者网站峰值访问略大,统计服务器有鸭梨,以及需要对统计数据做处理(清洗等)的场景。

---


如果喜欢折腾,可以使用方案二或者三,如果自己能操作统计应用 /数据库,完全可以使用定期同步和分析 log 并导入统计服务的方案。
xiaotianhu
2016-05-22 19:04:57 +08:00
php+ng 用 fastcgi_finish_request 在 index 里立马返回就可以了

http://rainyluo.net/post/php_echo_speedup
rrfeng
2016-05-22 19:08:57 +08:00
其实 openresty 里有大量的这种写法……

楼上有人说 post_action ,学习了!
klausgao
2016-05-23 06:56:08 +08:00
呃我感觉楼主和楼上的都想复杂了。
前端页面统计不过就是一个 post 的问题,页面访问的时候,前端直接 post 数据到统计服务器就 OK 了,干嘛要绕到后端来处理?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/280364

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX