SoFunction
Updated on 2025-05-20

Nginx's WebSocket reverse proxy practice process

1. Review of HTTP protocol upgrade mechanism

  • Upgrade/Connection Header

When the client initiates a WebSocket handshake, it will be added to a normal HTTP request.

Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: <Random value>
Sec-WebSocket-Version: 13

If the server accepts the protocol switch, it will101 Switching ProtocolsResponse and returnUpgradeandConnectionHeader.

  • Hop-by-Hop header limit

In HTTP/1.1,UpgradeandConnectionAll belong to the Hop-by-Hop header, which can only take effect between adjacent nodes and will not be forwarded by ordinary reverse proxy. Therefore, it is necessary to explicitly take these two out of the client request in Nginx and set them to the request header forwarded to the backend.

2. The key configuration of Nginx proxy WebSocket

1. Basic examples

location /chat/ {
    # Forward the request to the backend WebSocket service    proxy_pass http://backend;

    # Use the HTTP/1.1 protocol to support Upgrade    proxy_http_version 1.1;

    # Forward the Upgrade and Connection headers in the client request to the backend    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
proxy_http_version 1.1

Force HTTP/1.1, otherwise the default HTTP/1.0 cannot support protocol upgrades.

proxy_set_header Upgrade $http_upgrade

Passed the clientUpgrade: websocketPass to the backend.

proxy_set_header Connection “upgrade”

Identify andUpgradeUse together.

2. Intelligent Connection Settings

In some scenarios, I hope to issue only if there is a real need for upgrading"upgrade", otherwise keep the connection closed.

Can be used with NginxmapModule:

# Map the Upgrade header into variables if it existsmap $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    ...

    location /chat/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}
  • If there is no client requestUpgrade, then send to the backendConnection: close, more in line with the semantics of general HTTP requests.

3. Timeout and heartbeat optimization

By default, when Nginx proxys WebSocket connection, if the backend does not have any data back in 60 seconds, it will actively close the connection.

This is not friendly for scenarios where you are idle for a long time but may still have to push messages in the future.

There are two commonly used optimization solutions:

1. Extend Nginx'sproxy_read_timeout

existlocationorhttpserverLevel Add:

proxy_read_timeout 3600s;   # Increase the timeout to 1 Hour

2. Backend sending WebSocket Ping

Let the backend application periodically send ping frames to the client (via Nginx), triggering Nginx to read data, thus resetting the timeout timer, and detecting the connection health status.

4. Complete example

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    upstream backend {
        server 127.0.0.1:8080;    # Backend WebSocket service address        # Multiple servers can be added according to actual conditions to achieve load balancing    }

    server {
        listen 80;
        server_name ;

        # Static resource processing (optional)        location /static/ {
            root /var/www/html;
        }

        # WebSocket proxy portal        location /chat/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection $connection_upgrade;

            # Forward the client's real IP (optional)            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

            # Timeout configuration            proxy_read_timeout  3600s;
            proxy_send_timeout  3600s;
        }
    }
}

5. Practical points and precautions

  • HTTPS + WSS

If used on the front endwss://(i.e. TLS-encrypted WebSocket), the corresponding SSL certificate must be configured on Nginx and theserverUsed in blocksssl_certificatessl_certificate_keyWait for instructions.

  • Load balancing and Sticky Session

For services that require session consistency across multiple instances, consider Sticky Session configuration based on cookies or IP hashing, or design the service as stateless.

  • Safety reinforcement

Can be added in Nginxlimit_connlimit_reqEqual current limiting instructions to prevent malicious connections from exhausting resources;lua-nginx-moduleImplement more complex authentication or dynamic routing.

Summarize

Through the above method, Nginx can efficiently and stably forward the client's HTTP upgrade request (Upgrade) to the backend WebSocket service, realizing reverse proxy and load balancing.

On this basis, combined with reasonable timeout adjustment, heartbeat detection and safe current limit, a highly available and scalable real-time communication platform for the production environment can be built.

I hope this article can help you quickly get started with Nginx WebSocket agents and create a real-time architecture that meets business needs.

The above is personal experience. I hope you can give you a reference and I hope you can support me more.