我有 2 个 docker 容器:1 个 nginx (repro-nginx) 和 1 个 dotnet webapi,可产生“大响应”(repro-large-response) (73.7 kB)。
repro-nginx 部署在这里:https://repro-nginx.lemonsea-adf71d13.westeurope.azurecontainerapps.io/ 和 repro-large-response 部署在这里:https://repro-large-response.lemonsea -adf71d13.westeurope.azurecontainerapps.io/。 两者都部署在同一个容器应用程序环境中。 这意味着容器可以使用它们的服务名称相互通信。 理想情况下,repro-large-response 不会暴露给外界,这仅用于演示目的。
repro-nginx 配置如下: https://repro-nginx.lemonsea-adf71d13.westeurope.azurecontainerapps.io/:
上有 3 条路线问题: 每当您尝试 /repro-internal/ (https://repro-nginx.lemonsea-adf71d13.westeurope.azurecontainerapps.io/repro-internal/) 它有时会返回部分响应,您会看到总响应大小为 65.5 kB 与 73.7 kB,json 数据在某些时候被截断,并且在某些浏览器中错误代码为 NS_ERROR_NET_PARTIAL_TRANSFER。 其他外部端点没有这个问题。
我们创建了一个演示:
图像托管在 docker hub 上,您可以根据需要检查它们:
repro-nginx 配置:
cors-options.conf
proxy_hide_header Access-Control-Allow-Origin;
add_header 'Access-Control-Allow-Origin' $allow_origin;
add_header Vary Origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With';
cors-map.conf
map $http_origin $allow_origin {
default "";
}
/etc/nginx/conf.d/default.conf
include snippets/cors-map.conf;
server {
listen 80;
# server_name frontend;
# error_log /home/logs/error.log debug;
location / {
root /usr/share/nginx/html;
try_files $uri /index.html;
}
location /health {
access_log off;
error_log off;
add_header 'Content-Type' 'application/json';
return 200 '{"status":"UP"}';
}
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
client_max_body_size 500M;
client_body_buffer_size 500M;
client_body_timeout 300;
client_header_timeout 300;
keepalive_timeout 300;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
location /repro-internal/ {
include snippets/cors-options.conf;
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "Bearer null";
proxy_pass http://repro-large-response/;
proxy_http_version 1.1;
}
location /repro-external-http/ {
include snippets/cors-options.conf;
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "Bearer null";
proxy_pass http://repro-large-response.lemonsea-adf71d13.westeurope.azurecontainerapps.io/;
proxy_redirect off;
proxy_http_version 1.1;
}
location /repro-external-https/ {
include snippets/cors-options.conf;
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "Bearer null";
proxy_pass https://repro-large-response.lemonsea-adf71d13.westeurope.azurecontainerapps.io/;
proxy_redirect off;
proxy_http_version 1.1;
}
}
图像是使用 terraform 部署的,以下是部署计划的相关部分:
// Container app - repro-large-response
resource "azurerm_container_app" "repro-large-response" {
name = "repro-large-response"
container_app_environment_id = azurerm_container_app_environment.main.id
resource_group_name = azurerm_resource_group.main.name
revision_mode = "Single"
identity {
type = "SystemAssigned"
}
## Issue when deploying inmediately with ingress enabled
ingress {
external_enabled = true
target_port = 8080
allow_insecure_connections = true
traffic_weight {
percentage = 100
latest_revision = true
}
}
template {
min_replicas = 1
max_replicas = 1
container {
name = "repro-large-response"
image = "techorama2021cegeka/repro-large-response:3"
cpu = 0.25
memory = "0.5Gi"
}
}
tags = {
"container" = "repro-large-response"
}
}
// Container app - repro-nginx
resource "azurerm_container_app" "repro-nginx" {
name = "repro-nginx"
container_app_environment_id = azurerm_container_app_environment.main.id
resource_group_name = azurerm_resource_group.main.name
revision_mode = "Single"
identity {
type = "SystemAssigned"
}
## Issue when deploying inmediately with ingress enabled
ingress {
external_enabled = true
target_port = 80
allow_insecure_connections = false
traffic_weight {
percentage = 100
latest_revision = true
}
}
template {
min_replicas = 1
max_replicas = 1
container {
name = "repro-nginx"
image = "techorama2021cegeka/repro-nginx:4"
cpu = 0.25
memory = "0.5Gi"
}
}
tags = {
"container" = "repro-nginx"
}
}
如果您需要更多信息,请告诉我。
Azure 容器应用环境中 Nginx http 调用部分传输
Nginx 配置中的部分响应问题,尤其是在
/repro-internal/
路由上,似乎与 Nginx 的缓冲处理以及后端服务的 keepalive 设置有关。
由于使用外部路由(
/repro-external-http/
和/repro-external-https/
)时不存在该问题,因此表明内部网络或内部路由的特定配置可能是根本问题。
要解决 Nginx 设置中的部分响应问题,请尝试以下操作: 增加缓冲区大小(如
proxy_buffers
)以处理更大的响应。通过设置 proxy_set_header Connection "keep-alive";
,确保 Nginx 和 Dotnet 应用程序正确使用 keepalive 设置。
增强型 Nginx 配置示例
server {
listen 80;
location / {
root /usr/share/nginx/html;
try_files $uri /index.html;
}
location /health {
access_log off;
error_log off;
add_header 'Content-Type' 'application/json';
return 200 '{"status":"UP"}';
}
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
client_max_body_size 500M;
client_body_buffer_size 500M;
client_body_timeout 300;
client_header_timeout 300;
keepalive_timeout 650s;
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive"; # Ensuring keep-alive is used
proxy_buffer_size 512k;
proxy_buffers 16 512k;
proxy_busy_buffers_size 1m;
location /repro-internal/ {
include snippets/cors-options.conf;
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "Bearer null";
proxy_pass http://repro-large-response/;
}
location /repro-external-http/ {
include snippets/cors-options.conf;
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "Bearer null";
proxy_pass http://repro-large-response.lemonsea-adf71d13.westeurope.azurecontainerapps.io/;
proxy_redirect off;
}
location /repro-external-https/ {
include snippets/cors-options.conf;
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "Bearer null";
proxy_pass https://repro-large-response.lemonsea-adf71d13.westeurope.azurecontainerapps.io/;
proxy_redirect off;
}
}
我的示例地形配置:
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "main" {
name = "vksb-rg"
location = "East US2"
}
resource "azurerm_container_app_environment" "main" {
name = "testvk-container-app-env"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
# Configuration specific to your environment
}
resource "azurerm_container_app" "repro-large-response" {
name = "repro-large-response"
container_app_environment_id = azurerm_container_app_environment.main.id
resource_group_name = azurerm_resource_group.main.name
revision_mode = "Single"
identity {
type = "SystemAssigned"
}
ingress {
external_enabled = true
target_port = 8080
allow_insecure_connections = true
traffic_weight {
percentage = 100
latest_revision = true
}
}
template {
min_replicas = 1
max_replicas = 1
container {
name = "repro-large-response"
image = "techorama2021cegeka/repro-large-response:3"
cpu = 0.25
memory = "0.5Gi"
}
}
tags = {
"container" = "repro-large-response"
}
}
resource "azurerm_container_app" "repro-nginx" {
name = "repro-nginx"
container_app_environment_id = azurerm_container_app_environment.main.id
resource_group_name = azurerm_resource_group.main.name
revision_mode = "Single"
identity {
type = "SystemAssigned"
}
ingress {
external_enabled = true
target_port = 80
allow_insecure_connections = false
traffic_weight {
percentage = 100
latest_revision = true
}
}
template {
min_replicas = 1
max_replicas = 1
container {
name = "repro-nginx"
image = "techorama2021cegeka/repro-nginx:4"
cpu = 0.25
memory = "0.5Gi"
}
}
tags = {
"container" = "repro-nginx"
}
}
部署成功: