thinkphp3.2完美整合workerman,并调用示例

AndyYang| 阅读:1689 发表时间:2017-12-02 16:38:48 phpworkerman
摘要:Workerman是一款纯PHP开发的开源高性能的PHP socket 服务器框架。支持TCP长连接,支持Websocket、HTTP等协议,支持自定义协议。拥有异步Mysql、异步Redis、异步Http、异步消息队列等众多高性能组件。
workerman地址:http://www.workerman.net/
下载对应的版本,演示下载的是linux版本。

解压放到thinkphp的模板目录里,目录结构:
|~Application/
| |+Cli/
| |+Common/
| |+Home/
| |+Runtime/
| |~Workerman/
| | |+Connection/
| | |+Events/
| | |+Lib/
| | |+Protocols/
| | |-Autoloader.php
| | |-composer.json
| | |-MIT-LICENSE.txt
| | |-README.md
| | |-WebServer.php
| | `-Worker.php
| |-index.html
| `-README.md
|+Public/
|+ThinkPHP/
|-cli.php
|-composer.json
|-index.php
`-README.md

Cli模块里的Library添加文件夹WmServices,专门用于存放workerman调用的类。目录结构:
|~Cli/
| |+Common/
| |+Conf/
| |~Controller/
| | | |-index.html
| | | |-IndexController.class.php
| | | `-WorkermanController.class.php
| |~Library/
| | `~WmServices/
| |   `-User.php

这里只添加了一个User.php,源码:
<?php
/**
 * workermen功能测试类
 * author webyang.net
 */
namespace Cli\Library\WmServices;

class User
{
    public function getName($id)
    {
        $result = array(
            'status'  => 0,
            'message' => '请求失败',
        );

        if($id) {
            $result = array(
                'status'  => 1,
                'name'    => 'webyang.net',
                'message' => '',
            );

            //数据库调用
            //$arr = M('Users')->find($id);
            //$result['name'] = $arr['username'];
        }

        return $result;
    }
}
Cli模块下WorkermanController.class.php是workerman的启动文件,源码:

<?php
namespace Cli\Controller;
use Workerman\Worker;

/**
 * workermen启动控制器
 * author webyang.net
 */
class WorkermanController{

    public function __construct()
    {
        $this->logPath = APP_PATH . 'Runtime/Logs/Cli/workerman.logs';
    }

    //启动workerman
    public function index(){

        //限制命令行
        if(!IS_CLI){
            die("access illegal");
        }

        require_once APP_PATH.'Workerman/Autoloader.php';

        Worker::$daemonize = true;//以守护进程运行
        Worker::$pidFile = '/data/logs/Worker/workerman.pid';//方便监控WorkerMan进程状态
        Worker::$stdoutFile = '/data/logs/Worker/stdout.log';//输出日志, 如echo,var_dump等
        Worker::$logFile = '/data/logs/Worker/workerman.log';//workerman自身相关的日志,包括启动、停止等,不包含任何业务日志

        $worker = new Worker('JsonNL://0.0.0.0:10086');//此处我使用内网ip
        $worker->name = 'Worker';
        $worker->count = 32;
        //$worker->transport = 'udp';// 使用udp协议,默认TCP
        $worker->onWorkerStart = function($worker){
            echo "Worker starting...\n";
        };

        $worker->onMessage = function($connection, $data){
            // 判断数据是否正确
            if(empty($data['class']) || empty($data['method']) || !isset($data['param_array']))
            {
                // 发送数据给客户端,请求包错误
                return $connection->send(array('code'=>400, 'msg'=>'bad request', 'data'=>null));
            }

            // 获得要调用的类、方法、及参数
            $class = $data['class'];
            $method = $data['method'];
            $param_array = $data['param_array'];

            // 判断类对应文件是否载入
            if(!class_exists($class))
            {
                $include_file = __DIR__ . "/Library/WmServices/$class.php";
                if(is_file($include_file))
                {
                    require_once $include_file;
                }

                $className = '\Cli\Library\WmServices\\'.$class;
                if(!class_exists($className))
                {
                    $code = 404;
                    $msg = $include_file.", class $className not found";
                    // 发送数据给客户端 类不存在
                    return $connection->send(array('code'=>$code, 'msg'=>$msg, 'data'=>null));
                }
            }

            // 调用类的方法
            try
            {
                $ret = call_user_func_array(array($className, $method), $param_array);
                if($ret['status'] == 0)
                {
                    //处理失败,记录log
                    $this->addLog('Class : '. $class.', method:'. $method.', params:'.json_encode($param_array).', err_message:'.$ret['message']);
                }
                // 发送数据给客户端,调用成功,data下标对应的元素即为调用结果
                return $connection->send(array('code'=>0, 'msg'=>'ok', 'data'=>$ret));
            }
                // 有异常
            catch(Exception $e)
            {
                // 发送数据给客户端,发生异常,调用失败
                $code = $e->getCode() ? $e->getCode() : 500;
                $this->addLog('Class : '. $class.', method:'. $method.', params:'.json_encode($param_array).', err_message:'.$e->getMessage());
                return $connection->send(array('code'=>$code, 'msg'=>$e->getMessage(), 'data'=>$e));
            }
        };

        $worker->onBufferFull = function($connection){
            echo "bufferFull and do not send again\n";
        };

        $worker->onBufferDrain = function($connection){
            echo "buffer drain and continue send\n";
        };

        $worker->onWorkerStop = function($worker){
            echo "Worker stopping...\n";
        };

        $worker->onError = function($connection, $code, $msg){
            echo "error $code $msg\n";
        };

        // 运行worker
        Worker::runAll();
    }

    protected function addLog($message, $type = 'ERROR', $exit = false)
    {
        file_put_contents($this->logPath, date('Y-m-d H:i:s').' '.$type.':'.$message.PHP_EOL, FILE_APPEND);
        if($exit)
        {
            exit;
        }
    }
}
Home模块添加调用的处理,目录结构:
|~Home/
| |+Common/
| |+Conf/
| |~Controller/
| | |-index.html
| | `-IndexController.class.php
| |~Library/
| | `-RpcClient.class.php

Home模块下Controller文件下添加IndexController.class.php,源码:
<?php
/**
 * workermen web测试控制器
 * author webyang.net
 */

namespace Home\Controller;
use Think\Controller;

class IndexController extends Controller {

    public function index() {
        $this->show('Thinkphp集成Workerman,更多请关注:<a href="http://webyang.net">webyang.net</a>','utf-8');
    }

    //访问此方法查看调用
    public function test() {

        $uid = 1;
        \Home\Library\RpcClient::config(C('RPC_ADDRESS'));
        $rpcClient = \Home\Library\RpcClient::instance('User');
        //var_dump($rpcClient);exit;

        // ==同步调用==
        $return = $rpcClient->getName($uid);
        var_dump($return);exit;

        // ==异步调用==
        $return = $rpcClient->asend_getName($uid);
        var_dump($return);

    }

}

另外注意下Home模块下的Library文件下RpcClient.class.php,这个也是官网下载的(json RPC远程调用框架 包Applications/JsonRpc/Client/RpcClient.class.php)。

启动workerman:php cli.php Workerman
访问 localhost/Index/test

如果thinkphp尚未支持cli运行,可以参考:http://www.webyang.net/Html/web/article_338.html
另外本文所有源码可以前往github下载,地址:https://github.com/yangsir/thinkphp_workerman

本文为AndyYang原创,转载请注明出处!
如果您觉得好,可以打赏作者:
如果您觉得累了,是否想看点美女养养眼:猛戳>>若兰网
如果您觉得皮了,是否想来点神吐槽:猛戳>>iPhone查询中

已有3条评论

昵称:
邮箱:

  • 最新评论

男人的小秘密2018-06-29 09:51:12
这个workerman与thinkPHP的实战项目视频不错,利用websocket协议实现了长连接,来做即时通讯,在线客服。在网易云课堂官网搜workerman即可。地址 : http://study.163.com/course/introduction/1005015012.htm?share=2&shareId=400000000388007
workerman2018-06-29 09:51:03
这个workerman与thinkPHP的实战项目视频不错,利用websocket协议实现了长连接,来做即时通讯,在线客服。在网易云课堂官网搜workerman即可。地址 : http://study.163.com/course/introduction/1005015012.htm?share=2&shareId=400000000388007
亮亮2018-06-28 18:39:43
这个workerman与thinkPHP的实战项目视频不错,利用websocket协议实现了长连接,来做即时通讯,在线客服。地址 http://study.163.com/course/introduction/1005015012.htm?share=2&shareId=400000000388007
iPhone查询中 - bbs.ipcxz.com 若兰网 - www.rolan.wang iPhone查询中 - bbs.ipcxz.com
反馈
微信订阅号