Javascript 通过Apache/Varnish访问Websocket失败

Javascript 通过Apache/Varnish访问Websocket失败,javascript,apache,websocket,varnish,ratchet,Javascript,Apache,Websocket,Varnish,Ratchet,几天来,我一直在尝试让这个到websocket的连接正常工作,但当我试图通过Javascript连接到它时,仍然出现了一个错误 javascript抛出的错误如下: WebSocket connection to 'ws://lmc-staging.mydomain.org:8081/' failed: Connection closed before receiving a handshake response brainsocket.min.js:1 Event {clipboardData

几天来,我一直在尝试让这个到websocket的连接正常工作,但当我试图通过Javascript连接到它时,仍然出现了一个错误

javascript抛出的错误如下:

WebSocket connection to 'ws://lmc-staging.mydomain.org:8081/' failed: Connection closed before receiving a handshake response
brainsocket.min.js:1 Event {clipboardData: undefined, path: NodeList[0], cancelBubble: false, returnValue: true, srcElement: WebSocket…}bubbles: false cancelBubble: false cancelable: false clipboardData: undefined currentTarget: WebSocket defaultPrevented: false eventPhase: 0path: NodeList[0] returnValue: true srcElement: WebSockettarget: WebSockettimeStamp: 1421938720697 type: "error"__proto__: Event

brainsocket.min.js:1 WebSocket is already in CLOSING or CLOSED state.
使用Varnish将请求传输到Apache Web服务器xxx.xxx.xxx.203。varnish配置发布在下面:

# This is a basic VCL configuration file for varnish.  See the vcl(7)
# man page for details on VCL syntax and semantics.
# 
# Default backend definition.  Set this to point to your content
# server.
# 

# Internal hosts; same as purge, but separated for clarity.
acl internal {
  "localhost";
  "127.0.0.1";
  "xxx.xxx.xxx.0"/24;
  "xxx.xxx.xxx.203";
  "xxx.xxx.xxx.204";
}

# Hosts allowed to purge cache
acl purge {
  "localhost";
  "127.0.0.1";
  "xxx.xxx.xxx.0"/24;
  "xxx.xxx.xxx.203";
  "xxx.xxx.xxx.204";
}

# DEV webserver
backend vsrv1474 {
  .host = "xxx.xxx.xxx.203";
  .port = "80";
  .connect_timeout = 300s;
  .first_byte_timeout = 300s;
  .between_bytes_timeout = 300s;
}

# DEV brainsocket
backend brainsocket {
  .host = "xxx.xxx.xxx.203";
  .port = "8081";
  .connect_timeout = 300s;
  .first_byte_timeout = 300s;
  .between_bytes_timeout = 300s;
}

# PROD webserver
backend vsrv1475 {
  .host = "xxx.xxx.xxx.204";
  .port = "80";
  #.connect_timeout = 5s;
  #.first_byte_timeout = 60s;a
  #.between_bytes_timeout = 60s;
  .connect_timeout = 300s;
  .first_byte_timeout = 300s;
  .between_bytes_timeout = 300s;
}


sub vcl_recv {
  # Allow purge from hosts in purge acl or return 405
  if (req.request == "PURGE") {
    if (!client.ip ~ purge) {
      error 405 "Not allowed";
    }
    return(lookup);
  }


# entry for brainsocket
  if (req.http.Upgrade ~ "(?i)websocket") {
    set req.backend = brainsocket;
    return (pipe);
  }

# end entry for brainsocket

  if (req.url ~ "/dev/" || req.http.host == "staging.mydomain.org" || req.http.host == "dev.mydomain2.org" || req.http.host == "lmc-staging.mydomain.org" ){
    set req.backend = vsrv1474;
    return(pass);
  } elsif ( req.http.host == "www.mydomain2.org" || req.http.host == "lmc.mydomain2.org" ) {
    set req.backend = vsrv1475;
  } else {
    set req.backend = vsrv1475;
  }


  if (req.url ~ "^/misc/progress\.js\?[0-9]+$") {
    set req.url = "/misc/progress.js";
  }

  if (req.url ~ "^/admin/content/backup_migrate/export") {
    return (pipe);
  }

  # Do not cache these paths.
  if(req.url ~ "^/status\.php$"||
      req.url ~ "^/update\.php$"||
      req.url ~ "^/install\.php" ||
      req.url ~ "^/admin" ||
      req.url ~ "^/admin/.*$"||
      req.url ~ "^/user" ||
      req.url ~ "^/user/.*$" ||
      req.url ~ "^/users/.*$" ||
      req.url ~ "^/info/.*$" ||
      req.url ~ "^/flag/.*$"||
      req.url ~ "^.*/ajax/.*$"||
      req.url ~ "^.*/facebook-rss.xml$" ||
      req.url ~ "^.*/twitter-rss.xml$" ||
      req.url ~ "^.*/ahah/.*$") {
      return(pass);
  }

  # Disallow outside access to cron.php or install.php
  if (req.url ~ "^/(cron|install)\.php$" && !client.ip ~ internal) {
    error 404 "Page not found.";
  }

  # Always cache the following file types for all users.
  if (req.url ~ "(?i)\.(png|gif|jpeg|jpg|ico|swf|css|js|html|htm|woff)(\?[a-z0-9]+)?$") {
    unset req.http.Cookie;
  }

  # Remove all cookies that Drupal doesn't need to know about. ANY remaining
  # cookie will cause the request to pass-through to Apache. For the most part
  # we always set the NO_CACHE cookie after any POST request, disabling the
  # Varnish cache temporarily. The session cookie allows all authenticated users
  # to pass through as long as they're logged in.
  if (req.http.Cookie) {
    set req.http.Cookie = ";" + req.http.Cookie;
    set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
    set req.http.Cookie = regsuball(req.http.Cookie, ";(S{1,2}ESS[a-z0-9]+|NO_CACHE|CI_SESSION|ci_session|token|PHPSESSID)=", "; \1=");
    set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
    set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");

    if (req.http.Cookie == "") {
      # If there are no remaining cookies, remove the cookie header. If there
      # aren't any cookie headers, Varnish's default behavior will be to cache
      # the page.
      unset req.http.Cookie;
    }
    else {
      # If there is any cookies left (a session or NO_CACHE cookie), do not
      # cache the page. Pass it on to Apache directly.
      return (pass);
    }
  }


  # Remove the "has_js" cookie
  set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");

  # Remove the "Drupal.toolbar.collapsed" cookie
  set req.http.Cookie = regsuball(req.http.Cookie, "Drupal.toolbar.collapsed=[^;]+(; )?", "");

  # Remove any Google Analytics based cookies
  set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");

  # Remove the Quant Capital cookies (added by some plugin, all __qca)
  set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");

  # Are there cookies left with only spaces or that are empty?
  if (req.http.cookie ~ "^ *$") {
    unset req.http.cookie;
  }

  # Cache static content unique to the theme (so no user uploaded images)
  if (req.url ~ "^/themes/" && req.url ~ ".(css|js|png|gif|jp(e)?g)") {
    unset req.http.cookie;
  }

}


sub vcl_pipe {
    #copy the upgrade header
    if (req.http.upgrade) {
        set bereq.http.upgrade = req.http.upgrade;
    }

    #closing the connection might be necessary for some applications as the connection will remain open forever and consume resources if not properly stopped by server or client
    #set bereq.http.Connection = "close";
}


sub vcl_miss {
  if (req.request == "PURGE") {
    purge;
    error 200 "Purged";
  }
}

sub vcl_hit {
  if (req.request == "PURGE") {
    purge;
    error 200 "Purged";
  }
}

sub vcl_fetch {
  unset beresp.http.Vary;
  set beresp.http.x-url = req.url;
  set beresp.http.x-host = req.http.host;

 # Don't allow static files to set cookies.
  if (req.url ~ "(?i)\.(png|gif|jpeg|jpg|ico|swf|css|js|html|htm)(\?[a-z0-9]+)?$") {
    # beresp == Back-end response from the web server.
    unset beresp.http.set-cookie;
  }

  # Check if no ttl and a cookie set. 
  if (beresp.ttl <= 0s && beresp.http.Cookie ~ ".+" ) {
    set beresp.http.X-Cacheable = "NO:Not Cacheable: No ttl; has cookie";
  # Varnish determined the object was not cacheable
  } elsif (beresp.ttl <= 0s) {
    set beresp.http.X-Cacheable = "NO:Not Cacheable: No ttl; no cookie";
  # You don't wish to cache content for logged in users
  } elsif (req.http.Cookie ~ "(S{1,2}ESS[a-z0-9]+|NO_CACHE|CI_SESSION|ci_session|token|PHPSESSID)") {
    set beresp.http.X-Cacheable = "NO:Got Session";
    return(hit_for_pass);

    # You are respecting the Cache-Control=private header from the backend
  } elsif (beresp.http.Cache-Control ~ "private") {
    set beresp.http.X-Cacheable = "NO:Cache-Control=private";
    return(hit_for_pass);

  # Varnish determined the object was cacheable
  } else {
    set beresp.http.X-Cacheable = "YES";
  }

  return(deliver);
}

sub vcl_deliver {
  if (obj.hits > 0) {
     set resp.http.X-Cache = "HIT";
  } else {
    set resp.http.X-Cache = "MISS";
  }
  unset resp.http.x-url; # Optional
  unset resp.http.x-host; # Optional
  unset resp.http.Server;
  unset resp.http.X-Generator;
  unset resp.http.X-Powered-By;
  unset resp.http.X-Drupal-Cache;
}

我使用的是brainsocket包,它允许您使用Laravel创建客户端和服务器端套接字。Brainsocket使用Ratchet作为其底层websocket层

问题正如Marcel Dumont所建议的,与Varnish未配置为侦听端口8081有关。因此,我们将前端客户端重定向到连接端口80,并依靠Varnish将信息通过管道传输到端口8081上的底层websocket

varnish正在监听端口8081吗?你的大脑插座是,但不清楚是否也配置了清漆。有没有一个简单的方法来测试这个?我查看了wireshark流量,似乎流量正在从varnish服务器中继到另一个IP,但随后它中断了。我将使用Wireshark.check out/etc/default/varnish中的屏幕截图更新我的问题,其中定义了哪个端口。或者运行netstat-an | grep8081 | grep-i在varnish机器上侦听默认情况下所有传入的头文件?我以前遇到过web套接字和代理风格的请求转发问题,在到达后端时,关键的特定于websocket的头丢失了。见: