Coder Social home page Coder Social logo

think-worker's Introduction

ThinkPHP 6.0 Workerman 扩展

安装

composer require topthink/think-worker

使用方法

HttpServer

在命令行启动服务端

php think worker

然后就可以通过浏览器直接访问当前应用

http://localhost:2346

linux下面可以支持下面指令

php think worker [start|stop|reload|restart|status]

workerman的参数可以在应用配置目录下的worker.php里面配置。

由于onWorkerStart运行的时候没有HTTP_HOST,因此最好在应用配置文件中设置app_host

SocketServer

在命令行启动服务端

php think worker:server

默认会在0.0.0.0:2345开启一个websocket服务。

如果需要自定义参数,可以在config/worker_server.php中进行配置,包括:

配置参数 描述
protocol 协议
host 监听地址
port 监听端口
socket 完整的socket地址

并且支持workerman所有的参数。 也支持使用闭包方式定义相关事件回调。

return [
	'socket' 	=>	'http://127.0.0.1:8000',
	'name'		=>	'thinkphp',
	'count'		=>	4,
	'onMessage'	=>	function($connection, $data) {
		$connection->send(json_encode($data));
	},
];

也支持使用自定义类作为Worker服务入口文件类。例如,我们可以创建一个服务类(必须要继承 think\worker\Server),然后设置属性和添加回调方法

<?php
namespace app\http;

use think\worker\Server;

class Worker extends Server
{
	protected $socket = 'http://0.0.0.0:2346';

	public function onMessage($connection,$data)
	{
		$connection->send(json_encode($data));
	}
}

支持workerman所有的回调方法定义(回调方法必须是public类型)

然后在worker_server.php中增加配置参数:

return [
	'worker_class'	=>	'app\http\Worker',
];

定义该参数后,其它配置参数均不再有效。

在命令行启动服务端

php think worker:server

然后在浏览器里面访问

http://localhost:2346

如果在Linux下面,同样支持reload|restart|stop|status 操作

php think worker:server reload

think-worker's People

Contributors

liu21st avatar nhzex avatar tinywan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

think-worker's Issues

php.exe app\think worker

启动后,浏览器不能正常的渲染css文件。
所有请求类型变为text/plain,不能正常解析对应的文件类型。

GatewayWorker这个是无效的吗?

我单独拿出来用,无法使用
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13 PHP version:7.0.19
------------------------ WORKERS -------------------------------
user worker listen processes status

Press Ctrl+C to stop. Start success.

http服务用nginx反向代理响应超时

环境是docker 默认的影响容器(最新版本)
在本地响应非常快
一使用nginx代理响应就超时
`
location /worker
{
proxy_pass http://php:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

    rewrite /worker/(.*) /$1 break;
    proxy_redirect off;
}

`

tp5.1使用workerman作为HttpServer运行时,用postman等访问异常

使用composer新建tp5.1项目并按照
https://www.kancloud.cn/manual/thinkphp5_1/354134
安装workerman,并能够使用命令正常启动。
启动后,使用浏览器能够正常看到tp5.1首页,但是换用postman、cURL等工具访问测试接口时,无论使用何种请求都会失败。
使用平台为win10,PHP版本7.4
若将浏览器中的请求复制到powershell中执行,则会报告如下错误:
Invoke-WebRequest : 服务器提交了协议冲突. Section=ResponseStatusLine
所在位置 行:1 字符: 1

  • Invoke-WebRequest -Uri "http://127.0.0.1:8088/" -Headers @{
  •   + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest],WebExce
      ption
      + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
    
    

复制的命令为:
Invoke-WebRequest -Uri "http://127.0.0.1:8088/" -Headers @{
"Cache-Control"="max-age=0"
"Upgrade-Insecure-Requests"="1"
"User-Agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36 Edg/81.0.416.58"
"Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9"
"Sec-Fetch-Site"="none"
"Sec-Fetch-Mode"="navigate"
"Sec-Fetch-User"="?1"
"Sec-Fetch-Dest"="document"
"Accept-Encoding"="gzip, deflate, br"
"Accept-Language"="zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"
"Cookie"="PHPSESSID=c66be331f3a7d74120d6b1a4"
}

Request::token()

Request::token()
在worker下,每次请求获取的值是一样的

think-worker 进程数据内存不共享?Redis也使用不了?

服务脚本代码:Server.php

<?php
/** .-------------------------------------------------------------------
 * |  Github: https://github.com/Tinywan
 * |  Blog: http://www.cnblogs.com/Tinywan
 * |-------------------------------------------------------------------
 * |  Author: Tinywan
 * |  Date: 2017/2/20
 * |  Time: 8:36
 * |  Mail: [email protected]
 * |  Created by PhpStorm. http://115.29.8.55
 * '-------------------------------------------------------------------*/

namespace app\socket\controller;

use think\worker\Server;
use Workerman\Lib\Timer;

class PushWorker extends Server
{
    protected $socket = 'websocket://0.0.0.0:12345';

    /**
     * Workerman 启动的回调,这里传递的是Worker对象
     * @param $worker
     */
    public function onWorkerStart($worker)
    {
        echo "onWorkerStart success\n";
    }

    /**
     * 当连接建立时触发的回调函数
     * @param $connection
     */
    public function onConnect($connection)
    {
        $connection->send("connection success\n");
        // 每10s 检查客户端是否有name属性
        Timer::add(10, function () use ($connection) {
            if (!isset($connection->name)) {
                $connection->close("auth timeout and close");
            }
        }, null, false);
    }

    /**
     * 接受发送消息
     * @param $connection
     * @param $data
     */
    public function onMessage($connection, $data)
    {
        if (!isset($connection->name)) {
            $data = json_decode($data,true);
            if (!isset($data['name']) || !isset($data['password'])) {
                return $connection->close("auth fail and close");
            }
            // 如果客户端name存在,mysql,这里使用动态给对象赋值属性name,标记该对象已经通过验证
            $connection->name = $data['name'];
            // 广播给所有用户,该用户加入
            return $this->broadcast($connection->name . " join \n");
        }
        // 简单的连接器
        return $this->broadcast($connection->name . ' said : ' . $data);
    }

    /**
     * 发送信息
     * @param $msg
     */
    public function broadcast($msg)
    {
        /**
         * 引入$worker 对象 在这里直接这样子使用 $this->worker 就可以了
         *  $worker->connections 为客户端连接的所有对象
         */
        foreach ($this->worker->connections as $connection) {
            if (!isset($connection->name)) {
                //忽略掉
                continue;
            }
            $connection->send($msg);
        }
    }


    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {
        $connection->send("connection close \n") ;
    }

    /**
     * Workerman 停止回调
     * @param $worker
     */
    public function onWorkerStop($worker)
    {
        echo "onWorkerStop success\n";
    }

    /**
     * 当客户端的连接上发生错误时触发
     * @param $connection
     * @param $code
     * @param $msg
     */
    public function onError($connection, $code, $msg)
    {
        echo "error $code $msg\n";
    }
}

客户端测试代码

var  wsServer = 'ws://127.0.0.1:12345/'; 
var  websocket = new WebSocket(wsServer); 
websocket.onopen = function (evt) { onOpen(evt) }; 
websocket.onclose = function (evt) { onClose(evt) }; 
websocket.onmessage = function (evt) { onMessage(evt) }; 
websocket.onerror = function (evt) { onError(evt) }; 
function onOpen(evt) { 
console.log("Connected to WebSocket server."); 
} 
function onClose(evt) { 
console.log("Disconnected"); 
} 

Worker进程 数据不共享

  • 1、开启4个进程(系统默认),两个人发送信息,互相看不到发送的数据
  • 2、开启1个进程,则发送的信息是OK的

http服务用nginx反向代理响应超时

环境是docker 默认的影响容器(最新版本)
在本地响应非常快
一使用nginx代理响应就超时
`
location /worker
{
proxy_pass http://php:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

    rewrite /worker/(.*) /$1 break;
    proxy_redirect off;
}

`

think-worker库中重写Cookie的saveCookie方法提示错误,第一次启动会报错

第一次使用worker启动tp6后出现这个情况:
{ "Code": 20, "Description": "异常", "Success": false, "Data": { "name": "think\\exception\\ErrorException", "file": "/mnt/d/webProject/huayuan_api_php/vendor/topthink/think-worker/src/Cookie.php", "line": 38, "message": "Declaration of think\\worker\\Cookie::saveCookie(string $name, string $value, int $expire, string $path, string $domain, bool $secure, bool $httponly): void should be compatible with think\\Cookie::saveCookie(string $name, string $value, int $expire, string $path, string $domain, bool $secure, bool $httponly, string $samesite): void",
原因为:
重写saveCookie方法时少了一个参数:string $samesite 希望加在官方库中,避免我们改vendor
`namespace think\worker;

use think\Cookie as BaseCookie;
use Workerman\Protocols\Http as WorkerHttp;

/**

  • Workerman Cookie类
    /
    class Cookie extends BaseCookie
    {
    /
    *
    • 保存Cookie
    • @access public
    • @param string $name cookie名称
    • @param string $value cookie值
    • @param int $expire cookie过期时间
    • @param string $path 有效的服务器路径
    • @param string $domain 有效域名/子域名
    • @param bool $secure 是否仅仅通过HTTPS
    • @param bool $httponly 仅可通过HTTP访问
    • @return void
      */
      protected function saveCookie(string $name, string $value, int $expire, string $path, string $domain, bool $secure, bool $httponly): void
      {
      WorkerHttp::setCookie($name, $value, $expire, $path, $domain, $secure, $httponly);
      }

}
`

输入php server.php start报错

安装了这扩展后thinkphp里面的star.php文件就会被删除,然后命令行执php server.php start会报错说star.php文件不存在:
`
D:\phpStudy\PHPTutorial\WWW\tp50>php server.php start
PHP Warning: require(D:\phpStudy\PHPTutorial\WWW\tp50/thinkphp/start.php): failed to open stream: No such file or directory in D:\phpStudy\PHPTutorial\WWW\tp50\server.php on line 8
PHP Stack trace:
PHP 1. {main}() D:\phpStudy\PHPTutorial\WWW\tp50\server.php:0

Warning: require(D:\phpStudy\PHPTutorial\WWW\tp50/thinkphp/start.php): failed to open stream: No such file or directory in D:\phpStudy\PHPTutorial\WWW\tp50\server.php on line 8

Call Stack:
0.4183 343688 1. {main}() D:\phpStudy\PHPTutorial\WWW\tp50\server.php:0

PHP Fatal error: require(): Failed opening required 'D:\phpStudy\PHPTutorial\WWW\tp50/thinkphp/start.php' (include_path='.;C:\php\pear') in D:\phpStudy\PHPTutorial\WWW\tp50\server.php on line 8
PHP Stack trace:
PHP 1. {main}() D:\phpStudy\PHPTutorial\WWW\tp50\server.php:0

Fatal error: require(): Failed opening required 'D:\phpStudy\PHPTutorial\WWW\tp50/thinkphp/start.php' (include_path='.;C:\php\pear') in D:\phpStudy\PHPTutorial\WWW\tp50\server.php on line 8

Call Stack:
0.4183 343688 1. {main}() D:\phpStudy\PHPTutorial\WWW\tp50\server.php:0

D:\phpStudy\PHPTutorial\WWW\tp50>`

然后我把star.php从tp5那里复制进thinkphp文件夹里面,报一下的错误:

`
D:\phpStudy\PHPTutorial\WWW\tp50>php server.php start

[think\exception\ErrorException]
Non-static method think\App::run() should not be called statically

Exception trace:
() at D:\phpStudy\PHPTutorial\WWW\tp50\thinkphp\start.php:18
think\Error::appError() at D:\phpStudy\PHPTutorial\WWW\tp50\thinkphp\start.php:18
require() at D:\phpStudy\PHPTutorial\WWW\tp50\server.php:8

D:\phpStudy\PHPTutorial\WWW\tp50>`

这是什么问题呢?

模块中间件 使用问题

请求地址 index/index/login
文件存放 地址 index/index/v1/login
通过模块中间件转向,让 index/index/login 调用 index/index/v1/login
第一次请求 是正常的
打印 \thinkphp\library\think\App.php 文件 run 方法 里面的 $dispatch 变量,中间件在 ["think\Middleware"] =》queue =》 route 下标是0
第二次 请求 报错 打印 \thinkphp\library\think\App.php 文件 run 方法 里面的 $dispatch 变量,中间件在 ["think\Middleware"] =》queue =》 route 下标是1
在Nginx下是正常的,workerman下不正常

print_r输出问题

function sqlite(){
print_r($_SERVER);
$ds = Db::query('select EmployeeID,FirstName,LastName from Employees');
return $this->fetch('sqlite',[
'data'=>$ds
]);
}

sqlite里print_r输出data变量,但页面上会显示$_SERVER的值,按理$_SERVER的值是打印在控制台

php think worker:server reload 无效?

我就是加个日志 然后reload 日志根本没有生效 restart 生效了 啥区别啊 你们生产环境下都是怎么使用的?比如更新代码了 是restart?
image

5.1 无法读取配置,报错:Undefined index: app_path

系统:win10
PHP:7.2
版本:topthink/think-worker": "2.0.*
启动:php think worker
报错:Undefined index: app_path

vendor\topthink\think-worker\src\command\Worker.php 63 行 $this->config = config('worker'); 读取不到配置,导致 $worker->setAppPath($this->config['app_path']);报错

gateway组件更新后系统自动不起来了

[Exception]

Workerman[think] stopping ...
PHP Fatal error: Declaration of think\worker\Application::runningInConsole() must be compatible with think\App::runningInConsole(): bool in /www/wwwroot/th.tiantapay.com/vendor/topthink/think-worker/src/Application.php on line 107

Fatal error: Declaration of think\worker\Application::runningInConsole() must be compatible with think\App::runningInConsole(): bool in /www/wwwroot/th.tiantapay.com/vendor/topthink/think-worker/src/Application.php on line 107
worker[notify:4182] exit with status 64000
worker[Register:4314] exit with status 256

[think\exception\ErrorException]
Declaration of think\worker\Application::runningInConsole() must be compatible with think\App::runningInConsole(): bool

Exception trace:
() at /www/wwwroot/th.tiantapay.com/vendor/topthink/think-worker/src/Application.php:107
think\initializer\Error->appShutdown() at n/a:n/a

bug

protected $socket = 'websocket://0.0.0.0:2346';
protected $processes = 1;
public $uidConnections = array();

public function onWorkerStart($worker)
{
    echo 'work start!';
    //开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符
    $inner_text_worker = new Worker('text://0.0.0.0:5678');
    $inner_text_worker->onMessage = function($connection, $buffer)
    {
        global $worker;
        // $data数组格式,里面有uid,表示向那个uid的页面推送数据
        $data = json_decode($buffer, true);
        $uid = $data['uid'];
        // 通过workerman,向uid的页面推送数据
        $ret = $this->sendMessageByUid($uid, $buffer);
        // 返回推送结果
        $connection->send($ret ? 'ok' : 'fail');
    };
    // ## 执行监听 ##
    $inner_text_worker->listen();
} `

`
onWorkerStart 内部启动worker会报错,貌似陷入死循环

work start!Workerman[server.php] start in DEBUG mode
Workerman[server.php] already running
WORKER EXIT UNEXPECTED
work start!Workerman[server.php] start in DEBUG mode
Workerman[server.php] already running
WORKER EXIT UNEXPECTED
work start!Workerman[server.php] start in DEBUG mode
Workerman[server.php] already running
WORKER EXIT UNEXPECTED
work start!Workerman[server.php] start in DEBUG mode
Workerman[server.php] already running
WORKER EXIT UNEXPECTED
work start!Workerman[server.php] start in DEBUG mode
Workerman[server.php] already running
WORKER EXIT UNEXPECTED
work start!Workerman[server.php] start in DEBUG mode
Workerman[server.php] already running
WORKER EXIT UNEXPECTED

无法运行,按照官方手册直接运行是提示命名空间已被占用。

现象:在使用think-worker v2.0.11 按照官方手册安装后直接运行提示命名空间已被占用,如下图:
image
原因:注册命令顺序的问题。在v2.0.10版本使用正常 v2.0.11出现异常。需要调整命令注册的顺序,文件路径:vender/topthink/think-worker/src/command.php

image
改成
image即可正常运行。
修改后的结果:
image

finfo_file不能正确按照更好的预期运行,不能识别css,js等mimeType

如截图的效果,使用官方的workerman组件,并不能正确返回预期的类型,比如css,并没有返回css,而是text/plain,js也是.

我是继承了官方组件http,重写了几行内容,但并非我重写的原因,官方组件的效果也是如此.

我的php版本是7.2.13,系统是fedora29.

求证是否存在此问题或如何修复,我临时打算重写为其他方法.

tp5.1 启动报错

windows系统启动php think work:server
报错信息如下:
[think\exception\ErrorException] Cannot use Workerman\Worker as Worker because the name is already in use
解决办法:
找到目录:
\vendor\topthink\think-worker\src\command\Server.php

找到命名空间:
use Workerman\Worker;
修改为:
use Workerman\Worker as Worker2;
紧接着修改 119 行与 126的 worker 改为 Worker2

找到目录:
\vendor\topthink\think-worker\src\command\GatewayWorker.php

找到命名空间
use Workerman\Worker;
修改为:
use Workerman\Worker as Worker3;

linux centos系统没有以上错误

gatewayworker启用ssl

think-worker现在没有发现对wss进行支持。建议官方加上说明文档或增加功能

thinkphp8 使用think-worker扩展,提示workerman版本低的问题,希望提高对workerman高版本的支持

框架版本:thinkphp8
php版本:>=php8.0

在liunx下执行命令出错
报错1:执行php think hello start --mode d
Implicit conversion from float 2999991.1785125732 to int loses precision
解决:Workerman\Events\Select::class -> loop() 274行_selectTimeout属性传递到usleep(int)函数精度问题导致,使用int强转一下 usleep((int)$this->_selectTimeout)

报错2:fclose(): Argument #1 ($stream) must be of type resource, null given
解决:vendor/workerman/workerman/Worker.php,1245-1248行的fclose()函数加上判断
if ($STDOUT) {
\fclose($STDOUT);
}
if ($STDERR) {
\fclose($STDERR);
}
if (is_resource(\STDOUT)) {
\fclose(\STDOUT);
}
if (is_resource(\STDERR)) {
\fclose(\STDERR);
}

希望尽快提高workerman的版本,并修改部分代码,谢谢~~~

onConnect中无法推送消息

public function onConnect($connection)
    {
        echo "new connection from ip " . $connection->getRemoteIp() . "\n";
        $connection->send('receive success');
    }
    public function onMessage($connection, $data)
    {
         $connection->send($data);
    }

onMessage可以发送消息;onConnect无法推送消息,但是在客户端cli可以打印IP

Accessing static property Workerman\Worker::$pidFile as non static

1、版本:5.1
2、使用 自定义服务类

return [
	'worker_class'	=>	'app\http\Worker',
];

3、错误信息

# php think worker:server
Starting Workerman server...

  [think\exception\ErrorException]
  Accessing static property Workerman\Worker::$pidFile as non static  

4、配置选项

/**
* 配置选项
* @var array
*/
protected $option = [
    'count'		=> 4, // 设置当前Worker实例启动多少个进程
    'name'		=> 'resty_sokcet', 
    'user'		=> 'www-data',
    'pidFile'	=> '/www.tinywan.com/runtime/workerman_sokcet.pid',
    'logFile'	=> '/www.tinywan.com/runtime/workerman.log',
];

关于worker项目运行目录和web项目运行目录不一致导致的runtime文件写入&读取异常问题

官方worker运行在根目录,http运行在public目录
例如think-orm中的cache,由于默认的本地缓存path是相对路径(如下),导致读写失败

// 驱动方式
//文件缓存
        'file'  => [
                // 驱动方式
                'type'       => 'File',
                // 缓存保存目录
                'path'       => '../runtime/cache',
                // 缓存前缀
                'prefix'     => '',
                // 缓存有效期 0表示永久缓存
                'expire'     => 0,
                // 缓存标签前缀
                'tag_prefix' => 'tag:',
                // 序列化机制 例如 ['serialize', 'unserialize']
                'serialize'  => [],
        ],

可以修改path为空或者新建一个驱动方式(如下)

 // 驱动方式
'fileWK'  => [
            'type'       => 'File',
            // 缓存保存目录
            'path'       => '',
            // 缓存前缀
            'prefix'     => '',
            // 缓存有效期 0表示永久缓存
            'expire'     => 0,
            // 缓存标签前缀
            'tag_prefix' => 'tag:',
            // 序列化机制 例如 ['serialize', 'unserialize']
            'serialize'  => [],
]

然后使用
Db::setCache(Cache::store('fileWK'));设置缓存方案。谁有更好地方案,请告知

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.