、定義
<meta> 標簽提供關于 HTML 文檔的元數據。它不會顯示在頁面上,但是對于機器是可讀的。可用于瀏覽器(如何顯示內容或重新加載頁面),搜索引擎(關鍵詞),或其他 web 服務。
2、作用
meta里的數據是供機器解讀的,告訴機器該如何解析這個頁面,還有一個用途是可以添加服務器發送到瀏覽器的http頭部內容,例如我們為頁面中添加如下meta標簽:
瀏覽器的頭部就會包括這些:
只有瀏覽器可以接受這些附加的頭部字段,并能以適當的方式使用它們時,這些字段才有意義。
3、meta的必需屬性和可選屬性
meta的必需屬性是content,當然并不是說meta標簽里一定要有content,而是當有http-equiv或name屬性的時候,一定要有content屬性對其進行說明。例如:
必需屬性
<meta name="keywords" content="HTML,ASP,PHP,SQL">
這里面content里的屬性就是對keywords進行的說明,所以呢也可以理解成一個鍵值對吧,就是{keywords:"HTML,ASP,PHP,SQL"}。
可選屬性
在W3school中,對于meta的可選屬性說到了三個,分別是http-equiv、name和scheme。考慮到scheme不是很常用,所以就只說下前兩個屬性吧。
http-equiv
http-equiv屬性是添加http頭部內容,對一些自定義的,或者需要額外添加的http頭部內容,需要發送到瀏覽器中,我們就可以是使用這個屬性。在上面的meta作用中也有簡單的說明,那么現在再舉個例子。例如我們不想使用js來重定向,用http頭部內容控制,那么就可以這樣控制:
<meta http-equiv="Refresh" content="5;url=http://blog.yangchen123h.cn" />
在頁面中加入這個后,5秒鐘后就會跳轉到指定頁面啦,效果可看W3school的例子
name
第二個可選屬性是name,這個屬性是供瀏覽器進行解析,對于一些瀏覽器兼容性問題,name屬性是最常用的,當然有個前提就是瀏覽器能夠解析你寫進去的name屬性才可以,不然就是沒有意義的。還是舉個例子吧:
<meta name="renderer" content="webkit">
這個meta標簽的意思就是告訴瀏覽器,用webkit內核進行解析,當然前提是瀏覽器有webkit內核才可以,不然就是沒有意義的啦。當然看到這個你可能會有疑問,這個renderer是從哪里冒出來的,我要怎么知道呢?這個就是在對應的瀏覽器的開發文檔里就會有表明的,例如這個renderer是在360瀏覽器里說明的。360瀏覽器內核控制Meta標簽說明文檔
常用meta標簽大總結
接下來就是常用的meta標簽大總結啦,我會盡可能的做到全
charset
charset是聲明文檔使用的字符編碼,解決亂碼問題主要用的就是它,值得一提的是,這個charset一定要寫第一行,不然就可能會產生亂碼了。
charset有兩種寫法
兩個都是等效的。
百度禁止轉碼
百度會自動對網頁進行轉碼,這個標簽是禁止百度的自動轉碼
<meta http-equiv="Cache-Control" content="no-siteapp" />
SEO 優化部分
viewport
viewport主要是影響移動端頁面布局的,例如:
content 參數:
各瀏覽器平臺
Microsoft Internet Explorer
Google Chrome
360瀏覽器
UC手機瀏覽器
UCBrowser_U3_API
QQ手機瀏覽器
Apple iOS
Google Android
App Links
最后——移動端常用的meta
可以使用Fiddler工具抓取數據包,查看Nginx版本,也可以在CentOS中使用命令curl -I http://20.0.0.55 顯示響應報文首部信息。
curl -I http://20.0.0.55
vim /usr/local/nginx/conf/nginx.conf
http {
include mime.types;
default_type application/octet-stream;
server_tokens off; #添加關閉版本號
}
systemctl restart nginx
curl -I http://20.0.0.55
[root@localhost objs]# vim /opt/nginx-1.12.2/src/core/nginx.h
#define NGINX_VERSION "1.30.23" #修改版本號
#define NGINX_VER "apache/" NGINX_VERSION #修改服務器類型
---》wq
[root@localhost opt]# cd nginx-1.12.2/
[root@localhost nginx-1.12.2]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module
[root@localhost nginx-1.12.2]# make 編譯
[root@localhost objs]# cp /opt/nginx-1.12.2/objs/nginx /usr/local/nginx/sbin/nginx
[root@localhost objs]# systemctl start nginx
[root@localhost objs]# curl -I http://20.0.0.55
vim /usr/local/nginx/conf/nginx.conf
user root root; #取消注釋,修改用戶為root,組為root
systemctl restart nginx
ps aux | grep nginx
主進程由root創建,子進程由nginx創建
vim /usr/local/nginx/conf/nginx.conf
http {
......
server {
......
location / {
root html;
index index.html index.htm;
}
location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ { #加入新的 location,以圖片作為緩存對象
root html;
expires 1d; #指定緩存時間,1天
}
......
}
}
systemctl restart nginx
vim /opt/fenge.sh
#!/bin/bash
# filename: fenge.sh
day=$(date -d "-1 day" "+%Y%m%d") #顯示前一天的時間
logs_path="/var/log/nginx" #定義一個新的日志存放目錄
pid_path="/usr/local/nginx/logs/nginx.pid" #定義變量pid_path將nginx進程id
[ -d $logs_path ] || mkdir -p $logs_path #創建日志文件目錄
#移動并重命名日志文件
mv /usr/local/nginx/logs/access.log ${logs_path}/huigenb.com-access.log-{$day}
#重建日志文件
kill -USR1 $(cat $pid_path)
#刪除30天前的日志文件
find $logs_path -mtime +30 -exec rm -rf {} \;
#find $logs_path -mtime +30 |xargs rm -rf
---->wq
chmod +x /opt/fenge.sh
/opt/fenge.sh
ls /var/log/nginx
ls /usr/local/nginx/logs/access.log
crontab -e
0 1 * * * /opt/fenge.sh #設置周期性計劃
HTTP有個KeepAlive,告訴web服務器在處理完一個請求后保持這個TCP連接的打開狀態。若接收到來自客戶端的其他請求,服務端會利用這個未被關閉的連接,而不需要再建立一個連接。
KeepAlive在一段時間內保持打開狀態,它們會在這段時間占用資源,占用過多就會影響性能。
vim /usr/local/nginx/conf/nginx.conf
http {
......
keepalive_timeout 65 180; #三次握手的超過時間
client_header_timeout 80; #等待客戶端發送請求頭的超時時間會發送408 錯誤
client_body_timeout 80; #設置客戶端發送請求體的超時時間
......
}
systemctl restart nginx
指定KeepAlive的超時時間(timeout)。指定每個TCP連接最多可以保持多長時間,服務器將會在這個時間后關閉連接。 Nginx的默認值是65秒,有些瀏覽器最多只保持 60 秒,所以可以設定為 60 秒。若將它設置為0,就禁止了keepalive 連接。
第二個參數(可選的)指定了在響應頭Keep-Alive:timeout=time中的time值。這個頭能夠讓一些瀏覽器主動關閉連接,這樣服務器就不必去關閉連接了。沒有這個參數,Nginx 不會發送 Keep-Alive 響應頭。
客戶端向服務端發送一個完整的 request header 的超時時間。如果客戶端在指定時間內沒有發送一個完整的 request header,Nginx 返回 HTTP 408(Request Timed Out)。
指定客戶端與服務端建立連接后發送 request body 的超時時間。如果客戶端在指定時間內沒有發送任何內容,Nginx 返回 HTTP 408(Request Timed Out)。
在高并發場景,需要啟動更多的Nginx進程以保證快速響應,以處理用戶的請求,避免造成阻塞
cat /proc/cpuinfo | grep -c "physical id" #查看cpu核數
ps aux | grep nginx #查看nginx主進程中包含幾個子進程
vim /usr/local/nginx/conf/nginx.conf
worker_processes 2; #修改為核數相同或者2倍
worker_cpu_affinity 01 10; #設置每個進程由不同cpu處理,進程數配2 4 6 8分別為0001 0010 0100 1000
systemctl restart nginx
worker_processes 2;
worker_cpu_affinity 01 10;
解釋:01表示啟用第一個CPU內核,10表示啟用第二個CPU內核
worker_cpu_affinity 01 10;表示開啟兩個進程,第一個進程對應著第一個CPU內核,第二個進程對應著第二個CPU內核。
worker_processes 4;
worker_cpu_affinity 01 10 01 10;
解釋:開啟了四個進程,它們分別對應著開啟2個CPU內核
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
解釋:0001表示啟用第一個CPU內核,0010表示啟用第二個CPU內核,依此類推
worker_processes 2;
worker_cpu_affinity 0101 1010;
解釋:0101表示開啟第一個和第三個內核,1010表示開啟第二個和第四個內核;2個進程對應著四個內核;worker_cpu_affinity配置是寫在/etc/nginx/nginx.conf里面的;2核是 01,四核是0001,8核是00000001,有多少個核,就有幾位數,1表示該內核開啟,0表示該內核關閉
worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
解釋:0001表示啟用第一個CPU內核,0010表示啟用第二個CPU內核,依此類推;worker_processes最多開啟8個,8個以上性能提升不會再提升了,而且穩定性變得更低,所以8個進程夠用了。
Nginx的ngx_http_gzip_module壓縮模塊提供對文件內容壓縮的功能。
允許Nginx服務器將輸出內容在發送客戶端之前進行壓縮,以節約網站帶寬,提升用戶的訪問體驗,默認已經安裝可在配置文件中加入相應的壓縮功能參數對壓縮性能進行優化。
vim /usr/local/nginx/conf/nginx.conf
http {
......
gzip on; #取消注釋,開啟gzip壓縮功能
gzip_min_length 1k; #最小壓縮文件大小
gzip_buffers 4 64k; #壓縮緩沖區,大小為4個64k緩沖區
gzip_http_version 1.1; #壓縮版本(默認1.1,前端如果是squid2.5請使用1.0)
gzip_comp_level 6; #壓縮比率
gzip_vary on; #支持前端緩存服務器存儲壓縮頁面
gzip_types text/plain text/javascript application/x-javascript text/css text/xml application/xml application/xml+rss image/jpg image/jpeg image/png image/gif application/x-httpd-php application/javascript application/json; #壓縮類型,表示哪些網頁文檔啟用壓縮功能
......
}
cd /usr/local/nginx/html
先將圖片(R-C.jpg)文件傳到/usr/local/nginx/html目錄下
vim index.html
......
<img src="R-C.jpg"/> #網頁中插入圖片
</body>
</html>
systemctl restart nginx
在Linux系統中,打開火狐瀏覽器,按F12,然后F5
選擇 網絡------>選擇HTML、WS、其他
訪問http://20.0.0.55 ,雙擊200響應消息查看響應頭中包含Content-Enconding:gzip
vim /usr/local/nginx/conf/nginx.conf
http {
......
server {
......
location ~* \.(gif|jpg|swf)$ {
valid_referers none blocks *.dajb.com dajb.com;
if ( $invalid_referer) {
rewrite ^/ http://www.dajb.com/error.png;
}
}
......
}
}
~* .(jpg|gif|jepg|bmp|ico)$ :這段正則表達式表示匹配不區分大小寫,以.jpg 或.gif 或.swf
結尾的文件;
? valid_referers :設置信任的網站,可以正常使用圖片;
? 后面的網址或者域名 :referer 中包含相關字符串的網址;
? if語句:如果鏈接的來源域名不在valid_referers所列出的列表中,$invalid_referer為1,則執行后面的操作,即進行重寫或返回403 頁面。
cd /usr/local/nginx/html
將R-C.jpg、error.png文件傳到/usr/local/nginx/html目錄下
vim index.html
......
<img src="R-C.jpg"/>
</body>
</html>
echo "20.0.0.55 www.dajb.com" >> /etc/hosts
echo "20.0.0.58 www.daolian.com" >> /etc/hosts
yum install -y httpd
vim /var/www/html/index.html
<html>
<body>
<img src="http://www.dajb.com/R-C.jpg"/>
</body>
</html>
---->wq
echo "20.0.0.55 www.dajb.com" >> /etc/hosts
echo "20.0.0.58 www.daolian.com" >> /etc/hosts
cd /usr/local/php/etc/
cp php-fpm.conf.default php-fpm.conf
vim php-fpm.conf
pid=run/php-fpm.pid
vim /usr/local/php/etc/php-fpm.d/www.conf
#96行
pm=dynamic #fpm進程啟動方式,動態的
#107行
pm.max_children=20 #fpm進程啟動的最大進程數
#112行
pm.start_servers=5 #動態方式下啟動時默認開啟的進程數,在最小和最大之間
#117行
pm.min_spare_servers=2 #動態方式下最小空閑進程數
#122行
pm.max_spare_servers=8 #動態方式下最大空閑進程數
#啟動php-fpm,不可用于重啟
/usr/local/php/sbin/php-fpm -c /usr/local/php/lib/php.ini
#執行第一個命令后,就可以使用下面這條命令查看pid號重啟php-fpm
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
netstat -anpt | grep 9000
linux/Unix上,一切皆文件,每一次用戶發起請求就會生成一個文件句柄,文件句柄可以理解為就是一個索引,所以文件句柄就會隨著請求量的增多,而進程調用的頻率增加,文件句柄的產生就越多,系統對文件句柄默認的限制是1024個,對Nginx來說非常小了,需要改大一點
系統全局性修改
用戶局部性修改
進程局部性修改
vim /etc/security/limits.conf
在End of file前面添加4個參數
soft:軟控制,到達設定值后,操作系統不會采取措施,只是發提醒
hard:硬控制,到達設定值后,操作系統會采取機制對當前進程進行限制,這個時候請求就會受到影響
root:這里代表root用戶(系統全局性修改)
*:代表全局,即所有用戶都受此限制(用戶局部性修改)
nofile:指限制的是文件數的配置項。后面的數字即設定的值,一般設置10000左右
尤其在企業新裝的系統,這個地方應該根據實際情況進行設置,可以設置全局的,也可以設置用戶級別的
vim /usr/local/nginx/conf/nginx.conf
每個進程的最大文件打開數,所以最好與 ulimit -n 的值保持一致。
worker_rlimit_nofile 35535; #進程限制
nginx的連接處理機制在于不同的操作系統會采用不同的I/O模型,Linux下,nginx使用epoll的I/O多路復用模型,在freebsd使用kqueue的IO多路復用模型,在solaris使用/dev/pool方式的IO多路復用模型,在windows使用的icop等等。要根據系統類型不同選擇不同的事務處理模型,我們使用的是Centos,因此將nginx的事件處理模型調整為epoll模型。
events {
worker_connections 10240; //設置連接數
use epoll;
}
vim /usr/local/nginx/conf/nginx.conf
sendfile on; # 開啟高效文件傳輸模式。
tcp_nopush on; #需要在sendfile開啟模式才有效,防止網路阻塞,積極的減少網絡報文段的數量。將響應頭和正文的開始部分一起發送,而不一個接一個的發送。
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k
#將nginx進程設置為普通用戶,為了安全考慮
user nginx;
#當前啟動的worker進程,官方建議是與系統核心數一致
worker_processes 2;
#方式一,就是自動分配綁定
worker_cpu_affinity auto;
#日志配置成warn
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
#針對 nginx 句柄的文件限制
worker_rlimit_nofile 35535;
#事件模型
events {
#使用epoll內核模型
use epoll;
#每一個進程可以處理多少個連接,如果是多核可以將連接數調高 worker_processes * 1024
worker_connections 10240;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
charset utf-8; #設置字符集
#設置日志輸出格式,根據自己的情況設置
log_format main '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$args" "$request_uri"';
access_log /var/log/nginx/access.log main;
sendfile on; #對靜態資源的處理比較有效
#tcp_nopush on; #如果做靜態資源服務器可以打開
keepalive_timeout 65;
########
#Gzip module
gzip on; #文件壓縮默認可以打開
include /etc/nginx/conf.d/*.conf;
}
mote_addr - r e m o t e u s e r [ remote_user [ re m o t e u ? ser [ time_local] “ KaTeX parse error: Double superscript at position 34: … '? status b o d y b y t e s s e n t " body_bytes_sent " b o d y b ? y t e s s ? e n t " http_referer” ’
'“ h t t p u s e r a g e n t " " http_user_agent" " h tt p u ? se r a ? g e n t "" http_x_forwarded_for” ’
‘“
a r g s " " args" " a r g s ""
request_uri”’;
access_log /var/log/nginx/access.log main;
sendfile on; #對靜態資源的處理比較有效
#tcp_nopush on; #如果做靜態資源服務器可以打開
keepalive_timeout 65;
########
#Gzip module
gzip on; #文件壓縮默認可以打開
include /etc/nginx/conf.d/*.conf;
}
信做過web的同學對于 Nginx 一定不陌生,它是一款輕量級的開源 Web 服務及代理程序。在 Nginx 出現之前市場上主流兩款 Web 服務,一款是 IIS,另外一款是 Apache。而在 Nginx 誕生后,因其輕量化、支持高并發等特性,逐漸蠶食了這兩款 Web 服務的市場份額。目前國內大量企業已經廣泛使用 Nginx。那么我們在工作中如何對其進行優化和配置便成了重中之重。
在學習如何優化和配置 Nginx 之前,首先需要提前掌握一些基礎知識,包括:
Nginx 的優化主要分為基礎優化和緩存優化,我們先來看一下基礎優化。
基礎配置優化主要包括:
在 Nginx 用于普通的絕大部分 Web 服務時這些優化場景都是需要了解的。
所謂的 CPU 親和性是做什么呢?現在的CPU通常都是多核的,而且可以通過超線程來虛擬更多核數 ,那親和力就是讓 Nginx 充分發揮多核 CPU 的性能,從而提高 Nginx 的服務性能。 Nginx 運行時會啟用 1 個 master 進程及多個 worker 進程,worker 進程負責處理請求,如果 worker 進程在多核 CPU 中發生頻繁的調度切換就會損耗性能。在這種情況下,我們希望減少這種頻繁調度,讓每一個 Nginx 的 worker 線程都能夠固定到具體的 CPU 核心上,所以就需要配置 Nginx 的 CPU 親和性來解決這個問題。
由于 Nginx CPU 親和性配置本身有多套配置方案,這里推薦我們推薦直接將配置項設置成 auto(worker_cpu_affinity ),即采用了 Nginx 推薦的 CPU綁核策略方式。另外的一個方式是手動綁定,將 worker 線程數量與 CPU 核數一一綁定方式設置。我們設置成 auto Nginx 會自動識別并按照推薦策略來分配 worker 線程和 CPU。
如圖所示,我們看到 CPU 的核心有 8 個,如果我們設置成 auto 后,那么 Nginx 會將 8 個 worker 線程一對一地按照推薦策略綁定到 CPU 核心上,這樣避免 CPU 頻繁對 worker 線程進行調度,從而降低 CPU 損耗。
Nginx 第二個基礎配置優化項是 IO 流事件模型,我們經常可以在 Nginx 下面看到的 events 配置模塊中默認設置了 use epoll,表示 Nginx 使用 epoll 這個 IO 流事件模型,那為什么 Nginx 會選擇使用 epoll 呢?這是因為 epoll 有以下這些得天獨厚的優勢。我們來詳細講解一下:
首先,Linux 系統下一切皆文件,比如我們打開一個設備,它便會產生一個文件描述符。在產生一個進程時,這個進程便需要一個進程描述符,這個進程描述符也是一個文件。所以在 Nginx 處理請求的時候,每一個請求都會產生處理請求的描述符。
其次,在 Nginx 處理大規模請求的時候,為了提高并發效率需要采用異步非阻塞模型,這又和 epoll 有什么關系呢?epoll 本身是以異步非阻塞模型來處理請求流中的事件流。
這里還需要注意一點,并不是所有的 Linux 操作系統都可以使用 epoll,它是在 kernel 2.6 版本以后提出的,早期內核使用的 select\poll 模型,select 模型比 epoll 模型性能要低很多,有經驗的運維同學一定深有體會。
那么 epoll 相比于 select 模型到底具備哪些優勢呢?
另外補充下,在 events{} 配置中還涉及一個優化的地方就是 worker_connections,這個也是在 events 里面來進行設置的,通過上面的學習我們知道了 worker 線程作用,那每一個 worker 線程所支持的連接是有限的,這里會默認設置成 1024,而我們在處理高并發的場景時,單個 worker 線程設置成 1024 的話往往偏低,這里建議你將 worker_connections 調大一些,你可以參考實際業務所需 Nginx 處理最大峰值來調大這個設置值。
第三個基礎配置優化是零拷貝,所謂零拷貝的配置是在 Nginx 中的 HTTP 配置模塊中添加一個 sendfile on 配置項,它便是一個零拷貝,所謂零拷貝并不代表不拷貝了,而是說它做到了文件的內核態到用戶態的零拷貝。
如圖所示,如果我們沒有使用零拷貝時文件傳輸是什么樣子的?首先 Nginx 在處理文件時,會將文件傳入操作系統內核態的 Buffer Cache,然后傳遞到操作系統上層的用戶態,經用戶態的 Buffer Cache 再傳回內核態中,最后通過 Socket 將文件轉發出去。
這個時候你會發現一個問題,對于靜態文件并不需要流轉到用戶態中,直接通過內核態效率更高,所以這時我們就需要在 Nginx 中開啟 sendfile on,這樣靜態文件就可以通過紅色的路徑在內核態中完成轉發,而不用再去繞道用戶態,提高了效率。
Nginx 基礎配置優化的最后一項是文件壓縮,我們知道服務端往客戶端發送的數據越小,占用的延遲越低,用戶體驗就會越好。所以往往在代理或 Nginx 中會設置文件壓縮,我們主要通過 gzip 方式進行設置,主要的設置項如下:
最后這兩項表示設置 zip 的壓縮類型及是否關閉 客戶端使用 IE6 瀏覽器請求過來的壓縮,以上就是對文件壓縮的典型配置,你可以根據具體情況做一些細節上的調整。
上面就是我們講了基礎優化,但是我們在使用 Nginx 作為代理入口的時候,對于網站優化有效的方式除了需要考慮基礎配置優化外,更有用的方式就是優化緩存。用到緩存優化主要期望提高網站服務訪問效率,減少服務端的性能使用。
緩存配置優化大致可以分為幾個部分,分別是瀏覽器緩存優化、代理緩存優化、HTTPS SSL 緩存優化、KV 服務緩存優化等。
首先我們需要了解一個問題,客戶端如何直觀的看到大部分緩存(瀏覽器緩存、代理緩存、ssl緩存)優化效果呢?推薦你用 Chrome 瀏覽器中的開發者工具,打開瀏覽器并點擊視圖-開發者工具。例如我們在 URL 地址欄中輸入 www.baidu.com。這個時候我們會看到在 Network 標簽欄中會出現對應的訪問名稱、路徑。然后點擊某一個路徑,這時會在 Headers 中看到相應的頭信息內容。
我們剛用瀏覽器打開 www..com 這個網站,表示瀏覽器發送一次 HTTP 請求,我們能看到服務端會返回給客戶端代碼經過渲染后的一個效果展示。如果點擊右鍵查看源代碼,這樣就可以看到網站返回的 body 內容。除了 body 之外,一個完整的 HTTP 響應,服務端返回給客戶端還有一部分就是 Response Headers,表示服務端返回給客戶端的頭信息內容。
上面就是一次 HTTP 請求和響應的過程,如果我們想判斷服務端有沒有做緩存,緩存的時間是多長。這些內容都會在頭信息中通過服務端展示給客戶端,我們可以在 Response Headers 查看頭信息。
比如expires 頭信息是控制在什么時間點生成的緩存元素,Cache Control 負責保存這個元素需要緩存多長時間。
通過使用Chrome 開發者工具我們就能夠非常清晰的看到一次頁面的打開效果,了解它的請求了是什么(請求頭),服務端返回了什么( body及返回 頭信息),通過這個工具詳細的查看數據并對一個頁面緩存情況進行分析,對于開發和運維人員而言是必須要掌握的。
如果緩存的元素在客戶端,那么主要有瀏覽器緩存和 HTTPS 緩存,你可別認為緩存文件是在客戶端,這兩部分緩存都可以通過 Nginx 進行設置并作主要優化。
另外一個種類代理端的緩存(也就是緩存文件存放在代理服務的節點中),那 Nginx 作為反向代理服務的時候,可以支持代理緩存設置。
最后一個種類是將緩存文件放入后臺服務(通過后臺服務中程序邏輯來實現),例如我們可以將一部分數據通過此方式緩存,比如將用戶最長查看的數據(網站中登錄狀態、連接數等)緩存到 Memcache、Redis 中,避免直接請求關系型數據庫或其他服務,因為效率更高所以可以降低后端的延遲,也減少請求對數據庫的依賴度,從而整個網站的性能也會有很大的提升。
如果只考慮緩存最優的話,那么參考以下三點即可:
通常而言,一個網站如果做了緩存優化可以比沒做緩存優化的性能提升幾倍以上。下面我們就來具體介紹一下 Nginx 如何來設置緩存。
瀏覽器緩存通常是緩存到客戶端(如:瀏覽器、客戶端app),這就是瀏覽器緩存。
對于瀏覽器這部分緩存數據,我們通常可以把靜態元素,比如用戶請求的圖片、CSS 、JS 等元素緩存到客戶端。這種緩存可以通過 Nginx配置中的 expires 配置項進行設置,expires 后面可以加具體的時間,也可以加對應的特定意義的數值,比如 -1 表示永久緩存,max 設置最大周期緩存(默認緩存周期為 10 年),需要做具體的時間的設置可以寫入具體的時間周期,比如一個小時或是一天。
現在幾乎大部分網站都已經開啟了 HTTPS,當開啟https后客戶端訪問服務端打開一次瀏覽器,通過 HTTPS 方式會比 HTTP 請求握手會要增加很多次從而延遲也增加了。這時就需要考慮 HTTPS 是否有更好的優化方案來減少客戶端和服務端請求。
上面是一個 HTTPS 請求過程,實際在進行 HTTPS 請求之前需要進行 TCP 的三次握手過程,而這里我們只是描述 HTTPS 的建連過程,客戶端發送 hello 報文,服務端發送證書,客戶端進行加密,服務端驗證加密。這時開始進行服務端與客戶端的傳輸。我們看到整個 HTTPS 建立增加了部分的證書加密的協商。
多次的連接對于用戶和服務端而言,性能和延遲都會增加很多。并且如果每一次瀏覽器跟服務端斷開連接以后,又要進行一次整體的建立連接的過程。為了減少客戶端和服務端的斷開重連過程,這時就需要在 Nginx 中配置 ssl_session_cache 發揮作用。
當瀏覽器跟服務端建立第一次加密證書驗證的會話后,服務端會給客戶端瀏覽器緩存一個 SessionKey,如果客戶端跟服務端再次斷開連接,這時瀏覽器就可以拿 SessionKey 直接跟服務端進行交互。只需要進行一次校驗,就可以開始數據傳輸。我們看到有了 SessionKey 這種方式后,就可以避免瀏覽器跟服務端頻繁的進行 HTTPS 會話的建聯。
通過在 Nginx 中添加 ssl_session_cache 配置,配置中分配 Nginx 在處理 SSL 會話所需要開辟的共享內存的空間,我這里設置值為 10 MB,第二個參數就是設置 SSL SessionKey 的超時時間,這里設置的為 10 分鐘,也就是每隔 10 分鐘需要重新再進行一次建聯,這是一個在服務端的超時時間。
好了,上面就是對 HTTPS 在會話層進行的緩存優化示例。
打開文件緩存設置在 Nginx 端,通常而言我們會把一些靜態元素(如:JPG、CSS、GS)在代理端通過這種方式進行設置,這里 Nginx 緩存的是靜態元素的元數據。那么把元數據緩存到 Nginx 端有什么好處?元數據的作用就是緩存打開用戶所請求的靜態元素的文件路徑等信息,那么如果在本地頻繁地查找之前請求過的靜態元素文件而沒有緩存元數據時效率比較低,而如果我們把一部分索引數據緩存到 Nginx 的 Cache 下,這種頻繁訪問就可以很大地提高訪問效率。
我們來看 open_file_cache 具體的設置策略,max 表示最大能夠緩存的文件個數,inactive 表示最少的用戶使用次數。我們結合看一下,這個表示在 20 秒內最小需要使用兩次。如果沒有使用的話,就會把元數據刪掉,也這就是一個淘汰元數據的策略。
open_file_cache_valid 是設置主動更新和檢查的時間,表示每隔 30 秒檢查緩存文件的元信息有沒有對應的更新,如果有更新就需要去做對應的更新,它是一個更新的策略。
location / {
index index.htm index.html;
expires max;
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
最后就是代理緩存的優化了,代理緩存比較常見,比如說代理訪問 PHP 后臺服務并作緩存,也可以代理 JAVA 服務,緩存 JAVA 后臺服務的返回數據,注意這里不局限于通過 http_proxy來作代理緩存,只要 Nginx 支持的代理模式(UWSGI、SGI)都可以設置代理緩存。你可以來看一下通過http_proxy設置的如下示例:
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60mlocation / {
proxy_cache my_cache;
…
}
proxy_cache_path 表示在本地分配哪個路徑來存儲并緩存后臺返回數據;cache levels 表示存放文件的分層方式;my_cache:10m max_size=10g 分別表示是開辟一個名為my_cache共享塊(用于統計訪問次數)及緩存的單個文件的最大大小等。這些都是做對應的緩存在本地的文件目錄相關屬性的一些設置。另外一塊的設置表示在proxy_cache 的時候,通過 location 引用到 cache 的名稱。
代理緩存的特性是什么呢?首先通過 Nginx 作代理,可以支持實現動靜態的分離,靜態元素直接交給 Nginx 來處理,再把后端動態數據適當作緩存。通常做這種代理+緩存的架構,是能有效的提高整體網站的訪問并發性能。
對于緩存的整體使用,之前說的緩存越多越好,越靠前越好,命中率越高越好,但是同時我們也需要綜合考慮,并且注意緩存在使用時遇到的一些實際問題。
以上就是我們介紹的 Nginx 基礎配置優化和緩存配置優化,下一次我們說一下 Nginx 的負載均衡優化配置。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。