关于异步邮件发送服务的思路,和 Swoole 异步任务的一个问题
项目只用了swoole原生,使用Swoole
的异步Redis Server
来触发异步任务,但是在服务在task_worker_num
的数量的次数调用后,就会挂掉。
这个问题是执行任务的work进程没有处理好的问题么。
另外,目前邮件服务我挂载到了容器中,目前是用的DI容器,根据redis
的key value
动态的去调用模板,这样Swoole Server
来根据模板从容器中取出对应的Emailer
。 会是DI
容器的坑么?(smtp服务器已经协程化)
折腾了一天之后 发现可能是我在发送邮件后 会销毁掉smtp服务端的类中的属性,但是这个问题为什么在第最大任务进程数量
次数后才出现。
恳求各位哥哥姐姐们给个思路,指点一下。。。
使用redis-cli
调用
mail CreateCustomerNotify yichu4 123456 xx@lunion.com.cn
服务端调试
task_work_num 设置为了2
$this->server = $container->get('Kernel');
$this->server->set([
'task_worker_num' => 2,
'worker_num' => 2,
]);
服务的setHandler
方法 处理redis的一个key
public function mailHandle($fd, $data)
{
$taskID = $this->server->task($data);
$this->logger->Info(sprintf('Create Task ID is %s',$taskID));
$template = $data[0] ?? null;
if(null === $template){
return $this->server->send($fd, Server::format(Server::ERROR, 'Template is empty'));
}
$emailAddress = $data[1] ?? null;
if(null === $emailAddress){
return $this->server->send($fd, Server::format(Server::ERROR, 'Email is empty'));
}
try {
$this->container->make('Mail',[
'template' => $template
]);
} catch (TemplateNotFoundException $exception) {
return $this->server->send($fd, Server::format(Server::ERROR, 'Template ['.$template.']is not ready yet'));
}
if (false === $taskID) {
return $this->server->send($fd, Server::format(Server::ERROR));
} else {
return $this->server->send($fd, Server::format(Server::INT, 1));
}
}
任务处理方法
public function onTask($server, $taskID, $workID, $data)
{
$template = $data[0] ?? null;
if(null === $template){
$this->logger->error('Template is empty');
}
$emailAddress = $data[1] ?? null;
if(null === $emailAddress){
$this->logger->error('Email is empty');
}
$this->logger->Info(sprintf('Handle Task ID is %s',$taskID));
$this->logger->Info(sprintf('Handle Task Work ID is %s',$workID));
$this->logger->Info(sprintf('Use %s Mail-Template, send to %s,Server is loading',$template, $emailAddress));
$Mailer = $this->container->make('Mail',[
'template' => $template
]);
array_shift($data);
try{
$result = $Mailer->sendMail(...$data);
}catch (\Exception $e){
$this->logger->error(sprintf('Use %s Mail-Template, send to %s, the task is failed ! Look at %s :',$template, $data[2], $e->getMessage()));
}
$this->logger->Info(sprintf('Use %s Mail-Template, send to %s, Success!',$template, $data[2]));
return true;
}
果然第3次运行 就挂了
➜ \[0_0]/ yichu ~/workspace/MessageCenter git:(master) ✗ php bin/start.php
Here Task ID is 0
Here Work ID is 1
string(41) "App\Business\Message\CreateCustomerNotify" #这里是我打印的模板名称变量
Here Task ID is 1
Here Work ID is 1
string(41) "App\Business\Message\CreateCustomerNotify"
Here Task ID is 2
Here Work ID is 1
NULL #没了???? 我好菜
PHP Fatal error: Uncaught TypeError: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php:51
Stack trace:
#0 /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php(51): call_user_func(Array, 'yichu4', '123456', 'xx@lunion.co...')
#1 /mnt/d/ubuntu/space/MessageCenter/src/Server/App.php(84): App\Server\MailCenter->sendMail('yichu4', '123456', 'xx@lunion.co...')
#2 [internal function]: App\Server\App->onTask(Object(Swoole\Redis\Server), 2, 1, Array)
#3 /mnt/d/ubuntu/space/MessageCenter/src/Server/App.php(92): Swoole\Redis\Server->start()
#4 /mnt/d/ubuntu/space/MessageCenter/bin/start.php(14): App\Server\App->start()
#5 {main}
thrown in /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php on line 51
Fatal error: Uncaught TypeError: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php:51
Stack trace:
#0 /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php(51): call_user_func(Array, 'yichu4', '123456', 'xx@lunion.co...')
#1 /mnt/d/ubuntu/space/MessageCenter/src/Server/App.php(84): App\Server\MailCenter->sendMail('yichu4', '123456', 'xx@lunion.co...')
#2 [internal function]: App\Server\App->onTask(Object(Swoole\Redis\Server), 2, 1, Array)
#3 /mnt/d/ubuntu/space/MessageCenter/src/Server/App.php(92): Swoole\Redis\Server->start()
#4 /mnt/d/ubuntu/space/MessageCenter/bin/start.php(14): App\Server\App->start()
#5 {main}
thrown in /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php on line 51
[2020-07-17 17:56:35 ^3455.2] ERROR php_swoole_server_rshutdown (ERRNO 503): Fatal error: Uncaught TypeError: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php:51
Stack trace:
#0 /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php(51): call_user_func(Array, 'yichu4', '123456', 'xx@lunion.co...')
#1 /mnt/d/ubuntu/space/MessageCenter/src/Server/App.php(84): App\Server\MailCenter->sendMail('yichu4', '123456', 'xx@lunion.co...')
#2 [internal function]: App\Server\App->onTask(Object(Swoole\Redis\Server), 2, 1, Array)
#3 /mnt/d/ubuntu/space/MessageCenter/src/Server/App.php(92): Swoole\Redis\Server->start()
#4 /mnt/d/ubuntu/space/MessageCenter/bin/start.php(14): App\Server\App->start()
#5 {main}
thrown in /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php on line 51
[2020-07-17 17:56:35 $3454.0] WARNING swManager_check_exit_status: worker#2[pid=3455] abnormal exit, status=255, signal=0
本作品采用《CC 协议》,转载必须注明作者和本文链接
我很久之前写个一个开源项目,用来解决异步场景超级好用 github.com/star7th/htq
用htq几乎对php业务代码无侵入。不用考虑互相干扰啊生命周期啊回调之类的
call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in /mnt/d/ubuntu/space/MessageCenter/src/Server/MailCenter.php:51
这里就说明了你代码的问题了啊