部署 在 ssl 下实现 faye 的 websocket 的推送

jimrokliu · 2012年09月08日 · 最后由 xinhuahunter 回复于 2014年08月29日 · 8726 次阅读
本帖已被管理员设置为精华贴

我的网站全站使用 https 访问的,现在使用 faye 做推送服务,参考了这篇文章http://afitnerd.com/2012/08/14/websockets-over-ssl-stunnel-haproxy-node-js/ 因为 nginx 目前的版本是不支持 websocket 的,如果使用 longpoll 方式推送,消息的延时是非常明显的,同时,faye 的后台日志里也有大量的错误。

                                        http  |nginx:80 |
client-->|stunnel:443|-->|haproxy:8080|----> |nginx:8443|-->|thin:3000|
                                            |  websocket                      
                                            |--------------------^

1.首先,服务器开放 80 和 433 的端口,用户对 80 端口的访问将重新定向到 443 的 https 服务上。这个工作是由 nginx 完成的。

2.为了使用 haproxy 转发 websocket 的请求,必须对请求内容进行分析,由于 ssl 是加密的内容,必须现在 stunnel 中将 ssl 解开,转换成 http 协议。 3.haproxy 根据协议头中的信息,区分是 websocket 协议还是 http 协议,分别转向到 nginx:8443 还是 thin:3000 的 faye 服务上。因为我把 faye 和 rails 合并在一个 thin 上运行,所以,haproxy 和 nginx 都会请求这个 thin 的服务。

安装 stunnel 的方法如下:

$ wget -c http://www.stunnel.org/downloads/stunnel-4.53.tar.gz
$ tar -xvzf stunnel-4.53.tar.gz
$ cd stunnel-4.53
$ ./configure
$ make
$ sudo make install
$ useradd stunnel
$ mkdir -p /opt/stunnel/ssl
$ mkdir -p /opt/stunnel/pid
$ vi /opt/stunnel/stunnel.conf
$ cat ssl.crt server.key > /opt/stunnel/ssl/cert.key_pem
$ chmod 600 cert.key_pem

stunnel 配置文件如下

pid = /opt/stunnel/pid/stunnel.pid
#foreground = yes
setgid = stunnel
setuid = stunnel
cert = /opt/stunnel/ssl/cert.key_pem
[https]
accept = 443
connect = 8080

启动 stunnel

$ stunnel /opt/stunnel/stunnel.conf

安装 haproxy

$ wget -c http://haproxy.1wt.eu/download/1.4/src/haproxy-1.4.22.tar.gz
$ tar -xvzf haproxy-1.4.22.tar.gz
$ make TARGET=linux26
$ make TARGET=linux26 PREFIX=/opt/haproxy
$ useradd haproxy
$ sudo make install PREFIX=/opt/haproxy

vi /etc/haproxy.cfg

global
    log 127.0.0.1       local0
    log 127.0.0.1       local0 notice

    maxconn     4096
    daemon
    nbproc      1
    pidfile     /var/run/haproxy.pid

    user        haproxy
    group       haproxy

defaults
    mode http


frontend all *:8080
    timeout client    86400000
    default_backend   nginx_backend

    acl is_websocket hdr(Upgrade) -i WebSocket
    acl is_websocket hdr_beg(Host) -i ws
    acl is_faye url_sub comet

    use_backend faye_backend if is_faye
    use_backend ws_backend if is_websocket

backend ws_backend
    option forwardfor
    timeout queue 5000
    timeout connect 86400000
    timeout server 86400000
    server server1 localhost:3000 maxconn 2000 check

backend faye_backend
    option forwardfor
    timeout connect 4000
    timeout server 30000
    server server1 localhost:3000 maxconn 1024 check

backend nginx_backend
    option forwardfor
    timeout connect 4000
    timeout server 86400000
    server server1 localhost:8443 maxconn 1024 check

启动 haproxy

sudo /opt/haproxy/sbin/haproxy -f /etc/haproxy.cfg

为什么 longpoll 延时会非常明显呢?理论上应该不会啊

@edokeh 这个问题我的理解是当你的浏览器支持 websocket,而服务器又没有打开 websocket,那么肯定会造成客户端不停的重试与服务器的请求。后台的日志里的一些错误没有仔细分析,应该跟这个有关系。两者在时间上差别可以达到 5 到 6 秒的差距。

我没看过 faye 的 js client 代码,不过现在用 cometd 这个开源项目,也是基于 bayeux 协议 他的 client js 中有多种连接方式(ws, longpoll)的尝试,如果一种方式成功后,就停止另外的方式 而且我觉得这个跟延时应该没有关系啊

这个延时问题可能跟我原来后台的结构有关系,nginx 做反向代理使用了 ssl,而 faye 是独立运行,faye 的一些推送服务是从服务器内发起的,并不知道应该使用 https 进行推送,所以日志里会有错误信息:2012-09-04 17:27:14 [ERROR] [Faye::RackAdapter] Received request with no message: "curl -X GET http://www.abc.com/fayeip。显然应该是",这些信息发起的地址都是服务器的 https://www.abc.com/fayefaye,具体的问题没有分析,也许有人能给些线索。才能连通

资深/Lead 开发工程师 (ruby)

岗位职责: 1.在技术和运营上负责一个或多个产品组件、关键应用的架构改造、升级、研究与开发 2.关注互联网与广告热点技术的发展方向,敢于提出、评估并应用新技术,带领团队开发新的工具,帮助提高现有系统的效率、降低运营成本、提高可靠性 3.作为技术专家,解决系统开发中的疑难问题。在产品特性与架构演化之间做出良好的技术决策、平衡与取舍 4.能够与产品经理、管理团队进行良好地沟通合作,确保项目按时、保质完成 5.培养团队中有潜质的工程师

任职资格的具体描述: 1.本科及以上学历,计算机相关专业,(Lead 5,Senior 3)年以上工作经验,其中至少(Lead 3,Senior 2)年以上的大型核心业务系统开发经验 2.掌握多种主流程序设计语言,有大型 Web 应用开发和架构经验,熟悉主流 Web 应用框架,精通 Ruby 或 Java、PHP 3.熟悉 Linux 操作系统、网络和关系型数据库的应用开发与优化 4.对设计模式、软件工程、用户体验等有较深入的理解 5.喜欢团队协作,擅长沟通(Lead 还需具备一定的技术团队管理经验) 6.可以熟练地使用英文工作,适应外企环境

FreeWheel 北京(飞维美地信息技术(北京)有限公司)

需要 登录 后方可回复, 如果你还没有账号请 注册新账号