溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP怎么限制定時任務的進程數(shù)量

發(fā)布時間:2021-03-19 14:13:25 來源:億速云 閱讀:176 作者:小新 欄目:開發(fā)技術

這篇文章主要介紹PHP怎么限制定時任務的進程數(shù)量,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

可能存在的問題

當我們處理大量數(shù)據(jù)的時候,腳本的執(zhí)行時間可能很長,或者重復處理某條數(shù)據(jù)(寫錯的情況下)。

為了避免數(shù)據(jù)的重復處理、運行腳本過多導致服務器壓力過大等問題,我們需要限制腳本的運行數(shù)量。

如何做

思路一

查詢某種標識的進程數(shù)量,如果超過一定數(shù)量,則直接退出,不處理。

思路二

記錄每次的PID,可以使用 文件、redis、memcached 等來存儲。

當啟動一個新進程的時候,去查一下這個標識下面有哪些PID,是否還在運行,且與當前標識有關系。

當超過一定數(shù)量的時候,直接退出,不處理。

實踐

思路一實踐

這里通過 linux 的 ps、grep、wc 的命令來獲取指定標識的運行進程數(shù)。

<?php
/**
 * 是否可以運行
 *
 * @param string $ident 標識
 * @param integer $maxNum 最大運行數(shù)量
 *
 * @return bool
 */
function canRun($ident, $maxNum)
{
  $cmd = sprintf('ps ax | grep %s | grep -v /bin/sh | grep -v grep | wc -l', $ident);
  $fp = @popen($cmd, 'r');
  $num = (int)trim(@fread($fp, 2096));
  @pclose($fp);
  return $num <= $maxNum;
}

思路二實踐

這里使用 redis 存儲 pid 信息。

通過 /proc/{pid}/cmdline 文件檢測指定進程是否還在運行。

<?php
/**
 * 檢查 pid 是否存活
 *
 * @param string $pid  PID
 * @param string $ident 標識
 *
 * @return bool
 */
function isSurvive($pid, $ident)
{
  // 獲取指定pid的cmdline文件
  $cmdlinePath = sprintf('/proc/%s/cmdline', $pid);
  if (!is_file($cmdlinePath)) {
   return false;
  }
  $cmdline = trim(file_get_contents($cmdlinePath));
  // 檢查標識是否在 cmdline 中
  return strpos($cmdline, $ident) !== false;
}

/**
 * 是否可以運行
 *
 * @param string $ident 標識
 * @param integer $maxNum 最大運行數(shù)量
 *
 * @return bool
 */
function canRun($ident, $maxNum)
{
  // 假設已經(jīng)鏈接上
  $redisHandler = getRedis();
  // 定義一個key
  $key = sprintf('php:job:%s:pid', $ident);
  // 當前的PID
  $currentPid = getmypid();
  // 將當前的PID寫入redis
  $redis->sAdd($key, $currentPid);
  // 獲取redis中的所有pid
  $pids = $redis->sMembers($key);
  // 遍歷pid,檢查是否有效
  foreach ($pids as $index => $pid) {
    if ($currentPid == $pid) {
      continue;
    }
    // 檢查 pid 是否還在運行中
    if (isSurvive($pid, $ident)) {
      continue;
    }
    // 若不再運行,則直接刪除
    unset($pids[$index]);
    $redis->sRemove($key, $pid);
  }
  return count($pids) <= $maxNum;
}

關于標識

關于標識,可能我們在運行一些定時腳本的時候,統(tǒng)一的部分可能就是 php 了;或者,擁有相同標識的腳本,我們要歸為幾類。

為了能夠?qū)崿F(xiàn)這些需求,我們可以通過 php 的內(nèi)置函數(shù) cli_set_process_title 來實現(xiàn)自定義 COMMAND。
demo.php:

這個時候,我們運行 demo.php,然后通過 ps ax 可以看到如下結果:

PID  USER   TIME COMMAND
  1 root   0:09 php-fpm: master process (/usr/local/etc/php-fpm.conf)
  7 root   0:16 php-fpm: pool www
  8 root   0:15 php-fpm: pool www
  9 root   0:14 php-fpm: pool www
  10 root   0:00 sh
 663 root   0:00 sh
 690 root   0:00 {php} Job Demo
 691 root   0:00 ps ax

修改指定腳本的進程標題,我們就可以實現(xiàn)定義某些腳本的標識了。

以上是“PHP怎么限制定時任務的進程數(shù)量”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

php
AI