[TOC]
# Swoole的聲明周期
******
## php-fpm的聲明周期
傳統基于php-fpm的web開發通常淡化了全局期變量的影響,這對于開發者而言,顯然是降低了許多上手難度的;但也導致了許多新人對全局期變量會產生的影響沒有深刻理解。
我們知道,php-fpm收到請求后會分配一個worker進程去處理這條請求,而worker會去讀取并執行.php文件(在通常情基于框架的開發中,這個.php文件可能是index.php)。也就是說在傳統模式中,每個請求都是獨立在自己的進程中執行的,因為進程是隔離的而php-fpm又是同步阻塞的,所以我們可以很好的清楚和了解是誰在什么時候創建了變量、修改了變量、銷毀了變量。
<br />
**簡單舉個例子**
可可醬是商店的一名售貨員,這個店只有他一個人。當客戶來了之后需要購買一瓶可樂,可可醬檢查了貨架確認有可樂,隨后告訴客戶這瓶可樂價格是¥3.5元,客戶付錢給可可醬,可可醬收到錢后把可樂交給了客戶。
后來發現客人太多,只有可可醬一個人的時候后面的客戶需要排隊很久,于是老板決定再雇一名售貨員,于是加入了小明。
還是上面的場景,但是由于小明的加入,小明和可可醬同時接待了2名客戶,可可醬檢查了貨架確認還有一箱可樂的時候,和客人溝通可樂的價格時,小明的客戶需要購買一箱可樂,于是小明就取走了一箱可樂,當可可醬收了錢準備拿可樂的時候,發現沒有可樂了,然后被客戶打了一頓。
在上面的場景中,就是一個變量被修改而導致后續邏輯混亂的場景,在傳統的fpm開發中,往往只會在訪問數據庫的時候出現這種場景。但是如果假設一個fpm進程可以同時處理多條請求的時候,你如果將用戶信息存放在全局變量中,那么你就無法再可靠的判斷當前用戶是誰了。
<br />
# swoole_server 中對象的4層生命周期
******
以下內容摘自 [swoole文檔](https://wiki.swoole.com/wiki/page/354.html)
開發swoole程序與普通LAMP下編程有本質區別。在傳統的Web編程中,PHP程序員只需要關注request到達,request結束即可。而在swoole程序中程序員可以操控更大范圍,變量/對象可以有四種生存周期。
> 變量、對象、資源、require/include的文件等下面統稱為對象。
<br />
## 程序全局期
在`swoole_server->start`之前就創建好的對象,我們稱之為程序全局生命周期。這些變量在程序啟動后就會一直存在,直到整個程序結束運行才會銷毀。
有一些服務器程序可能會連續運行數月甚至數年才會關閉/重啟,那么程序全局期的對象在這段時間持續駐留在內存中的。程序全局對象所占用的內存是`Worker`進程間共享的,不會額外占用內存。
這部分內存會在寫時分離(`COW`),在`Worker`進程內對這些對象進行寫操作時,會自動從共享內存中分離,變為**進程全局**對象。
> 程序全局期`include`/`require`的代碼,必須在整個程序`shutdown`時才會釋放,`reload`無效
<br />
## 進程全局期
swoole擁有進程生命周期控制的機制,一個`Worker`子進程處理的請求數超過max\_request配置后,就會自動銷毀。`Worker`進程啟動后創建的對象(onWorkerStart中創建的對象),在這個子進程存活周期之內,是常駐內存的。onConnect/onReceive/onClose 中都可以去訪問它。
> 進程全局對象所占用的內存是在當前子進程內存堆的,并非共享內存。對此對象的修改僅在當前`Worker`進程中有效
> 進程期include/require的文件,在`reload`后就會重新加載
<br />
## 會話期
會話期是在`onConnect`后創建,或者在第一次`onReceive`時創建,`onClose`時銷毀。一個客戶端連接進入后,創建的對象會常駐內存,直到此客戶端離開才會銷毀。
在LAMP中,一個客戶端瀏覽器訪問多次網站,就可以理解為會話期。但傳統PHP程序,并不能感知到。只有單次訪問時使用session\_start,訪問$\_SESSION全局變量才能得到會話期的一些信息。
swoole中會話期的對象直接是常駐內存,不需要session\_start之類操作。可以直接訪問對象,并執行對象的方法。
<br />
## 請求期
請求期就是指一個完整的請求發來,也就是`onReceive`收到請求開始處理,直到返回結果發送`response`。這個周期所創建的對象,會在請求完成后銷毀。
swoole中請求期對象與普通PHP程序中的對象就是一樣的。請求到來時創建,請求結束后銷毀。
<br />
# 總結
在Swoole中,一個work進程處理完請求后并不會銷毀(甚至可能同時處理多個請求),所以務必要明確你創建的變量的生命周期,以防止出現邏輯上的問題。
- 引言
- Introduction
- 運行模式
- php-fpm
- php-cli
- 基礎介紹
- 網絡協議
- ip
- tcp
- tcp
- http
- webSocket
- udp
- port端口
- 會話管理
- cookie
- session
- api/token
- linux基礎
- lnmp安裝
- 命令
- 進程管理
- 擴展安裝
- 端口監控
- 防火墻說明
- php7.0
- 部分新特性
- php回調/閉包
- 回調事件
- 閉包/匿名函數
- php多進程
- 多進程開啟
- 進程通信
- 進程信號
- 僵尸進程
- 孤兒進程
- 守護進程
- 同步/異步
- 阻塞/非阻塞
- 協程
- Swoole
- 初始Swoole
- 運行機制
- 生命周期
- composer使用
- EasySwoole
- 設計理念
- 組件說明
- 運行過程
- demo
- 提問的藝術