目前我有以下用 Go 编写的 HTTP 服务器:
func main() {
http.HandleFunc("/", func(response http.ResponseWriter, request *http.Request) {
http.ServeFile(response, request, "/var/www/default/htdocs/index.html")
})
http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("/var/www/default/htdocs/public"))))
http.HandleFunc("/json", func(response http.ResponseWriter, request *http.Request) {
// serves a JSON response
})
http.HandleFunc("/socket", func(w http.ResponseWriter, r *http.Request) {
// replies to the WebSocket
})
http.ListenAndServe(":3000", nil)
}
我已经看到一些基准测试表明,当涉及到静态文件时,nginx 每秒可以处理更多的请求。gzip_static
nginx 的另一个有用特性是它可以透明地 gzip 响应,甚至可以使用模块提供预压缩文件。
理想情况下,我希望 nginx 为所有现有(静态)文件提供服务,并将不存在的所有内容代理到 Go:
location / {
try_files $uri $uri/ @go;
}
location @go {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $host;
}
不幸的是,nginx不喜欢上面的配置:
nginx:[emerg]“proxy_pass”不能在正则表达式给出的位置、命名位置、“if”语句或/etc/nginx/sites-enabled/default:23中的“limit_except”块中包含URI部分
在这一点上,我知道我有几个选择:
1) 放入proxy_pass
块location /
中
但这将代理所有内容,甚至是现有的(静态)文件。
2)在nginx中编写个人/json
和位置块/socket
但是如果我想在 Go 中添加更多的处理程序,我还必须相应地更新 nginx vhost。
3)重写Go代码并fastcgi_pass
在nginx中使用而不是proxy_pass
location @go {
fastcgi_pass 127.0.0.1:9000;
}
我还必须更改 Go 代码以使用,net/http/fcgi
而不是net/http
,问题是我不知道如何指定路径(/json
或/socket
)fcgi.Serve()
。
此外,FastCGI 似乎比 HTTP 慢 4 倍:https ://gist.github.com/hgfischer/7965620 。
4)完全丢弃nginx
让 Go 服务所有内容(包括静态文件)并处理每个请求的 gzip 压缩。
我怎样才能让 nginx 和 Go 表现得像我想要的那样(最好使用 HTTP 接口)?
抱歉,如果这个问题太基础,这是我编写 Go 网络应用程序的第一次体验。
附加问题
在 PHP 中,我指向fastcgi_pass
Unixphp-fpm
套接字。如果任何请求遇到PHP 致命错误,仍会处理即将到来的请求。但是,如果我的 Go 代码调用panic()
程序将终止并且服务将停止响应。在 Go 中处理这个问题的最佳方法是什么?
“proxy_pass”的问题似乎是因为尾随
/
,尝试删除它,因为它没有任何作用。如果您需要在将 URI 传递给代理之前更改它,请尝试使用重写,即删除 URI 的某些部分,请尝试以下操作:我使用了以下 nginx 配置 -资源
下面是我的目录结构:
根据这个网站,我运行了一个简单的 sinatra 应用程序:
这就是回应
如您所见,如果文件不存在,请求将发送到 sinatra 应用程序。