基于名字自动发布之多进程(3)

*爱你&永不变心* 提交于 2019-12-10 11:49:30

基于名字自动发布之多进程(3)

项目地址: https://gitee.com/lookingdreamer/RexDeploy_v1

流程图

为什么选择多进程?

随着应用越来越多,单进程的运行已经严重的拖慢了速度.所以多进程就应运而生了.为什么不是多线程?因为rex本身的框架都是采用的多进程.且多进程相对多线程来说要稳定得多.项目本身也去尝试了多线程,但在兼容性上出现了问题.索性就全部按照多进程去设计和开发.

多进程构建思路

  • 日常生活的比喻

    假设商店最大容纳人数为5个人,一共有12个人.只能等前面5个人进去出来之后,后面的5个人才能进入,不足5个人的全部进去

  • 转换为数学问题

       将12个人编号为0到12号

#!/bin/perl

my ($start,$maxchild,$max,%hash_pids) = (0,5,12) ;
for(my $g=0; $g < $max ;){
    $startIndex =  $g ; 
    $endIndex = $g + $maxchild;   
    if($endIndex > $max){
        $endIndex = $max;
    }
    $start = $start + 1 ;
    print("\r\n开始第$start次并发控制:($startIndex - $endIndex) \r\n");
    for($i=$startIndex;$i<$endIndex;$i++){
        select(undef, undef, undef, 0.25);
        my $child=fork();
        if($child){ 
            print("\r\n父进程PID:$$ 子进程PID:$child\r\n");
            $hash_pids{$child} = $child;  
        }else{ 
          # 在子进程中执行相关动作
          print("开始执行子进程,进程序号:$i \r\n");
          sleep(5);
          print("结束执行子进程,进程序号:$i  \r\n");
          exit 0;
        }
    }

    #收割并等待子进程完成
    while (scalar keys %hash_pids) { 
      my $kid = waitpid(-1, WNOHANG); 
      if ($kid and exists $hash_pids{$kid}) {
        delete $hash_pids{$kid};
      }
    }
    print("结束第$start次并发控制:($startIndex - $endIndex) \r\n"); 
    $g = $g + $maxchild;
}

  • 转换到关键词上

        比如我传名字关键词test1,test3,test4,abc,cde….,因为每个应用的名字是唯一的,我将名字添加到一个索引数组中 如上0-5对应就是索引数组的第1个到第5个,意味着第一次执行前5个名字的服务

my @ks = split(/ /, $k);
  • 关键点

        利用系统fork()创建多进程; 利用waitpid无阻塞的模式收割进程waitpid(-1, WNOHANG); 利用hash保存进程id

  • 多进程间通讯

        多进程间通讯一般分为消息队列、共享内存段以及信号量3种方式.通常情况下共享内存段和信号配合使用.在我的项目主要是通过IPC::Shareable模块来实现进程间的数据共享

use IPC::Shareable;
......
my @shared;
my $mainProces = $$;
#创建信号
my $ipch = tie @shared,   'IPC::Shareable',
                       "foco",
                       {  create    => 1,
                          exclusive => 'no',
                          mode      => 0666,
                          size      => 1024*512,
                          # destroy   => 'yes',
                       };
......
my $single = {"mainProcess"=>"$mainProces","data"=>$runres}  ; 
#持锁            
$ipch->shlock;
#保存数据到全局内存
push @shared, $single ;
#解锁
$ipch->shunlock;                           
  • 获取当前主进程开辟的子进程的所有数据

        保存到全局内存中的数组变量@shared,有可能含有其他主进程创建的子进程.所以在取出当前进程创建的子进程数据,我们需要做1个区分.因为在保存数据的时候,我们把当前的主进程ID也保存进去了.只要内存数据的数组元素的主进程PID等于主进程就是该进程创建的子进程数据.如下

......
my @mainShared;
my $u = 0 ;
my @deleteArray;
Rex::Logger::info("当前全局内存存储变量数量: $allCount");
for (my $var = 0; $var < $allCount; $var++) {
   my $process = $shared[$var]->{"mainProcess"};
   if ( "$process" eq "$mainProces" ) {
       $u = $u + 1;
       push @mainShared,$shared[$var] ;
       push @deleteArray,$var;
   }
}
  • 不足点

​​​​​​​         创建和消亡进程的时候,对系统带来一定的开销.同时也会频繁的切换CPU.由于对系统进程的并发的数量没有限制,对系统来说并不是很好控制和友好.不知道perl多进程是否可以引入多进程池.提前初始一部分线程给程序,然后在分发线程给程序,这样对CPU的资源以及进程的控制也能达到最大效率化.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!