程序使用的 workerman/gateway-worker。
因为业务端需要大量调用 第三方接口,所以需要使用异步http。
最开始用的 workerman/http-client。 但是第三方接口兼容有问题,每几百个请求就有一个超时的。
最终经过反复对比,打算用 Swoole 的携程调用 curl 请求第三方接口。
然后再 App.php 添加了 // 使用Swoole事件循环 利用携程发送异步请求
Worker::$eventLoopClass = \Workerman\Events\Swoole::class;
之后启动后,终端包参数不兼容。
这个错误本身问题不大, 主要错误如下 就是参数问题。
手动修补 可以完美运行,但是这样只是临时解决方案。
请问有其他办法处理此错误吗?
TypeError: Workerman\Connection\TcpConnection::__construct(): Argument #3 ($remoteAddress) must be of type string, null given, called in /Users/wheng/phpDevelopment/UtalkLearn/vendor/workerman/workerman/src/Worker.php on line 2638 and defined in /Users/wheng/phpDevelopment/UtalkLearn/vendor/workerman/workerman/src/Connection/TcpConnection.php:369
{
"name": "wheng/utalk-learn",
"type": "project",
"require": {
"workerman/gateway-worker": "v4.0.0",
"symfony/yaml": "^6.3",
"php-amqplib/php-amqplib": "^3.6",
"predis/predis": "^2.2",
"overtrue/pinyin": "^5.3",
"google/protobuf": "^4.27",
"workerman/http-client": "^v3.0.3"
},
"autoload": {
"classmap": [
"src/model/"
],
"psr-4": {
"Proto\\Binarydata\\": "src/Proto/Binarydata/",
"GPBMetadata\\Src\\Protobuf\\": "src/GPBMetadata/Src/Protobuf/"
}
},
"repositories": [
{
"type": "composer",
"url": "https://mirrors.cloud.tencent.com/composer/"
}
],
"config": {
"audit": {
"abandoned": "report"
}
}
}
<?php
/**
* run with command
* php start.php start
*/
date_default_timezone_set('Asia/Shanghai');
ini_set('display_errors', 'on');
use Workerman\Worker;
if (strpos(strtolower(PHP_OS), 'win') === 0) {
exit("start.php not support windows, please use start_for_win.bat\n");
}
// 检查扩展
if (!extension_loaded('pcntl')) {
exit("Please install pcntl extension. See http://doc3.workerman.net/appendices/install-extension.html\n");
}
if (!extension_loaded('posix')) {
exit("Please install posix extension. See http://doc3.workerman.net/appendices/install-extension.html\n");
}
// 标记是全局启动
define('GLOBAL_START', 1);
require_once __DIR__ . '/../vendor/autoload.php';
// 加载所有Applications/*/start.php,以便启动所有服务
foreach (glob(__DIR__ . '/start*.php') as $start_file) {
require_once $start_file;
}
// 使用Swoole事件循环 利用携程发送异步请求
Worker::$eventLoopClass = \Workerman\Events\Swoole::class;
// 运行所有服务
Worker::runAll();
<?php
declare(strict_types=1);
class AsyncExecutorClass
{
/**
* 执行异步任务
* @param callable $task 任务逻辑
* @param callable $callback 回调函数 function($result, $error)
* @param mixed ...$args 任务参数
*/
public static function run(callable $task, callable $callback, ...$args): void
{
\Workerman\Coroutine::create(function () use ($task, $callback, $args) {
try {
$result = $task(...$args);
$callback($result, null);
} catch (\Throwable $e) {
$callback(null, $e);
}
});
}
}
(base) wheng@MacBook-Pro src % php App.php start
Workerman[App.php] start in DEBUG mode
-------------------------------------------------- WORKERMAN --------------------------------------------------
Workerman/5.1.1 PHP/8.1.32 (Jit off) Darwin/22.6.0
--------------------------------------------------- WORKERS ---------------------------------------------------
event-loop proto user worker listen count state
swoole tcp wheng BusinessWorker none 1 [OK]
swoole tcp wheng Gateway websocket://0.0.0.0:8383 2 [OK]
swoole tcp wheng Register text://0.0.0.0:2238 1 [OK]
---------------------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
TypeError: Workerman\Connection\TcpConnection::__construct(): Argument #3 ($remoteAddress) must be of type string, null given, called in /Users/wheng/phpDevelopment/UtalkLearn/vendor/workerman/workerman/src/Worker.php on line 2638 and defined in /Users/wheng/phpDevelopment/UtalkLearn/vendor/workerman/workerman/src/Connection/TcpConnection.php:369
Stack trace:
#0 /Users/wheng/phpDevelopment/UtalkLearn/vendor/workerman/workerman/src/Worker.php(2638): Workerman\Connection\TcpConnection->__construct(Object(Workerman\Events\Swoole), Resource id #50, NULL)
#1 /Users/wheng/phpDevelopment/UtalkLearn/vendor/workerman/workerman/src/Events/Swoole.php(288): Workerman\Worker->acceptTcpConnection(Resource id #45)
#2 [internal function]: Workerman\Events\Swoole->Workerman\Events\{closure}()
#3 {main}
可以使用 stream_socket_get_name 二次 获得这个 链接名字。。
能看得出来, 是 start_gateway.php 没有为 Swoole 提供兼容支持!!
我最初是头痛医头脚痛医脚, 在 TcpConnection 添加如下代码
添加兼容代码后,业务能跑起来, 但是偶尔还是报错!主要是 gateway 通信不畅。
看了 github 上一位仁兄的解决方案后,得到灵感。
在 start_gateway.php 添加代码如下
项目正常运转了。。。
gatewayWorker不支持协程,目前没有计划让gatewayWorker支持协程,主要是没有精力和动力。
原因:
$_SESSION
$_SERVER
,这些在协程中会造成变量污染问题,需要花很多精力重构。不过可以把业务都转移到webman来做,在webman里使用协程,gatewayWorker只做通讯。