可透過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_id
是jobs
的欄位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_limit
在schedule.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 協議》,轉載必須註明作者和本文連結