说明

针对目前项目中需要实时通讯的场景,我们调研了一些第三方的库,目前比较成熟稳定的为基于workman的gatewaywork比较适合。本文主要针对如何集成gatewaywork进行说明。

安装

首先通过 composer 安装

composer require topthink/think-worker

Nginx配置

location / {
    if (!-e $request_filename){
        rewrite  ^(.*)$  /index.php?s=$1  last;   break;
    }
}
# websockets
location =/websocket{
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Nginx-Proxy true;
    proxy_pass https://localhost:21123;
    proxy_connect_timeout 86400s;
    proxy_read_timeout 86400s;
    proxy_send_timeout 86400s;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}

SSL配置

gateway_worker.php

<?php
return[
    'protocol'              => 'websocket', // 协议 支持 tcp udp unix http websocket text
    'host'                  => '0.0.0.0', // 监听地址
    'port'                  => 21123, // 监听端口
    'socket'                => '', // 完整监听地址
    'ssl'                    =>    true,
    'transport'             =>'ssl',
    'context'               => [
        'ssl' => [ 
            'local_cert' => 'fullchain.pem', //证书文件的存放路径(请改成自己的路径)
            'local_pk' => 'privkey.pem', //证书私钥的存放路径(请改成自己的路径)
            'verify_peer' => false,
        ]
    ], // socket 上下文选项
    'register_deploy'       => true, // 是否需要部署register
    'businessWorker_deploy' => true, // 是否需要部署businessWorker
    'gateway_deploy'        => true, // 是否需要部署gateway

    // Register配置
    'registerAddress'       => '127.0.0.1:21124',

    // Gateway配置
    'name'                  => 'runnerPaotui',
    'count'                 => 4,
    'lanIp'                 => '127.0.0.1',
    'startPort'             => 21125,
    'daemonize'             => true,
    'pingInterval'          => 30,//心跳检测,默认30秒,监测不到断开链接
    'pingNotResponseLimit'  => 1,//0服务端主动发送心跳(不推荐,默认) 1客户端定时发送心跳(推荐,设为1后客户端需做主动定时向服务端发包处理)
    'pingData'              => '{"type":"ping"}',//服务端定时向客户端发送的数据

    // BusinsessWorker配置
    'businessWorker'        => [
        'name'         => 'BusinessWorker',
        'count'        => 1,
//        'eventHandler' => '\think\worker\Events',
        'eventHandler' => '\api\wxapp\controller\Events',
    ],
];

worker.php


<?php
return [
    // 扩展自身需要的配置
    'host'                  => '0.0.0.0', // 监听地址
    'port'                  => 21128, // 监听端口
    'root'                  => '', // WEB 根目录 默认会定位public目录
    'app_path'              => '', // 应用目录 守护进程模式必须设置(绝对路径)
    'file_monitor'          => false, // 是否开启PHP文件更改监控(调试模式下自动开启)
    'file_monitor_interval' => 2, // 文件监控检测时间间隔(秒)
    'file_monitor_path'     => [], // 文件监控目录 默认监控application和config目录

    // 支持workerman的所有配置参数
    'name'                  => 'thinkphp',
    'count'                 => 4,
    'daemonize'             => false,
    'pidFile'               => '',
];

worker_server.php


<?php
return [
    'protocol'       => 'websocket',
    // 'pidFile'        => Env::get('runtime_path') . 'worker.pid',
    'worker_class'   => 'api\wxapp\controller\WorkerController', // 自定义Workerman服务类名 支持数组定义多个服务
];

启动

使用 php think worker:gateway 启动 扩展中的 GatewayWorker 即可 
 
php think worker:gateway start  #启动
php think worker:gateway stop   #停止
php think worker:gateway reload #重新加载

测试脚本


<!DOCTYPE html>  
<html>  
<head>  
<title>HTML5</title>  
<meta charset="utf-8" />  
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>  
<script>  
$(function() {      
    var socket;  
    var readyState = ["connecting", "connected", "closing", "closed"];  
    /* 打开连接事件 */  
    $("button:eq(0)").click(function() {  
        try {  
             /* 连接 */  
            //  socket = new WebSocket("ws://*");  
             socket = new WebSocket("wss://demo.com/websocket");
             /* 绑定事件 */  
             socket.onopen = function() {  
                 $("#msg").html("连接成功...");  
             };  
               
            socket.onmessage = function(e) {  
                 $("#msg").html($("#msg").html() + "<br />" + e.data);  
             };  
               
             socket.onclose = function() {  
                 $("#msg").html($("#msg").html() + "<br />关闭连接...");  
             };  
        } catch(exception) {  
            $("#msg").html($("#msg").html() + "<br />有错误发生");  
        }  
    });  
      
    /* 发送数据事件 */  
    $("button:eq(1)").click(function() {  
        /* 检查文本框是否为空 */  
        if($("#data").val() == "") {  
            alert("请输入数据!");  
            return;  
        }  
          
        try {  
            socket.send($("#data").val());  
            $("#msg").html($("#msg").html() + "<br />发送数据:" + $("#data").val());  
        } catch (exception) {  
            $("#msg").html($("#msg").html() + "<br />发送数据出错");  
        }  
          
        /* 清空文本框 */  
        $("#data").val("");  
    });  
      
    /* 断开连接 */  
    $("button:eq(2)").click(function() {  
        socket.close();  
    });  
});  
</script>  
</head>  
  
<body>  
<h1>WebSocket示例</h1>  
<input type="text" id="data" />  
<button>打开连接</button>  
<button>发送数据</button>  
<button>关闭连接</button>  
<p id="msg"></p>  
</body>  
</html>

郑州码农
1 声望1 粉丝

一个热爱code的郑州码农