Nginx Open File Cache


Nginx 的 open_file_cache 相關配置可以緩存靜態文件的元信息,在這些靜態文件被頻繁訪問時可以顯着提升性能。

被緩存的文件元信息包括:

  • fd,文件被打開一次后,fd保留使用
  • size
  • path
  • last modified time

這里有個配置示例:

open_file_cache max=64 inactive=30d;
open_file_cache_min_uses 8;
open_file_cache_valid 3m;

max=64 表示設置緩存文件的最大數目為 64, 超過此數字后 Nginx 將按照 LRU 原則丟棄冷數據。

inactive=30d 與 open_file_cache_min_uses 8 表示如果在 30 天內某文件被訪問的次數低於 8 次,那就將它從緩存中刪除。

open_file_cache_valid 3m 表示每 3 分鍾檢查一次緩存中的文件元信息是否是最新的,如果不是則更新之。

2 為什么只緩存文件元信息而不緩存文件內容?

這個問題的關鍵是 sendfile(2).

Nginx 在 serve 靜態文件的時候用的是 sendfile(2), 當然前提是你配置了 sendfile on, sendfile(2) 直接在 kernel space 內傳輸數據,對比使用 read(2)/write(2) 省去了兩次 kernel space 與 user space 之間的數據拷貝。而同時這些被頻繁讀取的靜態文件的內容會被 OS 緩存到 kernel space。在這樣的機制下,我們緩存中有文件的 fd 和 size,直接調用 sendfile(2) 就可以了。

如果要 Nginx 連內容一起緩存,那就需要每次文件變化都要用 read(2) 將數據從 kernel space 復制到 user space,然后放在 user space,每次應答請求的時候再從 user space 復制到 kernel space 然后寫入 socket。比起前面的方式,這樣的方式毫無優點。

3 在文件緩存更新周期內文件發生變化了會發生什么?

上面提到的配置中,30 天無訪問丟棄,每 3 分鍾做一次信息有效性監測,我們暫且把 3 分鍾叫做緩存更新周期。那在這 3 分鍾之內文件發生變化了會怎樣呢?

3.1 文件被刪除

由於 nginx 還持有原文件的 fd,所以你刪除此文件后,文件並不會真正消失, client 還是能通過原路徑訪問此文件。即便你刪除后又新建了一個同名文件,在當前緩存更新周期內能訪問到的還是原文件的內容。

3.2 文件內容被修改

文件內容被修改可以分為兩種情況:

文件大小不變或增大
由於 nginx 緩存了文件的 size 並且使用 這個緩存中 size 調用 sendfile(2),所以此種情況的后果是:
  • 從文件開始到原 size 字節中的變化可以被 client 看到。
  • 原 size 之后的內容不會被 sendfile(2) 發送,因此 client 看不到此部份內容。
文件大小減小
此種情況下,由於同樣原因,nginx 在 HTTP Header 中告訴 client 文件大小還是原來的尺寸,而 sendfile(2) 只能發送真正的文件數據,長度小於 HTTP Header 中設置的大小,所以 client 會等待到自己超時或者 Nginx 在 epoll_wait 超時后關閉連接。

4 如何設置?

  • 如果你的靜態文件內容變化頻繁並且對時效性要求較高,一般應該把 open_file_cache_valid 設置的小一些,以便及時檢測和更新。
  • 如果變化相當不頻繁的話,那就可以設置大一點,在變化后用 reload nginx 的方式來強制更新緩存。
  • 對靜態文件訪問的 error 和 access log 不關心的話,可以關閉已提升效率。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM