39

我有一个返回 json 响应的 REST API。有时(而且似乎是完全随机的),json 响应在中途被切断。所以返回的 json 字符串看起来像:

...route_short_name":"135","route_long_name":"Secte // end of response

我很确定这不是编码问题,因为截止点不断改变位置,具体取决于返回的 json 字符串。我还没有找到会发生截断的特定响应大小(我看到 65kb 没有被截断,而 40kbs 会)。

当切断确实发生时查看响应标头:

{
    "Cache-Control" = "must-revalidate, private, max-age=0";
    Connection = "keep-alive";
    "Content-Type" = "application/json; charset=utf-8";
    Date = "Fri, 11 May 2012 19:58:36 GMT";
    Etag = "\"f36e55529c131f9c043b01e965e5f291\"";
    Server = "nginx/1.0.14";
    "Transfer-Encoding" = Identity;
    "X-Rack-Cache" = miss;
    "X-Runtime" = "0.739158";
    "X-UA-Compatible" = "IE=Edge,chrome=1";
}

也不按铃。任何人?

4

7 回答 7

37

我有同样的问题:

Nginx 切断了 FastCGI 后端的一些响应。例如,我无法从 PhpMyAdmin 生成正确的 SQL 备份。我检查了日志,发现了这个:

2012/10/15 02:28:14 [crit] 16443#0: *14534527 open() "/usr/local/nginx/fastcgi_temp/4/81/0000004814" 在读取上游时失败(13:权限被拒绝),客户端:*,服务器:,请求:“POST /HTTP/1.1”,上游:“fastcgi://127.0.0.1:9000”,主机:“", 引用者: "http://*/server_export.php?token=** "

我所要做的就是为/usr/local/nginx/fastcgi_temp文件夹提供适当的权限,以及client_body_temp.

固定的!

非常感谢samvermette,您的问答让我走上了正轨。

于 2012-10-15T00:43:56.500 回答
31

查看我的 nginxerror.log文件,发现以下内容:

13870 open() "/var/lib/nginx/tmp/proxy/9/00/0000000009" failed (13: Permission denied) while reading upstream...

看起来 nginx 的代理正在尝试将响应内容(由瘦传递)保存到文件中。仅当响应大小超过proxy_buffers(64 位平台上默认为 64kb)时才会这样做。所以最后这个错误我的请求响应大小有关。

我通过在我的 nginx 配置文件中设置proxy_buffering为来解决我的问题,而不是升级或修复文件权限问题。offproxy_buffers

仍然不确定 nginx 缓冲区的用途。如果有人能补充一下,我将不胜感激。完全禁用缓冲是一个坏主意吗?

于 2012-05-11T21:09:59.943 回答
15

我在切断服务器响应时遇到了类似的问题。

仅当我在返回响应之前添加 json 标头时才会发生这种情况header('Content-type: application/json');

在我的情况下gzip导致了这个问题。

gzip_types我通过在打开之前指定nginx.conf并添加到列表来解决它:application/jsongzip

gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json;
gzip on;
于 2014-01-09T17:34:16.593 回答
2

可能你的 inode 用完了,这会阻止 NginX 正确使用 fastcgi_temp 目录。

试试看df -i,如果你有 0% 的 inode 空闲,那就是个问题。

尝试find /tmp -mtime 10(超过 10 天)查看可能会填满磁盘的内容。

或者它可能是另一个包含太多文件的目录。例如,转到 /home/www-data/example.com 并计算文件:

find . -print | wc -l

于 2014-02-05T09:37:46.427 回答
2

感谢您的问题和出色的答案,它为我节省了很多时间。最后,克莱门特和山姆的回答帮助我解决了我的问题,所以功劳归他们所有。

只是想指出,在阅读了有关该主题的一些内容后,似乎不建议禁用proxy_buffering它,因为如果客户端(您系统的用户)的互联网连接不佳,它可能会使您的服务器停止运行。

我发现这个讨论对于了解更多信息非常有用。Francis Daly 的例子让我非常清楚:

也许将整个过程视为一个过程链更容易。

Web 浏览器通过 1 MB/s 链接与​​ nginx 对话。nginx 通过 100 MB/s 的链接与上游服务器对话。上游服务器向 nginx 返回 100 MB 的内容。nginx 将 100 MB 的内容返回到 Web 浏览器。

开启 proxy_buffering 后,nginx 可以保持整个 100 MB,因此 nginx-upstream 连接可以在 1 s 后关闭,然后 nginx 可以花 100 s 将内容发送到 Web 浏览器。

关闭 proxy_buffering 后,nginx 只能以 nginx 将内容发送到 Web 浏览器的相同速率从上游获取内容。

Web 浏览器并不关心差异——它仍然需要 100 秒才能获得全部内容。

nginx 不太关心差异——它仍然需要 100 秒才能将内容提供给浏览器,但它确实必须将与上游的连接保持打开额外的 99 秒。

上游确实关心差异——本来可以花 1 s 的东西实际上需要 100 s;对于额外的 99 秒,该上游服务器不服务任何其他请求。

通常:nginx-upstream 链接比 browser-nginx 链接快;而upstream比nginx更“重量级”;所以谨慎的做法是让上游尽快完成处理。

于 2016-01-27T13:53:26.247 回答
2

我们遇到了类似的问题。这是由我们的 REST 服务器(DropWizard)启用了 SO_LINGER 引起的。在负载下,DropWizard 在有机会刷新其缓冲区之前就断开了 NGINX。JSON 大于 8kb,前端会收到截断的数据。

于 2016-10-07T15:09:24.367 回答
0

我也遇到过这个问题——JSON解析客户端有问题,响应被切断或更糟,响应是陈旧的,并且是从一些随机内存缓冲区中读取的。

在阅读了一些指南之后——通过 POST 从 Nginx和Nginx 提供静态内容:在尝试配置 nginx 以提供简单文件时使用 POST 服务静态时修复为“405 Not Allowed” 。JSON

就我而言,我不得不使用:

max_ranges 0;

这样当 nginxAccept-Ranges: bytes在响应头中添加时浏览器不会得到任何有趣的想法)以及

sendfile off;

在我server为静态文件提供服务的代理块中。将它添加到location最终会为找到的JSON文件提供服务的块中没有帮助。

另一个提供 staticJSON的提示也不会忘记响应类型:

charset_types application/json;
default_type application/json;
charset utf-8;

其他搜索产生了文件夹权限问题——nginx 正在切断动态页面的末尾并缓存它或代理缓冲问题——通过 nginx 获取分块请求,但这不是我的情况。

于 2016-03-23T07:43:22.533 回答