Nginx和Flask socketio Websockets:活动但不发送消息?

Nginx和Flask socketio Websockets:活动但不发送消息?,sockets,nginx,flask,socket.io,gevent-socketio,Sockets,Nginx,Flask,Socket.io,Gevent Socketio,让Nginx很好地使用Python Flask socketio库(基于gevent)有点困难。目前,由于我们正在积极开发,我正试图让Nginx作为代理来工作。对于发送页面,我可以通过直接运行flask socketio应用程序或通过gunicorn运行来实现这一点。有一个问题:websocket消息似乎不起作用。页面已成功托管并显示。但是,当我尝试使用WebSocket时,它们不起作用。它们足够活跃,以至于websocket认为它已连接,但它们不会发送消息。如果我删除Nginx代理,它们就可以

让Nginx很好地使用Python Flask socketio库(基于gevent)有点困难。目前,由于我们正在积极开发,我正试图让Nginx作为代理来工作。对于发送页面,我可以通过直接运行flask socketio应用程序或通过gunicorn运行来实现这一点。有一个问题:websocket消息似乎不起作用。页面已成功托管并显示。但是,当我尝试使用WebSocket时,它们不起作用。它们足够活跃,以至于websocket认为它已连接,但它们不会发送消息。如果我删除Nginx代理,它们就可以工作了。当我尝试发送消息时,Firefox会出现以下错误:

Firefox无法在ws:///socket.io/1/websocket/上建立与服务器的连接

其中web地址是服务器所在的位置,唯一id只是一组随机数字。它似乎做了足够多的工作来保持连接的活动(例如,客户端认为它已连接),但无法通过websocket发送消息。我不得不认为这个问题与代理的某些部分有关,但我在调试问题可能是什么方面遇到了很大的困难(部分原因是这是我第一次使用Flask socketIO和nginx)。我正在为nginx使用的配置文件是:

user       <user name>;  ## This is set to the user name for the remote SSH session
worker_processes  5;

events {
  worker_connections  1024;  ## Default: 1024
}

http {
  default_type application/octet-stream;
  log_format   main '$remote_addr - $remote_user [$time_local]  $status '
    '"$request" $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';
  sendfile     on;
  server_names_hash_bucket_size 128; # this seems to be required for some vhosts

  server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://localhost:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
  } 
}
user;##这被设置为远程SSH会话的用户名
工人联合会进程5;
事件{
辅助连接1024;##默认值:1024
}
http{
默认_类型应用程序/八位字节流;
日志格式主“$remote\u addr-$remote\u user[$time\u local]$status”
“$request”$body\u bytes\u sent“$http\u referer”
“$http_user_agent”“$http_x_forwarded_for””;
发送文件到;
服务器名称散列存储桶大小128;#某些虚拟主机似乎需要这样做
服务器{
听80;
服务器名称;
地点/{
代理通行证http://localhost:8000;
proxy_http_版本1.1;
代理设置头升级$http\U升级;
代理设置头连接“升级”;
代理设置头主机$Host;
}
} 
}

我将配置文件作为一个通用示例和一个websocket特定示例的混合体,但试图摆弄它并没有解决问题。此外,当我在wsgi模式下使用werkzeug Proxy_Fix调用时,我正在我的Flask app.wsgi_应用程序上使用它。我试过了,不管有没有,但是都没有用。如果有人有什么见解,我会全神贯注。

我设法解决了这个问题。这些问题不是针对flask socketio的,而是针对Ubuntu、NginX和gevent socketio的。存在两个重要问题:

  • Ubuntu 12.04有一个非常古老的nginx版本(1.1.19对1.6.x的稳定版本)。为什么?谁知道呢。我们所知道的是,这个版本不以任何有用的方式支持WebSocket,因为1.3.13是您应该使用的
  • 默认情况下,gevent socketio希望套接字位于/socket.io位置。您可以升级整个HTTP连接,但我在使其正常工作时遇到了一些困难(特别是在我将SSL加入混合后)
  • 我修复了#1,但在处理它时,我被nginx清除并安装了apt。。。Ubuntu上nginx的默认版本。然后,我莫名其妙地困惑于为什么事情比以前更糟。许多.conf文件在这场战斗中英勇牺牲
  • 如果尝试在此配置中调试WebSocket,我建议执行以下步骤:

  • 通过“nginx-v”检查您的nginx版本。如果它小于1.4,请升级它
  • 检查nginx.conf设置。您需要确保连接升级
  • 检查服务器IP和端口是否与nginx.conf反向代理匹配
  • 检查您的客户端(例如socketio.js)是否使用正确的协议连接到正确的位置和端口
  • 检查被阻止的端口。我在EC2上,所以您必须手动打开80(HTTP)和443(SSL/HTTPS)
  • 刚刚检查了所有这些东西,有一些外卖

  • 在Ubuntu()上升级到最新稳定的nginx版本可以通过以下方式完成:

    sudo apt-get install python-software-properties
    sudo apt-get install software-properties-common
    sudo add-apt-repository ppa:nginx/stable
    sudo apt-get update
    sudo apt-get install nginx
    
    在像Windows这样的系统中,您可以使用,并且不太可能得到错误的版本

  • 这方面的许多配置文件可能令人困惑,因为nginx大约在2013年正式添加了套接字,使得早期的解决方案配置过时。现有的配置文件往往不包括nginx、gevent-socketio和SSL的所有基础,但它们都是分开的(,)。带有flask socketio(包装gevent socketio)和SSL的nginx 1.6的配置文件是:

    user <user account, probably optional>;
    worker_processes  2;
    error_log  /var/log/nginx/error.log;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include mime.types;
        default_type       application/octet-stream;
        access_log         /var/log/nginx/access.log;
        sendfile           on;
    #   tcp_nopush         on;
        keepalive_timeout  3;
    #   tcp_nodelay        on;
    #   gzip               on;
        client_max_body_size 20m;
        index              index.html;
    
        map $http_upgrade $connection_upgrade {
                default upgrade;
                ''      close;
        }
    
        server {
          # Listen on 80 and 443
          listen 80 default;
          listen 443 ssl;  (only needed if you want SSL/HTTPS)
          server_name <your server name here, optional unless you use SSL>;
    
          # SSL Certificate (only needed if you want SSL/HTTPS)
          ssl_certificate <file location for your unified .crt file>;
          ssl_certificate_key <file location for your .key file>;
    
          # Optional: Redirect all non-SSL traffic to SSL. (if you want ONLY SSL/HTTPS)
          # if ($ssl_protocol = "") {
          #   rewrite ^ https://$host$request_uri? permanent;
          # }
    
          # Split off basic traffic to backends
          location / {
            proxy_pass http://localhost:8081; # 127.0.0.1 is preferred, actually.
            proxy_redirect off;
          }
    
          location /socket.io {
            proxy_pass          http://127.0.0.1:8081/socket.io; # 127.0.0.1 is preferred, actually.
            proxy_redirect off;
            proxy_buffering off; # Optional
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
          }
        }
     }
    
  • 对于socketio.js这样的客户端,连接应该很容易。例如:

    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js"></script>
    <script type="text/javascript">
        var url = window.location.protocol + document.domain + ':' + location.port,
            socket = io.connect(url);
        socket.on('message', alert);
        io.emit("message", "Test")
    </script>
    
    
    var url=window.location.protocol+document.domain+':'+location.port,
    socket=io.connect(url);
    socket.on('消息',警报);
    io.emit(“消息”、“测试”)
    
  • 开放端口实际上更像是一个问题,因为它在很大程度上取决于防火墙。有关AmazonEC2,请参阅

  • 如果尝试所有这些都不起作用,哭吧。然后返回列表的顶部。因为您可能只是意外地重新安装了较旧版本的nginx


  • 您不应该在某个非根URL上代理websocket连接吗?如果一切都通过websocket,那么如何向客户端提供HTTP/JS文件?在生产环境中,nginx将通过一些额外的配置设置来处理这些问题。现在,在引擎盖下,Flask正在处理一切。它有自己的静态文件路由功能。基本上,我使用的是沿着/js/、/static/等行的一些端点,这些端点会导致相应的Flask向存储它们的地方发送\u static\u文件调用。方便测试,但显然不知道如何扩展任何内容。但是,这些都可以使用上述nginx配置。只有websocket消息失败。我现在已经修复了这个问题。实际上是tw
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js"></script>
    <script type="text/javascript">
        var url = window.location.protocol + document.domain + ':' + location.port,
            socket = io.connect(url);
        socket.on('message', alert);
        io.emit("message", "Test")
    </script>