top-think / think-worker Goto Github PK
View Code? Open in Web Editor NEWWorkerman extend for ThinkPHP
License: Apache License 2.0
Workerman extend for ThinkPHP
License: Apache License 2.0
请求地址 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下不正常
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系统没有以上错误
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 启动项目
访问绑定了中间件的控制器方法,第偶数次访问,中间件会失效
测试过路由上绑定中间件和控制器中间件,都无法正确运行
官方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'));
设置缓存方案。谁有更好地方案,请告知
think-worker现在没有发现对wss进行支持。建议官方加上说明文档或增加功能
vendor/topthink/think-worker/src/command/GatewayWorker.php这一个启动文件调取配置文件GatewayWorker.php是 有的大小写不匹配,会导致按照命令启动时,按照默认配置启动,没有按照配置文件中的参数启动,建议更新下。
Press Ctrl+C to stop. Start success.
类 \vendor\topthink\think-worker\src\command\Server.php 67-77行直接运行自定义类, 没有先判断是否开启守护进程模式
有些特性4.x版本才能用。
在自定义异常处理接管中"\app\common\exception\Http", 获取不到Request
试过:request()->baseUrl() 和 Request::baseUrl() 都拿不到,请问如何在异常处理中获取request内容呢?
框架版本: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的版本,并修改部分代码,谢谢~~~
nginx 时http反向代理时报 net::ERR_CONTENT_LENGTH_MISMATCH 200 (OK)错误
解决方法:
Application worker方法
$connection->send($content);
修改为
if (\strtolower($_SERVER['HTTP_CONNECTION']) === "keep-alive") {
$connection->send($content);
} else {
$connection->close($content);
}
支持thinkphp8吗
有示例demo吗?说明手册有吗?
workerman不用4.0么
系统: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']);
报错
启动后,浏览器不能正常的渲染css文件。
所有请求类型变为text/plain,不能正常解析对应的文件类型。
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
环境是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;
}
`
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',
];
<?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");
}
think-worker/src/Application.php
Line 44 in 9ba5433
这里未对 download()->send() 进行处理,在 tp6 中,File 返回会有一个 while 处理 ob 的过滤,会造成 内容输出到 cli 上。
建议在实例 Res 对象时使用 make 方式,可以通过注入的方式替换原有返回对象。
// 以下参数都可以在配置文件中的businessWorker参数中设置
$worker->name = 'BusinessWorker';
$worker->count = 1;
$worker->eventHandler = !empty($option['event_handler']) ? $option['event_handler'] : '\think\worker\Events';
//新版本的缺少上面的参数,导致onMessage错误
$this->option($worker, $option);
问题参数
js css 等文件输出全部都是:Content-Type:text/plain
然后标准的H5页面都不能正常显示
workerman对tp5.1的这个插件还是非常好用的,希望作者能够修复这个bug,后面大家就可以丢弃php-fpm了。
在此谢过先。
环境是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;
}
`
哪个老大回答一下,感谢呀
这两个bug能修复下么
第一次使用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;
/**
}
`
Request::token()
在worker下,每次请求获取的值是一样的
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
使用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
+ 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"
}
如截图的效果,使用官方的workerman组件,并不能正确返回预期的类型,比如css,并没有返回css,而是text/plain,js也是.
我是继承了官方组件http,重写了几行内容,但并非我重写的原因,官方组件的效果也是如此.
我的php版本是7.2.13,系统是fedora29.
求证是否存在此问题或如何修复,我临时打算重写为其他方法.
[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
安装了这扩展后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>`
这是什么问题呢?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.