2012-05-17 58 views
3

嘿,我一直在試圖讓HAProxy的代理WebSocket連接從socket.ioHAProxy的socket.io的WebSocket代理總是回落到長輪詢

我看了幾乎所有我能找到谷歌,並嘗試了無數的變化haproxy.cfg,但無論我嘗試socket.io總是會回到長輪詢。

值得一提的是,如果我將連接直接路由到套接字服務器即時通訊,ws連接完美工作。

所以即時使用socket.io客戶端和龍捲風tornadio2 websocket服務器。從這裏haproxy example conf

defaults 
mode http 

frontend all 
bind 0.0.0.0:80 
mode tcp 

maxconn 200000 
timeout client 86400000 
default_backend www_backend 

# Any URL beginning with socket.io will be flagged as 'is_websocket' 
acl is_websocket path_beg /socket.io 
acl is_websocket hdr(Upgrade) -i WebSocket 
acl is_websocket hdr_beg(Host) -i ws 

# The connection to use if 'is_websocket' is flagged 
use_backend socket_backend_http if is_websocket 

tcp-request inspect-delay 500ms 
tcp-request content accept if HTTP 

backend www_backend 
option httplog 
option httpclose 
balance roundrobin 
option forwardfor 
timeout server 30000 
timeout connect 4000 
server nginx localhost:81 weight 1 maxconn 1024 check 

backend socket_backend_http 
mode http 
option httplog 
option http-server-close 
option forceclose 
no option httpclose 
balance roundrobin 
option forwardfor 
timeout queue 5000 
timeout server 86400000 
timeout connect 86400000 
timeout check 1s 
server socket1 localhost:3012 weight 1 maxconn 1024 check 

WebSocket的請求被正確地路由到該socket_backend_http但瀏覽器控制檯總是顯示以下錯誤

Unexpected response code: 400 

然後socket.io回落到了我的當前haproxy.cfg短時間後的長輪詢消息按預期顯示。 我已經測試過使用最新版本的chrome,safari和firefox全部都有相同的結果

我見過這麼多人說他們有這個工作讓我失望!我會永遠感謝任何能夠解決這個問題的人。

再次只是爲了闡明haproxy綁定到80端口,nginx在端口81上運行,而套接字服務器在端口3012上運行。如果有人認爲看到套接字服務器會有用,請留下評論和惡意修改與代碼後

在此先感謝

編輯 當前haproxy.cfg實際上是造成這種錯誤的龍捲風服務器提高

Traceback (most recent call last): 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-  packages/tornado/ioloop.py", line 399, in _run_callback 
callback() 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/iostream.py", line 304, in wrapper 
callback(*args) 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/httpserver.py", line 250, in _on_headers 
self.request_callback(self._request) 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 1362, in __call__ 
handler._execute(transforms, *args, **kwargs) 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 992, in _execute 
self._handle_request_exception(e) 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 1032, in _handle_request_exception 
self.send_error(500, exc_info=sys.exc_info()) 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 688, in send_error 
self.finish() 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/web.py", line 669, in finish 
self.request.finish() 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/httpserver.py", line 422, in finish 
self.connection.finish() 
File "/home/mike/.virtual-envs/watchdog-app/local/lib/python2.7/site-packages/tornado/httpserver.py", line 183, in finish 
assert self._request, "Request closed" 

UPDATE

好,所以進一步發展。我已經設法使用stunnel進行稍微不同的設置。所以現在nginx重新將http請求路由到https,在那裏它被接收,並且ssl連接被stunnel終止,然後在端口8443轉發請求,haproxy選擇它。套接字握手做,一切都按預期工作,這是偉大的,但ID愛一個人能夠啓發我爲什麼這與ssl工作,而不是與http!

回答

2

做了一些快速研究 - 不是個人熟悉,但我一直在使用SockJS並注意到相同的行爲。我發現至少是Nginx與websockets不兼容,並且HAProxy需要努力才能像你發現的那樣工作。 haproxy and socket.io not fully working

示例配置與您的配置非常相似,源於以下源http://book.mixu.net/ch13.html,看起來與您的配置類似99%。

https://github.com/mixu/sioconfig/blob/master/single.haproxy.cfg

另外兩個花絮我發現是 - 從HAProxy + WebSocket Disconnection

  • 確保您的HAProxy的是1.4或更高
  • 確保您socket.io是0.6.8版或更好
+0

嘿謝謝你的答案。我已經閱讀了你在你的答案中提出的所有內容,但似乎沒有任何工作:(我已經看到許多反駁說,由於內容長度標題沒有正確設置,這實際上不會工作。我認爲需要8個字節,這就是爲什麼即時看到不良要求返回。我一直在無意中讓一些haproxy irc頻道的傢伙擺脫一些光,但它的鬼城!! –

3

我不能說關於Socket.io,但SockJS已經過測試,並且在最近的haproxy(例如1.4.16)後工作良好。參見樣本設置:

我還沒有想出一個辦法來運行Nginx的背後SockJS。

+0

嘿感謝您的答案,我沒有聽說過很多關於SockJS和tbh似乎應該有可能使用socket.io 就nginx背後的運行和套接字服務器而言,我們將不得不等待nginx的版本1.3,在那裏他們將引入對http1.1協議的支持websocket握手。 –

1

爲了說清楚,WebSocket中沒有HTTP內容,因此不需要任何內容​​長度標題。

此外,您的配置有錯誤。前端處於TCP模式,因此只有當請求速度足夠快時,ACL纔會匹配。事實上,有時它可能會以純運氣的方式進行部分工作。請將你的前端設置爲「mode http」來解決這一問題, 並刪除你的「tcp-inspect」規則,這些規則變得毫無用處。順便說一下,你的「http-backend」也缺少HTTP模式。

我猜你沒有檢查日誌,否則你可能已經注意到了,他們並沒有真正的TCP開採: -/

0

我知道這是一個老問題,但:

HAProxy的ISN」能夠代理websockets(截至2013年6月)。 這個錯誤的原因很可能是因爲它將它看作是一個普通的http連接,並將連接計時。你可以讓超時時間持續很長時間,但感覺很髒。

的選項有:

  • Nginx的版本用於代理的WebSockets 1.4就將此支持見http://nginx.org/
  • 使用Nodejitsu的WebSocket的代理http://blog.nodejitsu.com/http-proxy-intro(發現泄漏的內存,跌倒在地,當我們把> 5K併發連接)。
  • 客戶端平衡,如使用server<n>.x.com
  • 使用亞馬遜的route53做DNS輪轉(我說亞馬遜,因爲它支持健康檢查,但如果你不需要HA正常的DNS會做)
  • 恐慌...

需要牢記的一點是,您還需要執行粘性會話或使用集中式會話存儲。 SockJS比socket.io更容易,因爲它會在每個會話的url中放置一個隨機字符串,以便您可以簡單地基於url進行平衡。您可以使用集中式存儲(如Redis)與Socket.io進行會話,因爲我發現它很笨拙。

Nginx和nodejitsu選項都可以爲你終止你的SSL。