基於名字自動發佈之多進程(3)

基於名字自動發佈之多進程(3)

項目地址: https://gitee.com/lookingdreamer/RexDeploy_v1git

流程圖

爲何選擇多進程?

隨着應用愈來愈多,單進程的運行已經嚴重的拖慢了速度.因此多進程就應運而生了.爲何不是多線程?由於rex自己的框架都是採用的多進程.且多進程相對多線程來講要穩定得多.項目自己也去嘗試了多線程,但在兼容性上出現了問題.索性就所有按照多進程去設計和開發.數組

多進程構建思路

  • 平常生活的比喻多線程

    假設商店最大容納人數爲5我的,一共有12我的.只能等前面5我的進去出來以後,後面的5我的才能進入,不足5我的的所有進去併發

  • 轉換爲數學問題框架

       將12我的編號爲0到12號spa

#!/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個名字的服務.net

my @ks = split(/ /, $k);
  • 關鍵點線程

        利用系統fork()建立多進程; 利用waitpid無阻塞的模式收割進程waitpid(-1, WNOHANG); 利用hash保存進程idscala

  • 多進程間通信設計

        多進程間通信通常分爲消息隊列、共享內存段以及信號量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的資源以及進程的控制也能達到最大效率化.

相關文章
相關標籤/搜索