定時任務管理

so_easy發表於2021-02-22

可透過web訪問控制的定時任務系統。

配置檔案

第一步首先就是配置好schedule.ini檔案。

為了能夠交代清楚後面的邏輯,首先需要告知的是:定時任務的的子任務都是來源於資料庫,

總共分為了三個資料表:scheduler_jobs、scheduler_vars、scheduler_tags。

  • jobs:定時任務
  • vars:變數配置
  • tags:標籤配置

jobs的記錄首先按照server_id分組,那麼不同組可能會在不同的伺服器執行。而不同的伺服器

的工作目錄、執行命令等可能又存在區別,所以透過vars配置變數去遮蔽不同的伺服器之間的差異性。

因此在配置檔案中需要指定這些區別。

; 基本配置模組,如pid檔案、log檔案路徑、記憶體最大限制等。
[base]
; 此處省略,在demo中有
; 服務配置模組
;1對應的就是server_id=1的組別。
[server_1]
host = 127.0.0.1 ;線上最好不要寫0.0.0.0和127.0.0.1,而是寫真實的內網ip。
port = 3401 ;埠號,不同的組別埠號必須不同。
server = 1 ;最終DB的不同組可部署到不同伺服器,為了遮蔽不同伺服器
;之間的配置不同,透過`server`指定的變數替換jobs的佔位符。

[server_2]
host = 127.0.0.1
port = 3402
server = 1
; DB模組
[db1]
; 此處省略,是DB連線的配置

第一件事情除了配置好配置檔案之外,那就是初始化資料表。
檔案在src/db/database.sql

工作原理

透過第一步配置檔案的介紹,基本上能夠知道工作機制的大概。

sched.demo中寫好了一個shell,可以幫助我們快速啟動服務。首先可執行

cp sched.demo sched 然後在vim sched。再執行sudo sh sched start啟動程式。

如果在linux上,還可以執行sudo ln -s /path/to/sched /etc/init.d/,最後別忘了執行

sudo chmod +x /etc/init.d/sched。那麼到這裡以後就可以很方便的使用:

/sudo /etc/init.d/sched start server_id啟動服務了。

注意:這裡的server_idjobs的欄位server_id,即分組。是一個必要引數。

啟動的流程大致如:

執行Process.php -> 載入配置檔案 -> 初始化stream ->

( 接收web請求 -> 同步DB的資料 -> 啟動子程式 -> 回收子程式 ) 這是一個迴圈的過程

後來再同步DB的資料這一步驟中,還增加了防止主程式意外退出時,立即重新啟動主程式導致多個相同子程式併發的情況處理。每個任務可以配置最大併發數量,透過refcount記錄目前已啟動的子程式數。透過這兩個資料的比較則可以控制單任務的最大併發數。

你可能已經注意到了,這個是基於記憶體管理的。那麼既然是基於記憶體管理的,那麼在記憶體的使用方面則需要特別注意。對於phper來說,寫的最多的可能是業務方面的需求,不太會考慮到資源的回收。因為PHP是單程式的,執行結束後則自動回收資源。而在這裡就不得不去多加考慮記憶體方面的最佳化了。我雖然沒有寫PHP常駐程式的經驗,所以就從這裡開始修煉。在記憶體回收方面,也是透過xdebug和長時間的記憶體使用日誌跟蹤,最終使主程式的記憶體使用穩定下來了。主要是從以下幾點:

  • 變數的回收
  • DB連線的關閉
  • 輸出緩衝的關閉
  • web客戶端請求連線的關閉
  • 子程式資源的回收

但是即使對記憶體的回收做到了極致(何況我還沒有:),在某些情況下依然會發現記憶體在緩緩上升。這是為什麼呢?原因可能是因為:

推薦閱讀:www.laruence.com/2011/03/04/1894.h...

1)PHP是預先申請,然後自己內部分配。

2)陣列申請完之後則不會再釋放,這也就導致在陣列變大時,即使已經將陣列內的元素後來釋放了,

但是該主程式佔用的記憶體依然不會變小。

3)雖然透過top -p pid可觀察到主程式共佔用的記憶體,但是內部實際使用的會比這個小。

所以不必對記憶體的總佔用太過擔心,實際使用的記憶體穩定性很重要。但是預設主程式最大可使用的記憶體是1024M

也可透過memory_limitschedule.ini配置。以此來防止記憶體的溢位。

結合以上的理論,在本專案中可能導致記憶體增大的條件有:

  • 子程式的數量上升
  • web訪問的併發數

目前已逐步上線,更多的問題需要後續跟蹤發現。

自認為的優點

透過絮絮叨叨的以上說明,現在可以說說它的優點了。

  • 最大的優點:定製化的定時任務管理,可伸縮性很強。這種模式可以運用到其他的用途。

如除了定時任務之外,還寫了一個監控系統guarder,也是透過這種模式運作。
除此之外,也可自己增加登入授權、IP白名單。如果有需要,還可以增加每個任務的功能說明及任務重跑時的額外引數等。定製化是這個專案的最大特性。

  • 最大並行數量的控制。
  • web訪問控制。
  • 支援分散式服務。

TCP抓包

發起web請求,透過socket響應web請求。

定時任務管理

於是嘗試抓TCP的包 sudo tcpdump -i any tcp port 3499,如下:

定時任務管理

  • Client發起SYN請求連線
  • Client超時重發
  • Server收到client.SYN,並且傳送自己的SYN和ACK
  • Server超時重發
  • Client響應ACK,告知WIN=408256.
  • Client 響應 [TCP Dup ACK] 即 DACK,因為收到了Server的第二條 SYN+ACK。
  • [TCP Update Window] 接收方(server)視窗發生變化,通知Client併傳送ACK。
  • Server DACK。

思考:是我家裡的網路太差了嗎?為什麼會發生這麼頻繁的網路丟包問題?難道是程式碼有問題嗎?

本作品採用《CC 協議》,轉載必須註明作者和本文連結