• easyswoole学习记录


    php-fpm的工作方式

    php-fpm就是php-fastcgi进程管理器

    主要工作的就是mastr进程,主要和linux进行一个协调,当请求从nginx到fpm的时候,master会把请求交给自己下面管理的子进程一个池模型,

    问题:一个work进程内只会处理一个请求,也就是说这个进程内在同一时刻只会处理一个request请求,不会处理多个,所以一台服务器的并发数就取决于服务器开启了多少个work进程数决定的,假如开启了100个进程,剩下的所有请求,就只能在后面等着,排着队。所以这也是php-fpm并发性能不好的根本原因,如果无限制的开启大量进程,那么电脑的cpu性能会耗费在进程的上下文切换上,会带来更大开销。

    Swoole进程模型以及生命周期

    Swoole不简单是一个php扩展,它完全不依赖于php-fpm,它是一种长驻进程多进程模型,就是说每次一个request请求完毕,swoole的work进程不会清理,php文件是常驻进程内的,而php-fpm是每次请求都会清理work进程,重新加载php文件,这也是为什么swoole服务修改代码后,必须重新加载服务才会生效的原因。在使用swoole时候需要注意它的生命周期,不要在onrequest以外定义全局变量,防止内存泄漏,swoole官方有提供max_request参数,防止内存泄漏。

    swoole协程

    Php work 进程是同步阻塞的,php代码从上刀下执行,如果期间有io操作那么这个请求就会阻塞卡在那儿等待io操作完成,然而work进程是有限的,假如启动了3个work进程,一个request请求是1秒,那么这一秒最多处理3个请求,这也就极大的限制了系统的并发量。携程就是可以极大的利用服务器的cpu资源开销,当一个request请求中间有io等耗时操作,就可以使用携程把这个操作挂起,这样work进程就不会阻塞等待,继续接受下一个请求。它是一个交替执行的过程。

    controller 类定义私有属性需要注意每次request属性是不会初始化的。

    如果需要初始化加入easyswoole框架的gc方法

    协程+Channel+WaitGroup实现并发编程

    1. include_once '../vendor/autoload.php';
    2. use Swoole\Coroutine as co;
    3. go(function (){
    4. $time = time();
    5. $chan = new co\Channel(12);//管道
    6. $wait = new \EasySwoole\Component\WaitGroup(12);
    7. //模拟查询
    8. for($i=1;$i<=12;$i++) {
    9. $wait->add();//+1
    10. go(function () use ($wait,$chan,$i){
    11. co::sleep(rand(1,1));
    12. $chan->push("第个{$i}月的数据");
    13. $wait->done();//-1
    14. });
    15. }
    16. $wait->wait();//等待
    17. while(true) {
    18. if($chan->isEmpty()) {
    19. break;
    20. }
    21. $res = $chan->pop();//输出
    22. error_log($res . PHP_EOL,3,'channel.log');
    23. }
    24. error_log('----------------------'. PHP_EOL,3,'channel.log');
    25. error_log(time()-$time,3,'channel.log');
    26. });

    自定义进程,并向自定义进程发送信号

    1 自定义进程类

    1. namespace App\HttpController\Test;
    2. use EasySwoole\Component\Process\AbstractProcess;
    3. use Swoole\Coroutine;
    4. use Swoole\Process;
    5. class ProcessOne extends AbstractProcess
    6. {
    7. private $data = [];
    8. /**
    9. * 业务逻辑
    10. * @param $arg
    11. */
    12. protected function run($arg)
    13. {
    14. // TODO: Implement run() method.
    15. $processName = $this->getProcessName(); // 获取 注册进程名称
    16. $swooleProcess = $this->getProcess(); // 获取 注册进程的实例 \Swoole\Process
    17. $processPid = $this->getPid(); // 获取 当前进程 Pid
    18. $args = $this->getArg(); // 获取 注册进程时传递的参数
    19. //接收参数
    20. $size = $arg['size'];
    21. go(function () use ($size) {
    22. while (true){
    23. //写入数据
    24. $this->data[] = 'easyswoole';
    25. if(count($this->data) > $size) {
    26. //判断参数则进行报警
    27. echo '报警提示' . PHP_EOL;
    28. }
    29. var_dump(count($this->data));
    30. //sleep 1
    31. Coroutine::sleep(1);
    32. }
    33. });
    34. }
    35. /**
    36. * 信号接收方法
    37. * @param Process $process
    38. */
    39. protected function onPipeReadable(Process $process)
    40. {
    41. // 该回调可选
    42. // 当主进程对子进程发送消息的时候 会触发
    43. $recvMsgFromMain = $process->read(); // 用于获取主进程给当前进程发送的消息
    44. var_dump('收到主进程发送的消息: ');
    45. var_dump($recvMsgFromMain);
    46. switch ($recvMsgFromMain) {
    47. case 'clear':
    48. $this->data = [];
    49. break;
    50. default:
    51. echo '命令非法';
    52. }
    53. }
    54. protected function onException(\Throwable $throwable, ...$args)
    55. {
    56. // 该回调可选
    57. // 捕获 run 方法内抛出的异常
    58. // 这里可以通过记录异常信息来帮助更加方便地知道出现问题的代码
    59. }
    60. protected function onShutDown()
    61. {
    62. // 该回调可选
    63. // 进程意外退出 触发此回调
    64. // 大部分用于清理工作
    65. }
    66. protected function onSigTerm()
    67. {
    68. // 当进程接收到 SIGTERM 信号触发该回调
    69. }
    70. }

    2 EasySwooleEvent.php

    1. public static function mainServerCreate(EventRegister $register)
    2. {
    3. $processConfig = new \EasySwoole\Component\Process\Config([
    4. 'processName' => 'test1', // 设置 自定义进程名称
    5. 'processGroup' => 'Custom', // 设置 自定义进程组名称
    6. 'arg' => [
    7. 'size' => '3'
    8. ], // 【可选参数】设置 注册进程时要传递给自定义进程的参数,可在自定义进程中通过 $this->getArg() 进行获取
    9. 'enableCoroutine' => true, // 设置 自定义进程自动开启协程
    10. ]);
    11. $obj = new ProcessOne($processConfig);
    12. \EasySwoole\Component\Process\Manager::getInstance()->addProcess($obj);
    13. \EasySwoole\Component\Di::getInstance()->set('test1', $obj->getProcess());

    3 发送信号方法

    1. $customProcess = Di::getInstance()->get('test1');
    2. // 向自定义进程中传输信息,会触发自定义进程的 onPipeReadable 回调
    3. $customProcess->write('clear');

    未完待续。。。 

  • 相关阅读:
    vuInhub靶场实战系列--Kioptrix Level #4
    CRM与销售能力自动化SFA的关系
    1.4.17 实验17:ASBR
    C++实战演练---负载均衡在线oj项目预热
    发过的朋友圈怎么再快速发一次?
    OpenCV之cv::createTrackbar
    2022/9/17(cf·div2)https://codeforces.com/contest/1728
    haproxy,nginx,keepalived综合运用
    项目复习:基于TCP的文件服务器
    道可云元宇宙每日资讯|德国研发元宇宙虚拟战场训练平台
  • 原文地址:https://blog.csdn.net/weixin_40896800/article/details/126490620