1

我在通过 Nginx 提供分块传输编码时遇到了一些问题。

提供的数据来自通过 uwsgi 运行的烧瓶应用程序。这是 uwsgi 对 GET 请求的响应示例:

0000: 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
0010: 0a                                              .
<= Recv header, 28 bytes (0x1c)
0000: 54 72 61 6e 73 66 65 72 2d 45 6e 63 6f 64 69 6e Transfer-Encodin
0010: 67 3a 20 63 68 75 6e 6b 65 64 0d 0a             g: chunked..
<= Recv header, 32 bytes (0x20)
0000: 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 70 Content-Type: ap
0010: 70 6c 69 63 61 74 69 6f 6e 2f 6a 73 6f 6e 0d 0a plication/json..
<= Recv header, 32 bytes (0x20)
0000: 41 63 63 65 73 73 2d 43 6f 6e 74 72 6f 6c 2d 41 Access-Control-A
0010: 6c 6c 6f 77 2d 4f 72 69 67 69 6e 3a 20 2a 0d 0a llow-Origin: *..
<= Recv header, 75 bytes (0x4b)
0000: 41 63 63 65 73 73 2d 43 6f 6e 74 72 6f 6c 2d 41 Access-Control-A
0010: 6c 6c 6f 77 2d 48 65 61 64 65 72 73 3a 20 41 75 llow-Headers: Au
0020: 74 68 6f 72 69 7a 61 74 69 6f 6e 2c 20 43 6f 6e thorization, Con
0030: 74 65 6e 74 2d 54 79 70 65 2c 20 43 6f 6e 74 65 tent-Type, Conte
0040: 6e 74 2d 4c 65 6e 67 74 68 0d 0a                nt-Length..
<= Recv header, 80 bytes (0x50)
0000: 41 63 63 65 73 73 2d 43 6f 6e 74 72 6f 6c 2d 45 Access-Control-E
0010: 78 70 6f 73 65 2d 48 65 61 64 65 72 73 3a 20 20 xpose-Headers:  
0020: 57 57 57 2d 41 75 74 68 65 6e 74 69 63 61 74 65 WWW-Authenticate
0030: 2c 20 43 6f 6e 74 65 6e 74 2d 54 79 70 65 2c 20 , Content-Type, 
0040: 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 0d 0a Content-Length..
<= Recv header, 2 bytes (0x2)
0000: 0d 0a                                           ..
<= Recv data, 17 bytes (0x11)
0000: 63 0d 0a 7b 22 64 65 76 69 63 65 22 3a 20 5b 0d c..{"device": [.
...DATA...
01a0: 32 0d 0a 5d 0a 0d 0a 32 0d 0a 7d 0a 0d 0a       2..]...2..}...
<= Recv data, 5 bytes (0x5)
0000: 30 0d 0a 0d 0a                                  0....

然后此响应进入一个 unix 套接字,该套接字通过以下配置通过管道传输到 nginx:

server {
listen      80;
server_name  _;
client_max_body_size 4m;
chunked_transfer_encoding on;

location = /abc { rewrite ^ /abc/; }
location /abc { try_files $uri @abc; }
location @abc {
    include uwsgi_params;
uwsgi_param SCRIPT_NAME /abc;
    uwsgi_modifier1 30;
    uwsgi_pass unix:/path/to/socket.sock;
}

问题是 Nginx 实际上给出了这个响应:

<= Recv header, 17 bytes (0x11)
0000: 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
0010: 0a                                              .
== Info: Server nginx/1.4.6 (Ubuntu) is not blacklisted
<= Recv header, 30 bytes (0x1e)
0000: 53 65 72 76 65 72 3a 20 6e 67 69 6e 78 2f 31 2e Server: nginx/1.
0010: 34 2e 36 20 28 55 62 75 6e 74 75 29 0d 0a       4.6 (Ubuntu)..
<= Recv header, 37 bytes (0x25)
0000: 44 61 74 65 3a 20 54 75 65 2c 20 30 38 20 4a 75 Date: Tue, 08 Ju
0010: 6c 20 32 30 31 34 20 30 31 3a 30 32 3a 33 33 20 l 2014 01:02:33 
0020: 47 4d 54 0d 0a                                  GMT..
<= Recv header, 32 bytes (0x20)
0000: 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 70 Content-Type: ap
0010: 70 6c 69 63 61 74 69 6f 6e 2f 6a 73 6f 6e 0d 0a plication/json..
<= Recv header, 28 bytes (0x1c)
0000: 54 72 61 6e 73 66 65 72 2d 45 6e 63 6f 64 69 6e Transfer-Encodin
0010: 67 3a 20 63 68 75 6e 6b 65 64 0d 0a             g: chunked..
<= Recv header, 24 bytes (0x18)
0000: 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 6b 65 65 70 Connection: keep
0010: 2d 61 6c 69 76 65 0d 0a                         -alive..
<= Recv header, 32 bytes (0x20)
0000: 41 63 63 65 73 73 2d 43 6f 6e 74 72 6f 6c 2d 41 Access-Control-A
0010: 6c 6c 6f 77 2d 4f 72 69 67 69 6e 3a 20 2a 0d 0a llow-Origin: *..
<= Recv header, 75 bytes (0x4b)
0000: 41 63 63 65 73 73 2d 43 6f 6e 74 72 6f 6c 2d 41 Access-Control-A
0010: 6c 6c 6f 77 2d 48 65 61 64 65 72 73 3a 20 41 75 llow-Headers: Au
0020: 74 68 6f 72 69 7a 61 74 69 6f 6e 2c 20 43 6f 6e thorization, Con
0030: 74 65 6e 74 2d 54 79 70 65 2c 20 43 6f 6e 74 65 tent-Type, Conte
0040: 6e 74 2d 4c 65 6e 67 74 68 0d 0a                nt-Length..
<= Recv header, 79 bytes (0x4f)
0000: 41 63 63 65 73 73 2d 43 6f 6e 74 72 6f 6c 2d 45 Access-Control-E
0010: 78 70 6f 73 65 2d 48 65 61 64 65 72 73 3a 20 57 xpose-Headers: W
0020: 57 57 2d 41 75 74 68 65 6e 74 69 63 61 74 65 2c WW-Authenticate,
0030: 20 43 6f 6e 74 65 6e 74 2d 54 79 70 65 2c 20 43  Content-Type, C
0040: 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 0d 0a    ontent-Length..
<= Recv header, 2 bytes (0x2)
0000: 0d 0a                                           ..
<= Recv data, 926 bytes (0x39e)
0000: 33 39 32 0d 0a 63 0d 0a 7b 22 64 65 76 69 63 65 392..c..{"device
... DATA ...
0380: 0a 7d 0d 0a 32 0d 0a 5d 0a 0d 0a 32 0d 0a 7d 0a .}..2..]...2..}.
0390: 0d 0a 30 0d 0a 0d 0a 0d 0a 30 0d 0a 0d 0a       ..0......0....

所以它基本上把烧瓶应用程序生成的所有块放在一个大块中,他在分块传输编码中提供服务。

所有其他功能(基本 HTTP 1.0)都运行良好,所以我想知道这种行为的原因是什么。

tl;dr :NGINX 将一个块列表转换成一个大块,并将十六进制数字留在所服务的 json 数据的中间

4

1 回答 1

0

显然,这个问题与我遇到的问题相似。

我找到的解决方案是在 nginx 上启用传输编码

chunked_transfer_encoding on;

然后将数据包一个一个地流式传输到 nginx:它是传输编码分块的,没有十六进制大小标记和 CRLF。

发生的事情(我认为)是 nginx 在其一侧缓冲数据(通过它正在侦听的套接字)。这样,它可以防止您在 python/java 端溢出内存使用(我不会满足于 Python 或 Java 的内存效率)。

我期待任何更好的解决方案,但对于不是那么大/众多的查询(总共<50Mb),它适用于小型实例。我会用新的发现更新这个页面。

于 2014-11-11T00:21:43.973 回答