Ubuntu 16.04 上的 Nginx + Docker + DotNet 应用程序请求超时

Ubuntu 16.04 上的 Nginx + Docker + DotNet 应用程序请求超时

我在 Digital Ocean 上有一个带有 Docker 的 Ubuntu 16.04 环境,并且正在使用 docker-compose 启动服务:

version: '2'
services:
  cis-api:
    image: docker.myserver.com/cis-api:latest
    ports:
      - 8080:5000
    environment:
      DB_CONN_STRING: 'Server=tcp:...;Initial Catalog=cis-stage;Persist Security Info=False;User ID=...;Password=...;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;'

然后我安装了 vanilla Nginx,里面有一个配置/etc/nginx/conf.d

upstream cis-api {
  server 0.0.0.0:8080;
}

server {
  listen 80;
  server_name cis-api.myserver.com;

  location / {
    proxy_pass                          http://cis-api;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}

当我尝试绕过 nginx 请求 URL 时,一切正常:

root@cis-stage:/etc/nginx# curl localhost:8080/businesses -H 'Authorization: Bearer ...'
[{"id":1,...,"email":null}]

但是,如果我尝试通过 nginx 执行完全相同的请求,连接就会挂起,或者如果我设置了 30 秒的超时,它就会超时:

root@cis-stage:/etc/nginx# curl --max-time 30 --connect-timeout 30 http://cis-api.mysever.com/businesses -H 'Authorization: Bearer ....'

curl: (28) Operation timed out after 30000 milliseconds with 0 bytes received

该应用程序是用 ASP.Net Core 1.1 编写的,这是我绕过 nginx 运行它时的输出差异:

cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[1]
cis-api_1  |       Connection id "0HL3OL7D1CF19" started.
cis-api_1  | info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
cis-api_1  |       Request starting HTTP/1.1 GET http://localhost:8080/businesses
cis-api_1  | info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[2]
cis-api_1  |       Successfully validated the token.
cis-api_1  | info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[3]
cis-api_1  |       HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
cis-api_1  | info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
cis-api_1  |       Request finished in 414.6261ms 200 application/json; charset=utf-8
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[6]
cis-api_1  |       Connection id "0HL3OL7D1CF19" received FIN.
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[9]
cis-api_1  |       Connection id "0HL3OL7D1CF19" completed keep alive response.
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[10]
cis-api_1  |       Connection id "0HL3OL7D1CF19" disconnecting.
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[7]
cis-api_1  |       Connection id "0HL3OL7D1CF19" sending FIN.
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[8]
cis-api_1  |       Connection id "0HL3OL7D1CF19" sent FIN with status "0".
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[2]
cis-api_1  |       Connection id "0HL3OL7D1CF19" stopped.

当我使用 nginx 作为代理运行时:

cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[1]
cis-api_1  |       Connection id "0HL3OL7D1CF1B" started.
cis-api_1  | info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
cis-api_1  |       Request starting HTTP/1.0 GET http://cis-api.myserver.com/businesses
cis-api_1  | info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[2]
cis-api_1  |       Successfully validated the token.
cis-api_1  | info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[3]
cis-api_1  |       HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.

它会挂起在这里,直到请求超时,然后:

cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[6]
cis-api_1  |       Connection id "0HL3OLAD6F4QN" received FIN.
cis-api_1  | info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
cis-api_1  |       Request finished in 4615.4522ms 200 application/json; charset=utf-8
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[10]
cis-api_1  |       Connection id "0HL3OLAD6F4QN" disconnecting.
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[7]
cis-api_1  |       Connection id "0HL3OLAD6F4QN" sending FIN.
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[8]
cis-api_1  |       Connection id "0HL3OLAD6F4QN" sent FIN with status "-107".
cis-api_1  | dbug: Microsoft.AspNetCore.Server.Kestrel[2]
cis-api_1  |       Connection id "0HL3OLAD6F4QN" stopped.

有任何想法吗?

答案1

经过大量研究,我在这里找到了答案:

https://github.com/aspnet/KestrelHttpServer/issues/468#issuecomment-165951249

通过更改 nginx 配置文件以添加新的代理标头,问题得到了解决:

proxy_set_header  Connection        keep-alive;

新的location区块变为:

  location / {
    proxy_pass                          http://cis-api;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_set_header  Connection        keep-alive;
    proxy_read_timeout                  900;
  }

现在一切都按预期进行

相关内容