TLDR

  • Issue:Unable to receive SSE after migrating Nginx configuration from test to production environment
  • Cause:Nginx 1.22.0 defaults to using HTTP/1.0 instead of HTTP/1.1
  • Investigation : Enable debug logs and analyze
  • Solution : Specify HTTP version 1.1 in Nginx global settings

Scenario

After migrating the same configuration from the test environment to the production environment, regular requests worked normally, but SSE had no response (Timeout).

Manual and tool comparisons, as well as ChatGPT analysis, did not reveal any configuration issues. The only difference was that the test environment used Nginx version 1.22.1, while the production environment used version 1.22.0.

Investigation

Enable Debug Logs

First, enable debug logs in /etc/nginx/nginx.conf to print detailed errors:

1
error_log /var/log/nginx/error.log debug;

Check the configuration and reload Nginx:

1
2
nginx -t
nginx -s reload

Analyze Logs

We can find error information in /var/log/nginx/error.log.

For urgent online fixes with many users online, which may result in too many logs to search through, you can use the following command:

1
tail -f -n 1 /var/log/nginx/error.log | grep -i "sse" # 'sse' can be replaced with your desired keyword

This command will continuously track the latest line of error.log and filter out lines containing “sse”.

Then, trigger the problematic API and obtain the following information:

1
2
3
4
5
6
# Sensitive information replaced and text shortened
[notice] XXXX#XXXX: _XXXX "^/app/(._)$" matches "/app/api/sse", client: X.X.X.X, server: example.com, request: "GET /app/api/sse HTTP/1.1", host: "example.com", referrer: "https://example.com/app/Game"
[notice] XXXX#XXXX: *XXXX "^/app/(.*)$" matches "/app/api/sse", client: X.X.X.X, server: example.com, request: "GET /app/api/sse HTTP/1.1", host: "example.com", referrer: "https://example.com/app/Game"
[notice] XXXX#XXXX: *XXXX rewritten data: "/root/api/sse", args: "", client: X.X.X.X, server: example.com, request: "GET /app/api/sse HTTP/1.1", host: "example.com", referrer: "https://example.com/app/Game"
[error] XXXX#XXXX: *XXXX upstream timed out (110: Connection timed out) while reading upstream, client: X.X.X.X, server: example.com, request: "GET /app/api/sse HTTP/1.1", upstream: "http://127.0.0.1:80/root/api/sse", host: "example.com", referrer: "https://example.com/app/Game"
[info] XXXX#XXXX: \*XXXX epoll_wait() reported that client prematurely closed connection, so upstream connection is closed too while reading upstream, client: 127.0.0.1, server: example.com, request: "GET /root/api/sse HTTP/1.0", upstream: "http://X.X.X.X:8888/sse", host: "127.0.0.1", referrer: "https://example.com/app/Game"

Discovering the Problem

Upon closer inspection, we can see in the last line that Nginx did not correctly apply the HTTP/1.1 setting and erroneously used HTTP/1.0, causing the SSE transmission to fail.

Even setting proxy_http_version 1.1; in all places in the configuration did not successfully resolve the issue.

It is speculated that for unknown reasons (possibly version differences), Nginx ignored the configuration file and used the default HTTP/1.0 to call SSE.

Solution

Directly change the global proxy_http_version default to 1.1 in the http block. This forces Nginx to use HTTP/1.1 in all connections, including connections to upstream servers.

1
2
3
4
# Different projects may have different settings
http {
    proxy_http_version 1.1;
}

Conclusion

  1. Version differences can lead to unexpected issues, even with identical configuration files.
  2. Enabling detailed logs is very helpful for diagnosing problems.
  3. Sometimes global settings can solve specific problems, especially when individual directives seem ineffective.
  4. When migrating environments, be sure to carefully check the versions of all related software.