在Varnish / Nginx服务器上部署node.js应用程序的最佳方式

我即将部署一个全新的node.js应用程序,我需要一些帮助来设置它。

我的设置现在的方式如下。

我已经在external_ip:80上运行了Varnish

我有Nginx在internal_ip:80上运行

两个都在80端口,一个内部端口,一个外部监听。

注意:node.js应用程序在WebSockets上运行

现在我有了我的新的node.js应用程序,它将在端口8080上侦听。

我可以清漆设置,它是在nginx和node.js前面。

Varnish必须将websocket代理到端口8080,但是静态文件(如css,js等)必须通过端口80到nignx。

Nginx不支持开箱即用的websockets,否则我会这样安装:

清漆 – > nignx – > node.js

刚刚设置了一个与您所描述的基本相同的项目,我将分享我的方法 – 不保证它是“最好的”,但它确实有效。

我的服务器堆栈是

  • 清漆(v3.0.2) – 所有接口,端口80
  • Nginx(v1.0.14) – 本地接口,端口81
  • Node.js(v0.6.13) – 本地接口,端口1337
  • 操作系统是CentOS 6.2(或类似的)

我的Node.js应用程序使用Websockets(sockets.io – v0.9.0)和Express(v2.5.8) – 并永久启动。 (同一个服务器也有其他的网站 – 主要是使用相同的Nginx和Varnish实例的PHP)。

我的方法的基本意图如下:

  • websocket和“常规”数据的单一公共端口/地址
  • 使用光油来caching一些资产
  • 直接从nginx提供(未caching)静态资产
  • 将“网页”的请求传递给nginx,并从代理传递给Node.js
  • 直接将Web套接字请求(从Varnish)传递给Node.js(绕过nginx)。

光油configuration – /etc/varnish/default.vcl:

 #Nginx - on port 81 backend default { .host = "127.0.0.1"; .port = "81"; .connect_timeout = 5s; .first_byte_timeout = 30s; .between_bytes_timeout = 60s; .max_connections = 800; } #Node.js - on port 1337 backend nodejs{ .host = "127.0.0.1"; .port = "1337"; .connect_timeout = 1s; .first_byte_timeout = 2s; .between_bytes_timeout = 60s; .max_connections = 800; } sub vcl_recv { set req.backend = default; #Keeping the IP addresses correct for my logs if (req.restarts == 0) { if (req.http.x-forwarded-for) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } } #remove port, if included, to normalize host set req.http.Host = regsub(req.http.Host, ":[0-9]+", ""); #Part of the standard Varnish config if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" && req.request != "OPTIONS" && req.request != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } if (req.request != "GET" && req.request != "HEAD") { /* We only deal with GET and HEAD by default */ return (pass); } #Taken from the Varnish help on dealing with Websockets - pipe directly to Node.js if (req.http.Upgrade ~ "(?i)websocket") { set req.backend = nodejs; return (pipe); } ###Removed some cookie manipulation and compression settings## if(req.http.Host ~"^(www\.)?example.com"){ #Removed some redirects and host normalization #Requests made to this path, even if XHR polling still benefit from piping - pass does not seem to work if (req.url ~ "^/socket.io/") { set req.backend = nodejs; return (pipe); } #I have a bunch of other sites which get included here, each in its own block }elseif (req.http.Host ~ "^(www\.)?othersite.tld"){ #... } #Part of the standard Varnish config if (req.http.Authorization || req.http.Cookie) { /* Not cacheable by default */ return (pass); } #Everything else, lookup return (lookup); } sub vcl_pipe { #Need to copy the upgrade for websockets to work if (req.http.upgrade) { set bereq.http.upgrade = req.http.upgrade; } set bereq.http.Connection = "close"; return (pipe); } #All other functions should be fine unmodified (for basic functionality - most of mine are altered to my purposes; I find that adding a grace period, in particular, helps. 

Nginxconfiguration – /etc/nginx/*/example.com.conf:

 server { listen *:81; server_name example.com www.example.com static.example.com; root /var/www/example.com/web; error_log /var/log/nginx/example.com/error.log info; access_log /var/log/nginx/example.com/access.log timed; #removed error page setup #home page location = / { proxy_pass http://node_js; } #everything else location / { try_files $uri $uri/ @proxy; } location @proxy{ proxy_pass http://node_js; } #removed some standard settings I use } upstream node_js { server 127.0.0.1:1337; server 127.0.0.1:1337; } 

对于proxy_pass声明的重复,我并不是特别的疯狂,但不幸的是,还没有find一个更清洁的select。 一种方法可能是使位置块明确指定静态文件扩展名,并将proxy_pass语句保留在任何位置块之外。

/etc/nginx/nginx.conf中的一些设置:

 set_real_ip_from 127.0.0.1; real_ip_header X-Forwarded-For; log_format timed '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '$request_time $upstream_response_time $pipe'; port_in_redirect off; 

在我的其他服务器模块和设置中,我也在我的nginxconfiguration中启用了gzip和keepalive。 (顺便说一句,我相信有一个Nginx的TCP模块,可以使用websockets – 但是,我喜欢使用'香草'版本的软件(及其相关的仓库),所以这不是我的select)。

此设置的以前版本导致与Varnishpipe道不寻常的“阻塞”的行为。 本质上,一旦build立了pipe道套接字连接,下一个请求将被延迟,直到pipe道超时(最多60秒)。 我还没有看到与此设置相同的情况 – 但会有兴趣知道你是否看到类似的行为。