Swoole Websocket behind Apache mod_ssl proxy

标题里除了那个副词 behind 以外,其他都是技术术语。 充满了技术的高(Low)大(B)上的感觉。

Swoole 是 PHP 语言的一个模块, 就是说 PHP 里要加载这个 模块 (php -m|grep swoole 可以查看是否加载),是做异步,做微服务的性能最好的工具。

Websocket 是什么? wss 就是 Web socket secure,就是前后端需要长连接实时聊天,来回 ping/pong 的协议工具。

Apache 是什么?在这里是 httpd 服务器,就是 Web 服务器。

mod_ssl 就是 Apache 的 https 实现,就是 HTTP 加密需要用的 Apache 模块。

Proxy 的意思,就是代理, 有正向和反向, 在 Web 服务器上, 我们一般都是反向代理, 就是把前端给过来的流量往后端丢。 在这里, 就是 微信小程序客户端请求 wss://wss.yj777.cn/ 连接到 wss.yj777.cn 的 443 端口,我们把数据往 PHP 语言写的基于 Swoole 模块的 WebSocket 的某个端口,例如 9901 丢。
PHP 的片段代码是这样的:

$request 就是取的小程序前端丢过来的 WSS 连接请求数据。从微信小程序端丢过来的请求头是长这样子的:

我们用 curl 写一段测试脚本:

当我们命令行运行这段脚本的时候,会提示如下:

然后就等待聊天的输入,我们按 Ctr-C 退出就好。

为了让 Websocket 服务长期驻留,我们要设置成服务的形式,写一个
/etc/systemd/system/yj777_wss.service
然后 systemctl daemon-reload,然后 systemctl –now enable 就可以启用并启动服务。

当然最核心的,总是留到写到最后的。 那就是 Apache 的代理配置。这是所有出错的关键,遇到的问题,几乎都是在 Apache 的配置里。
首先当然是确认做 ws 反向代理的模块 wstunnel.so 已经加载: httpd -M|grep tunnel:
proxy_wstunnel_module
CentOS 7 安装了 Apache 后,默认是加载 /etc/httpd/conf.modules.d 下的所有 .conf 文件的,这个模块包含在 00-proxy.conf 文件里。

核心的就是 下面的两行:请注意里面的 URL 协议是 wss 不是 https ,关于这个梗,有人写 https 的, 但是需要 rewrite_mod 写 http_upgrade, 就是类似以上 curl 里的头,实际上就是多余的。

  ProxyPass / wss://127.0.0.1:9901/
  ProxyPassReverse / wss://127.0.0.1:9901/

当然其他的几个也非常重要。例如 ProxyPreserveHost

我们每天总是在填坑和挖坑间不断进步!

最后,来一个 Nginx 上配置代理 Websocket 的花絮:
我们直接把 请求转到另外一台服务器公网上暴露的 9981 端口了。(这是不好的)
所以,我们一般需要配一个子域名,做单独的 WS 服务,然后开启证书,然后 wss 就是指向 443 端口, 让 Nginx/Apache 代理往后面的 Swoole 丢。
记住:微服务,每个服务是一个独立的二级域名!

以上 Nginx 配置里, proxy_pass 后面应该是 http://localhost:port/ 即可,用 https 会要求后台的服务器地址开启证书,没有必要。