2015/1/14日, 在192.168.2.209环境, web端进行大文件(300-500M)上传时, nginx经常报错. 错误信息如下:
2015/01/15 03:53:29 [error] 4065#0: *3604 lua tcp socket write timed out while sending to client, client: 192.168.2.24, server: private.com, request: "POST /upload/single HTTP/1.1", host: "192.168.2.209", referrer: "http://192.168.2.209/os/home.html"
2015/01/15 03:53:29 [error] 4065#0: *3604 [lua] single_upload.lua:7: fail to invoke storage append_by_buff() ! err: storage send request error:timeout while sending to client, client: 192.168.2.24, server: private.com, request: "POST /upload/single HTTP/1.1", host: "192.168.2.209", referrer: "http://192.168.2.209/os/home.html"
经过分析, 错误可能是一下原因导致的:
- nginx.conf中配置的proxy_connect_timeout, proxy_read_timeout, proxy_send_tiemout
- upload.lua文件中指定大文件分块上传到fastdfs, 默认是20M一块, 是否太小了
- fastdfs.lua, fdfs storage lua socket在使用完成后, 会默认放到socket pool中, 通过调用set_keepalive(timeout, size)函数实现, 是否timeout时间设置太小了. 导致在使用该lua socket时, timeout过期了, 报
lua tcp socket write timed out
- 查看nginx lua的API 文档, 分析那些配置会影响到lua socket的timeout.
经过排查, 1,2,3这几个配置确实有问题, 可以优化的. 但改完后, 上传大文件还是报错. 以下是上面几点的优化配置:
- nginx.conf
proxy_connect_timeout 5;
proxy_read_timeout 60;
proxy_send_timeout 60;
- uploader.lua中分块修改:
默认最新分块是60M, 超过60M的文件, 按照60M一块上传到Fastdfs中
- fastdfs.lua set_keepalive(timeout, size)修改:
tracker:set_keepalive(0, 3)
storage:set_keepalive(0, 5)
- 根据官方文档说明,
socket:set_keepalive(timeout, size)
中参数timeout是指定该socket在socket pool中缓存的时间, size则是指定每一个nginx worker中该类socket pool的大小. 配置timeout为0则表示该socket永不过期, 减少因为timeout到期时, 如果该socket正在使用时出错的概率. > 在上传文件到fastdfs的应用中, 每次新创建的socket都会有如下提示:
Success to query storage! option: {host: 127.0.0.1, port: 22122}- 如果使用的是socket pool中的storage socket, 则不会有上面的日志提示.
- 如果使用的是缓存中的socket, 调用socket:connect()函数会使set_keepalive(timeout, size)中配置的timeout不起作用, 因为此时会将调用socket:close(), 然后重新建立连接
优化了这几点后, 大文件上传成功的概率更高了, 但还不是100%. 经过更加仔细的研究nginx lua关于socket的文档, 我推断问题是上面的第4点. 即lua socket的tcpsock:send() 报了超时错误(也就是write timeout了). 这一点我是从文档中看出来的, 以下是我修改后的fastdfs.lua和uploader.lua
tracker:set_timeout(60000) # 原来的是300
storage:set_timeout(60000) # 原来的3000
即现在connect, send, receive的timeout都是60s, 上传大文件全部成功了!
参考NGINX LUA文档
tcpsock:connect
tcpsock:send
tcpsock:set_timeout
tcpsock:set_keepalive
更新记录
- 2015/1/14, 问题发生, 解决, 记录