workman分布式部署遇到的bug以及修复方式

代码备份录—— workman 分布式部署遇到的问题,以及解决方式

我的目标

状况
现在手里是有2台服务器,并且已经是借助阿里云的slb负债均衡转发请求的,当然这个负债均衡在此处并没有用到,因为它主要是监听43380端口用。我并没有去监听tcp 我的内容
这个案例回头想想还是比较简单的

主要实现商家后端登入保持在线后,若有人下单,给它推送一个mp3指令(播放mp3)

服务器情况

服务器A :公网IP 66.66.66.61  内网IP192.168.0.1
服务器B :公网IP 99.99.99.91  内网IP192.168.0.2

服务端配置 - 服务器A

内容来自:start_register.php
<?php 
use \Workerman\Worker;
use \GatewayWorker\Register;
require_once __DIR__ . '/../../vendor/autoload.php';
// register 服务必须是text协议
$register = new Register('text://0.0.0.0:1238');
// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}

---分割线---
内容来自:start_gateway.php
<?php
use \Workerman\Worker;
use \GatewayWorker\Gateway;
use \Workerman\Autoloader;

require_once __DIR__ . '/../../vendor/autoload.php';

// gateway 进程
$gateway = new Gateway("Websocket://0.0.0.0:7373");
$gateway->name = 'gateway';// 设置名称,方便status时查看
$gateway->count = 4;// 设置进程数,gateway进程数建议与cpu核数相同
$gateway->lanIp = '192.168.0.1'; // 分布式部署时请设置成内网ip(非127.0.0.1)此处做演示用,需填写真实的服务器内网ip
$gateway->startPort = 2310;// 不可被其他项目占用端口,2300-2303 , 2310-2313,   必须1236,1238端口不能重复,不能2个项目都用1236端口,可以全部替换其他端口!同时startPort不能冲突
$gateway->pingInterval = 10;// 心跳间隔
$gateway->pingData = '{"type":"ping"}';// 心跳数据
$gateway->registerAddress = '192.168.0.1:1238';// 服务注册地址

if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}
---分割线---
内容来自:start_businessworker.php 
<?php
use \Workerman\Worker;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;

require_once __DIR__ . '/../../vendor/autoload.php';

$worker = new BusinessWorker();// bussinessWorker 进程
$worker->name = 'businessWorker';// worker名称
$worker->count = 4;// bussinessWorker进程数量
$worker->registerAddress = '192.168.0.1:1238';// 服务注册地址
// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}

注:框架其他文件
GatewayWorker/vendor/workerman/gateway-worker/src/Gateway.php
GatewayWorker/vendor/workerman/gateway-worker/src/Lib/Gateway.php
以上2个文件因为是部署在第一台,所以$registerAddress中的可以ip可以是127.0.0.1,但端口要修改为自己注册的端口:1238 【即:start_register.php 文件中填写的端口】

服务端配置 - 服务器B

内容来自:start_register.php 【此文件内所有内容全部注释,因为register需要统一一个】
<?php 

// 就当全部删除了

---分割线---
内容来自:start_gateway.php 【此文件,和服务器A不同的地方在内网ip lanIp】
<?php
use \Workerman\Worker;
use \GatewayWorker\Gateway;
use \Workerman\Autoloader;

require_once __DIR__ . '/../../vendor/autoload.php';

// gateway 进程
$gateway = new Gateway("Websocket://0.0.0.0:7373");
$gateway->name = 'gateway';// 设置名称,方便status时查看
$gateway->count = 4;// 设置进程数,gateway进程数建议与cpu核数相同
$gateway->lanIp = '192.168.0.2'; // 分布式部署时请设置成内网ip(非127.0.0.1)此处做演示用,需填写真实的服务器内网ip
$gateway->startPort = 2310;// 不可被其他项目占用端口,2300-2303 , 2310-2313,   必须1236,1238端口不能重复,不能2个项目都用1236端口,可以全部替换其他端口!同时startPort不能冲突
$gateway->pingInterval = 10;// 心跳间隔
$gateway->pingData = '{"type":"ping"}';// 心跳数据
$gateway->registerAddress = '192.168.0.1:1238';// 服务注册地址

if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}
---分割线---
内容来自:start_businessworker.php  【此文件无改动】
<?php
use \Workerman\Worker;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;

require_once __DIR__ . '/../../vendor/autoload.php';

$worker = new BusinessWorker();// bussinessWorker 进程
$worker->name = 'businessWorker';// worker名称
$worker->count = 4;// bussinessWorker进程数量
$worker->registerAddress = '192.168.0.1:1238';// 服务注册地址
// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}

注:框架其他文件
GatewayWorker/vendor/workerman/gateway-worker/src/Gateway.php
GatewayWorker/vendor/workerman/gateway-worker/src/Lib/Gateway.php
以上2个文件部署在第二台,所以$registerAddress中的可以ip要改为是192.168.0.1 (register的内网地址,不能是127.0.0.1),端口还是:1238 【即:第一台start_register.php 文件中填写的端口】

域名绑定

添加记录
1、domain.com ==正常解析到第一台ip==> 66.66.66.61

客户端绑定

代码说明
1、一个看不见的mp3 标签(通过jq播放,需要当前页面有点击事件,否则会报错,但由于后台登入的时候,就已经触发了点击,所有下方的jq能操作播放)
2new ws协议,进入websocket握手环节 -> 成功则会逐步在控制台打印
启动ws链接
onopen
{"type":"init","client_id":"c0a8a0cc090800000007"}
收到workman返回的client_id,准备绑定laravel
开始绑定client_id
绑定成功 [Array(1)]


<div style="display: none">
    <audio src="/mp3/xxxx.mp3" controls="controls" preload="auto" id="mp3" ></audio>
</div>
<script type="text/javascript">

    var ws;
    var client_id ;

    function connect() {
        // 此处的domain.com 是指向register的那台服务器(上方服务器有记录)
        ws = new WebSocket("ws://domain.com:7373");
        ws.onopen = onopen;
        ws.onmessage = onmessage;
        ws.onclose = function() {
            console.log("连接关闭,定时重连");
            connect();
        };
        ws.onerror = function() {
            console.log("出现错误");
        };
    }
    function onmessage(e) {
        console.log("服务端推送",e.data);
        var data = JSON.parse(e.data);
        client_id = data['client_id'];
        switch(data['type']){
            // 绑定 client_id
            case 'init':
                // 客户端ID绑定
                console.log("收到workman返回的client_id,准备绑定laravel");
                loginInit(data);
                break;
            // 服务端 ping 客户端
            case 'ping':
                ws.send('{"type":"ping"}');
                break;
            case 'mp3':
                mp3Bf();
                break;
        }
    }
    function loginInit(data) {
        $.ajax({
            url:"api/wss/bindUid",
            type: "post",
            data:{
                id:"business",//"{{$user}}",
                type:"business",
                client_id:data['client_id']
            },
            cache:false,
            dataType: "json",
            beforeSend:function(XMLHttpRequest){
                console.log("开始绑定client_id");
            },
            success:function(pay){
                console.log("绑定成功",pay);
            },
            error: function (XMLHttpRequest,ex) {
            }
        });
    }
    function onopen() {

    }

    function mp3Bf(){
        var mp3 = document.getElementById('mp3');
        mp3.play();
    }

    setTimeout(function () {
        console.log("启动ws连接");
        connect();
    },1000);
</script>

遇到的问题,放在最后

1、阿里云服务器内的iptables和firewalld要关掉
若遇到 GatewayConnection Error : 1 ,connect fail xxxx 表示两台电脑并不互通,尝试执行命令测试是否还会出现 worker给的回复也是没法互通
systemctl stop iptables # 停止防火墙
systemctl stop firewalld # 停止firewalld规则
如果确定不会出现,可以直接禁用(直接使用阿里云的安全组吧)
systemctl disable firewalld # 禁用firewalld规则
2、 stream_socket_client(): unable to connect to tcp://127.0.0.1:1238 这个是第二台服务器框架文件中,没有修改为第一台内网的IP导致

心得

有了这次经验后,准备再优化成wss协议,即ws +ssl 提供小程序做websocket 

官网指导的部署方式

workman官方部署指导方式

本作品采用《CC 协议》,转载必须注明作者和本文链接
朝着梦,踏平坎坷
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!