解决Nginx反向代理GRPC时Received RST_STREAM错误代码2的问题
Fixing Nginx gRPC Reverse Proxy Issue with Dialogflow StreamingDetectIntent
Looks like you're hitting a common pitfall when proxying bidirectional streaming gRPC calls through Nginx—especially with Google's Dialogflow API. Let's break down the problem and fix it step by step.
Root Cause
Your current config misses two critical pieces for bidirectional gRPC streams:
- Incorrect Host Header: When proxying to Dialogflow's API, Nginx is sending your own domain (
example.com) as theHostheader instead ofdialogflow.googleapis.com. Google's APIs rely on the correct Host header to route requests properly. - Missing HTTP/2 & gRPC Stream Configuration: Bidirectional streaming requires specific Nginx settings to maintain the stream lifecycle, plus you need to ensure your Nginx version is at least 1.13.10 (the first version that fully supports bidirectional gRPC streams).
Modified Nginx Configuration
Here's the adjusted config that should resolve the issue:
user nginx; worker_processes auto; # Use auto to leverage all CPU cores error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; multi_accept on; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 75; keepalive_requests 1000; # Increase for sustained streaming client_max_body_size 4000M; # Critical gRPC settings for streaming grpc_read_timeout 86400s; # 1 day, match your original but use explicit seconds grpc_send_timeout 86400s; grpc_buffer_size 16k; # Smaller buffer is better for streaming (16k is default, no need for 100M) grpc_next_upstream_tries 3; # Retry on transient errors # HTTP/2 settings optimized for gRPC http2_max_field_size 16k; http2_max_header_size 32k; http2_idle_timeout 86400s; http2_recv_timeout 86400s; include /etc/nginx/conf.d/*.conf; server { listen 443 ssl http2; server_name example.com; # Explicitly set your domain access_log /var/log/nginx/access_grpc.log main; location / { grpc_pass grpcs://dialogflow.googleapis.com:443; # Set correct Host header for Dialogflow API grpc_set_header Host dialogflow.googleapis.com; # Pass through other necessary headers (like authorization) grpc_set_header X-Real-IP $remote_addr; grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for; grpc_set_header X-Forwarded-Proto $scheme; } ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # Fixed typo here (exemple -> example) # SSL settings optimized for gRPC ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; } server { listen 80; listen [::]:80; server_name example.com; return 301 https://$host$request_uri; } }
Key Changes Explained
- Explicit Host Header: The
grpc_set_header Host dialogflow.googleapis.com;line ensures Dialogflow receives the correct hostname to process your streaming request. Without this, Google's API might reject or misroute the stream. - Fixed Typo: Corrected
exemple.comtoexample.comin your SSL key path (a small but easy-to-miss error that could cause unexpected issues). - Optimized HTTP/2 & gRPC Settings: Adjusted timeouts, buffer sizes, and session settings to maintain long-lived bidirectional streams. Using a smaller
grpc_buffer_sizeis better for streaming since it reduces latency by sending data chunks immediately instead of buffering large amounts. - SSL Hardening: Added TLS 1.2/1.3 support and optimized cipher suites, which is important for secure gRPC communication over HTTPS.
Verification Steps
- Check your Nginx version with
nginx -v—if it's older than 1.13.10, upgrade it first. - Test the config with
nginx -tto ensure no syntax errors. - Reload Nginx with
systemctl reload nginx(orservice nginx reloaddepending on your OS). - Re-run your StreamingDetectIntent call—this should now work as expected, with Dialogflow properly sending back the downstream stream responses.
内容的提问来源于stack exchange,提问作者Maxime Wimez
相关产品推荐
相关产品推荐

