如何才能讓PHP應用性能維持在更高水平

默認情況下安裝的PHP類似於在百貨商店中購買的常規軟件包,但它非常合適,但並不完美。調優的PHP就像是量身定製的裝備。但是,應該注意的是,調優PHP只是提高PHP性能和效率的一種手段,它與不良的代碼和無響應的API調用無關。

php.ini文件

PHP 解釋器在 php.ini 文件中配置和調優,此文件的位置在不同的操作系統中是不同的,並且常規命令行對應 php.ini 和 PHP-FPM 對應的 php.ini 文件是分開的。在這裏,我們假設配置PHP-FPM 對應於php.ini,但是下面講的優化措施適用於所有 php.ini

注:我們首先應該使用 PHP Iniscan 工具掃描 php.ini,檢查使用了安全方面的最佳實踐。

 

 

內存

運行 PHP 時需要關心每個 PHP 進程要使用多少內存,php.ini 中的 memory_limit 設置用於設定單個 PHP 進程可以使用的系統內存最大值。

此設置的默認值爲128M,這可能適用於大多數中小型PHP應用程序。但是,如果您正在運行微型PHP應用程序,則可以降低此值以節省系統資源。另一方面,如果您正在運行內存密集型的PHP應用程序,則可以增加該值。此值的大小由可用的系統內存確定,確定爲PHP分配多少值是一門藝術。

決定給 PHP 分配多少內存,以及能負擔起多少個 PHP-FPM 進程時,可以根據以下維度信息進行判斷:

  • 一共可以分配給 PHP 多少內存?以一個 2G 內存的 VPS 爲例,這臺設備中可能還運行了其他進程,如 MySQL、Nginx 等,那麼留 512M 給 PHP 是合適的。

  • 每個 PHP 進程平均耗費多少內存?這個要監控進程的內存使用量,可以使用命令行命令 top,也可以在 PHP 腳本中調用 memory_get_peak_usage() 函數,不管使用哪種方式,都要多次運行同一個腳本,然後取內存消耗的平均值。

  • 能負擔起多少個 PHP-FPM 進程?假設我給 PHP 分配了 512M 內存,每個 PHP 進程平均耗費 15M 內存,那麼可以負擔起 34 個 PHP-FPM 進程。

  • 有足夠的系統資源嗎?最後還需要確認有足夠的系統資源運行 PHP 應用並處理預期的流量。

注:我們應該使用 Apache Bench 或 Siege 在類似生產環境的條件下對 PHP 應用做壓力測試,以確定生產環境是否有足夠的資源可用。

 

 

 

 

Zend OPcache

確定要分配多少內存後,就可以配置 PHP 的 Zend OPcache 擴展

PHP 5.5.0+ 內置了這個擴展,下面是在 php.ini 文件中配置和優化 Zend OPcache 擴展所用的設置:

  • opcache.memory_consumption = 64:爲操作碼緩存分配的內存量(以MB爲單位)。分配的內存量應能夠存儲應用程序中所有PHP腳本編譯的操作碼。該值可以根據應用程序的大小設置爲不同的值。

  • opcache.interned_strings_buffer = 16:用於存儲常駐字符串的內存量(以MB爲單位)。什麼是駐留字符串?  PHP解釋器將在其後找到同一字符串的多個實例,並將此字符串保存在內存中。如果再次使用相同的字符串,PHP解釋器將使用指針,以節省內存。默認情況下,PHP駐留字符串在每個PHP進程中都是隔離的。此設置允許PHP-FPM進程池將所有進程駐留字符串存儲在共享緩衝區中,以便可以將其存儲在PHP-FPM進程池中。在多個進程之間引用常駐字符串,從而節省了更多內存。

  • opcache.max_accelerated_files = 4000:可以存儲在操作碼緩存中的PHP腳本的最大數量。取值範圍是2000〜100,000。此值必須大於PHP應用程序中的文件數。

  • opcache.validate_timestamps = 1:當此設置的值爲1時,一段時間後,PHP將檢查PHP腳本的內容是否已更改,並檢查間隔由 opcache.revalidate_freq 設置指定。如果此設置的值爲0,則PHP將不會檢查PHP腳本的內容是否有更改,並且我們必須自己清除緩存的操作碼。建議在開發環境中將其設置爲1,在生產環境中將其設置爲0。

  • opcache.revalidate_freq = 0:設置多久(單位是秒)檢查一次 PHP 腳本內容是否有變化。設置爲0秒的含義是僅當opcache.validate_timestamps 設置爲1時,每次請求PHP文件時都會重新驗證它們,因此,每次在開發環境中而不是在生產環境中都會重新驗證PHP文件。

  • opcache.fast_shutdown = 1:此設置允許操作碼使用更快的停機時間,將對象破壞和內存釋放留給Zend Engine的內存管理器。

 

文件上傳

如果您的應用程序允許上傳文件,則最好設置可以上傳的最大文件大小。另外,最好設置一次可以上傳多少個文件:

file_uploads = 1
upload_max_filesize = 10M
max_file_uploads = 3

 

默認情況下,PHP允許在單個請求中上傳20個文件。 上傳的最大文件爲2MB。在這裏,我將其設置爲在單個請求中最多上傳3個文件,每個文件的最大大小爲10MB。也不要設置此值。很大,否則會發生超時。

注:如果非要上傳大文件,Web 服務器的配置也要做相應調整。除了在 php.ini 中設置之外,還要調整 Nginx 虛擬主機配置中的 client_max_body_size 設置。

 

最長執行時間

php.ini 文件中的 max_execution_time 用於設置單個PHP進程在終止之前可以運行的最長時間。此設置默認爲30秒,建議將其設置爲5秒:

max_execution_time = 5

 

注:在 PHP 腳本中可以調用 set_limit_time() 函數覆蓋這個設置。

假設我們要生成報告並將結果生成爲PDF文件。該任務可能需要10分鐘才能完成,並且我們當然不希望等待PHP請求10分鐘。我們應該編寫一個單獨的PHP文件,並將其放在單獨的背景中。在該流程中執行後,Web應用程序可以在幾毫秒內生成一個單獨的後臺流程,然後返回HTTP響應:

<?php
exec('echo "create-report.php" | at now');
echo 'report pending...';

 

create-report.php 在單獨的後臺進程中運行。運行之後,您可以更新數據庫或將報告通過電子郵件發送給收件人。但是,這種用法很少見。通常,我們通過異步使用隊列來實現類似的功能。無論在安全性,可伸縮性和可維護性方面,效果都更好。相關組件具有輕量級消息隊列PHPResque等。

處理會話

PHP的默認會話處理程序減慢了大型應用程序的速度,因爲該處理程序將會話數據存儲在硬盤上,從而造成不必要的磁盤I / O並浪費時間。我們應該將會話數據保留在內存中,例如使用Memcached或Redis。這還有一個額外的好處-將來更容易擴展。如果會話數據存儲在硬盤上,則添加其他服務器不方便。如果會話數據存儲在Memcached或Redis中,則任何分佈式PHP-FPM服務器都可以訪問會話數據。

如果想把會話數據保存在 Memcached 中,需要做如下配置:

session.save_handler = 'memcached'
session.save_path = '127.0.0.1:11211'

 

緩衝輸出

如果在更少的塊中發送更多的數據,而不是在更多的塊中發送更少的數據,則網絡將更加高效,也就是說,以更少的片段瀏覽器傳遞內容以進行訪問,這可以減少HTTP請求的總數。

因此,我們必須讓PHP緩衝輸出。默認情況下,PHP已啓用輸出緩衝功能,並且PHP將在緩衝4096字節的輸出後將內容發送到Web服務器。

output_buffering = 4096
implicit_flush = false

 

注:如果想要修改輸出緩衝區的大小,確保使用的值是4(32位系統)或8(64位系統)的倍數。

 

真實路徑緩存

PHP 會緩存應用使用的文件路徑,這樣每次包含或導入文件時就無需不斷搜索包含路徑了,這個緩存叫真實路徑緩存(realpath cache),如果運行的是大型的 PHP 文件(如 Composer 組件),使用了大量文件,增加 PHP 真實路徑緩存的大小能得到更好的性能。

真實路徑緩存的默認大小爲16K。此緩存所需的確切大小不易確定,但可以使用一些技巧:首先,增加實際路徑高速緩存的大小並將其設置爲特別大的值,例如256K。最後在php腳本末尾添加上 print_r(realpath_cache_size());,輸出真實路徑緩存的真正大小,最後,把真實路徑緩存的大小改爲這個真正的值。我們可以在 php.ini 文件中設置真實路徑緩存的大小:

realpath_cache_size = 64K
發佈了198 篇原創文章 · 獲贊 26 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章