前言
此前开发web后台都是用php(没有用任何框架)以及C++编写的CGI(是的你没有看错,奇葩的部门),哦还有我的启蒙语言Python+Django。
虽然我正在学习Golang的路上,Golang也可以用来做web开发,但同时我也知道开发web后台,论生态论社区论热度还是nodejs靠谱。Golang,我还是把它留在高并发系统吧。
Nodejs众所周知,自己就可以做成一个高性能的服务器,可以处理动态逻辑,也可以处理静态文件。然而在Web服务器领域,当前Nginx还是非常强势非常好用的,日志功能、ssl、虚拟域名等等的现有服务直接拿过来就能用,要对接nodejs也是比较简单的,所以还是选择用Nginx做web服务器。
本文记录一下使用Nginx配置转发中路径相关的问题。
示例
废话不多说,先来一段简单的node web服务代码:
var express = require('express')
var app = express()
app.get('/', function(req, res){
res.send('Hello world')
})
app.get('/node', function(req, res){
res.send('hello node')
})
app.get('/other', function(req, res){
res.send('hello other')
})
var server = app.listen(3000, function(){
var host = server.address().address
var port = server.address().port
console.log('Example app listening on http://%s:%d', host, port)
})
用的是express框架,监听3000端口,这里nodejs会处理三个路径,结果分别是:
/ - hello world
/node - hello node
/other - hello other
把服务起起来后,要做的就是用Nginx做服务器监听80端口,然后配置转发规则,将要交给node处理的请求转发到3000端口。
Nginx配置
Nginx端口转发的命令是proxy_pass,官方介绍参考这里。我们在location上下文中配置转发,但是要注意,转发的目标路径是关键。有的人说是跟结尾的斜杠有关系,其实没有那么复杂,看看官方解释:
If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive
If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:
什么叫With a URI呢?实际上这里的理解应该是不包含协议、域名和端口的,比如http://localhost:3000/node就是,因为它携带一个/node。
Without a URI
先来看这个配置,without a URI的情况
location /node/ {
proxy_pass http://localhost:3000;
}
此时,客户端访问的路径如果符合条件,比如/node、/node/node、/node/other等等,都会被转发到3000端口。那么此时Nodejs看到的访问路径是什么呢?根据上面的文档,路径的信息是passed to the server in the same form的,也就是说分别会出现这样的结果:
/node - hello node
/node/node - Cannot GET /node/node
/node/other - Cannot GET /node/other
是否已经明白发生了什么以及上面文档的第二段英文说了什么?Nginx会把匹配路径原封不动地加在localhost:3000后面。
With a URI
location /node/ {
proxy_pass http://localhost:3000/; #这里结尾加了一个斜杠
}
加了一个斜杠,变成With a URI,则proxy_pass配置的URI会取代location中匹配的路径,也就是本例中/会替换/node/。
所以同样的访问路径,此时的结果就不太一样了:
/node - hello world
/node/node - hello node
/node/other - hello other
这里有个需要注意的地方,文档中也有提到,就是不能在有正则匹配的location中用带URI的proxy_pass,因为这可能导致nginx不知道怎么做替换,比如
location ~ /node/ {
proxy_pass http://localhost:3000/;
}
加载配置的时候Nginx就会报错:
nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /usr/local/etc/nginx/nginx.conf:53
结尾
关于Nginx中的路径配置暂时就说到这,没有什么项目工程经验,所以可能一些的边界情况没涉及到,等以后项目实践遇到的时候再补充吧。
本文出处:http://www.amghost.cc/nginx-node-proxy_pass-setting/
参考:http://nginx.org/en/docs/http/ngx_http_proxy_module.html