目錄
原因
危險的做法
正確的姿勢
CLI模式
總結
首頁 後端開發 php教程 聊聊關於PHP定時器的那些事

聊聊關於PHP定時器的那些事

Sep 15, 2021 pm 02:47 PM
php 定時器

常見的計時器有兩種:一種週期性定時執行,例如每天的凌晨三點出報表;另一種在指定時間後執行(一次),例如會員登入系統五分鐘後發放每日登入獎勵。兩種情況對應shell中的cronat指令,與JavaScript中的setIntervalsetTimeout函數類似(嚴格來說setInterval是週期性執行,指定時間點執行需要自行處理)。

做web開發的PHP程式設計師對JavaScript中的兩個定時器函數應該都還熟悉,回到PHP層面就有點傻眼:PHP中有sleep,但是沒有(內置)定時器函數可用。 sleep函數勉強可以做到,但會導致進程阻塞,期間不能做其他事(或無回應)。為什麼PHP沒能提供定時器(Timer)這個功能呢?

原因

個人認為,web開發中PHP不能使用定時器的本質原因是可控 常駐記憶體運行環境的缺失。兩個重點:第一常駐內存,第二可控。 CGI模式下,進程執行完腳本後直接退出,不能指望其到指定時間運行任務;PHP-FPM模式下,進程(絕大多數)常駐內存,但不可控。

不可控的意思是執行PHP的進程不受PHP程式碼影響,進程的入口點和退出時機由額外的程式控制。例如FPM模式下,PHP腳本中的exitdie函數只會中斷腳本的執行,不會對執行腳本的程序產生特別的影響(記憶體外洩除外)。 PHP開發人員編寫的腳本是進程的執行體,執行完畢後就從進程的執行上下文中卸載出去。在這種情況下,執行PHP腳本的時機仍然由外部驅動,沒有外部請求PHP程式碼就安詳的躺在硬碟上,什麼都不做,也就定時任務。

由於PHP主要針對web開發,PHP這種執行模式穩定可靠,開發效率快。例如省去資源釋放這一步,就避免了開發中許多工作量和坑。想想某些第三方函式庫程式碼中改時區、字元編碼等還不還原,在常駐記憶體運作環境下幾乎肯定會導致後續請求有問題。但在FPM模式下,這種坑無意中直接趟平,省去許多調試時間,為程式設計師保住髮際線做出了不小的貢獻。

問題已經了解,那麼PHP如何使用定時器執行定時任務?

危險的做法

在web環境下,PHP腳本預設有逾時時間。去掉超時設置,就可以讓程式一直在背景運行(如果進程不退出的話)。例如以下程式碼在回應請求後繼續後台運行,並且每五秒鐘輸出一次時間到檔案:

# test.php
set_time_limit(0); # 取消超时设置,让脚本可一直运行

echo 'This is a background run forever script. Now you can leave me alone.';

fastcgi_finish_request();   # 结束当前请求

do{
   file_put_contents("/tmp/out.dat", "test script, now:" . date("Y-m-d H:i:s") . "\n", FILE_APPEND);
   sleep(5);
}while(true);
登入後複製

請求http://localhost:8080/test.php檔案後,監控/tmp/out.dat文件,會發現不斷有內容輸出,無論客戶端是否斷開連線、關閉瀏覽器或重新啟動電腦(無法重新啟動伺服器)。這說明程式一直在執行,也實作了我們想要的定時器功能。如果把sleep改成usleeptime_nanosleep,還能實作微秒、奈秒定時器,豈不美哉?

實務上應盡量避免以這種方式實現定時器,不僅因為低效,還略有危險。原因之一是每次請求會佔用一個進程,請求十萬次需要十萬個進程,基本上會導致系統崩潰或後續請求無響應;另外如果打開了session,但是忘記調用session_write_close ,會導致同一個使用者的後續請求被hang住(session活躍時處於加鎖狀態,不關閉session會導致後續進程無法開啟session)。

web開發應當越快回應使用者的要求越好,在web開發中用這種方式強行實作定時器,會讓整個web應用程式處於不穩定、不可靠或不可預測狀態。孟子曰:知而慎行,君子不立於危牆之下。不靠譜的做法要盡量避免,順帶也避免背鍋和甩鍋。

接下來看看PHP中使用定時器的正確姿勢。

正確的姿勢

PHP實作計時器的做法可簡單歸結為以下幾種:

  1. 使用cron、Jenkins等調度工具做週期性定時任務(既可以是執行腳本,也可以是請求某個網址);
  2. 一次執行任務透過訊息佇列、資料庫等方式投遞給第三方程式執行;
  3. 像WordPress一樣模擬定時任務,但要記住這種方式依賴客戶端請求,並需自行處理好進程並發問題;
  4. #使用常駐內存型方式運行PHP程序,即CLI模式。

除了第三種做法,其他方式都是建議的,具體方案請結合實際需求。身為PHP程式設計師,當然還是首選用PHP來做,也就是CLI模式。

CLI模式

摸著良心說,CLI模式讓PHP發揮的空間拓展不少。在CLI模式下,程式的入口點就是腳本,且程式碼可以常駐內存,進程完全由PHP程式碼控制。在這種形式下,實作定時器就有多種玩法。本文列出幾種做法,拋磚引玉:

  1. 使用swooleworkerman等框架,內建(高精度)計時器;
  2. 使用多進程(池)/多執行緒(池)技術(pcntlpthreads拓展在CLI模式下才可使用);
  3. 處理tick或alarm等訊號;
  4. 使用libeventlibev等事件驅動程式庫;
  5. sleep加上循環或自行實作事件循環。

想折騰的話自己用2-5方案,不想折騰swooleworkerman等框架是首選,穩定可靠。

總結

區分HTTP請求和任務的關係,實現定時任務就簡單了。至於用不用PHP來實現,那是另外一回事。當然作為web開發的首選語言,PHP實現定時任務也是輕而易舉的。

推薦學習:《PHP影片教學

#

以上是聊聊關於PHP定時器的那些事的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

我後悔之前不知道的 7 個 PHP 函數 我後悔之前不知道的 7 個 PHP 函數 Nov 13, 2024 am 09:42 AM

如果您是經驗豐富的PHP 開發人員,您可能會感覺您已經在那裡並且已經完成了。操作

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

See all articles