相信做爲一個web開發者,大家都有遇到過網站訪問瓶頸的情況,那麼如何通過一些技術手段來解決這個網站訪問的性能問題呢?
首先,需要明確的一點是引發網站性能瓶頸的因素有哪些?
一、服務器
服務器方面又可以細分爲硬件和系統架構的原因,比如當一個日常在2000 DAU的電商網站突然因爲做促銷活動網站的pv暴增的時候,肯定就要考慮擴容了,另一方面系統架構的原因,主要體現在我們選擇的服務器端框架有時候決定了網站的瓶頸,Apache和Ngix支持的併發數量就不一樣,另一方面,我們可以通過負載均衡的方式來降低服務器的壓力,來加快服務器的訪問速度。
一般負載均衡的幾種方式:
負載均衡也是Nginx常用的一個功能,負載均衡其意思就是分攤到多個操作單元上進行執行,例如Web服務器、FTP服務器、企業關鍵應用服務器和其它關鍵任務服務器等,從而共同完成工作任務。
簡單而言就是當有2臺或以上服務器時,根據規則隨機的將請求分發到指定的服務器上處理,負載均衡配置一般都需要同時配置反向代理,通過反向代理跳轉到負載均衡。而Nginx目前支持自帶3種負載
均衡策略,還有2種常用的第三方策略。
1.RU(輪詢的方式)這是Nginx默認的
#每個請求按時間順序逐一分配到不同的後端服務器,如果後端服務器down掉,能自動剔除
upstream test {
server localhost:8080;
server localhost:8081;
}
server {
listen 81;
server_name localhost;
client_max_body_size 1024M;
location / {
proxy_pass http://test;
proxy_set_header Host $host:$server_port;
}
}
Remark:
這裏我配置了2臺服務器,實際上也可能只有一臺,只是端口不一樣而已,如果服務器處於不能訪問(服務器掛了),就不會跳轉到這臺服務器,所以也避免了一臺服務器掛了影響使用的情況,由於Nginx默認是RR策略,所以我們不需要其他更多的設置
2.ip-hash
upstream test {
ip_hash;
server localhost:8080;
server localhost:8081;
}
3.權重的方式
#指定輪詢機率,weight和訪問比率成正比,用於後端服務器性能不均的情況
upstream test {
server localhost:8080 weight=9;
server localhost:8081 weight=1;
}
備註:上面的2種方式都有一個問題,那就是下一個請求來的時候請求可能分發到另外一個服務器,當我們的程序不是無狀態的時候(採用了session保存數據),這時候就有一個很大的很問題了,比如把登錄信息保存到了session中,那麼跳轉到另外一
臺服務器的時候就需要重新登錄了,所以很多時候我們需要一個客戶只訪問一個服務器,那麼就需要用iphash了,iphash的每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。
4.fair
#按後端服務器的響應時間來分配請求,響應時間短的優先分配
upstream backend {
fair;
server localhost:8080;
server localhost:8081;
}
複製代碼
5.url-hash
按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。 在upstream中加入hash語句,server語句中不能寫入weight等其他的參數,hash_method是使用的hash算法
upstream backend {
hash $request_uri;
hash_method crc32;
server localhost:8080;
server localhost:8081;
}
另一方面,在服務器的代碼設計上,我們可以把一些頁面靜態化設置,這樣可以適當減少對數據庫的訪問壓力
二、數據庫
在用戶與服務器的交互過程中,很大一部分時間是耗費在數據庫的CURD操作上,所以對於數據庫的優化可以很大成都上來優化頁面的訪問體驗。那麼如何優化服務器的訪問速度呢?
I)數據庫表的設計:
1.數據表在設計的時候,在需要經常查詢的字段上添加索引
2.主鍵使用自增還是UUID?
主鍵肯定還是使用自增,innodb的主鍵是聚族索引,如果主鍵是自增的,那麼每次插入的新數據都會順序添加到當前索引節點的後續位置,當一頁寫滿時,就會自動開啓第二頁,如果不是自增鍵,那麼就可能在中間插入,就會引發頁的分裂,產生很多碎片,總之用自增的主鍵性能更好。
UUID產生的索引文件更大,當數據量超過一百萬行時,主鍵查詢性能和索引文件大小都比UUID要更有效率和更小。
3.枚舉的字段最好不要使用enum類型
原因如下:
a).ENUM類型,order by操作效率低,需要額外的操作
b). 如果枚舉是數值,有陷阱
例如:表結構如下create table test(sex enum('0','1'))此時執行插入語句insert into test values(1) 查詢的結果爲0
只有這樣插入insert into test values('1')此時結果纔是1
c).字段爲什麼要定義爲not null
1)索引性能更好
2)使用not null會出現一些不可預料的結果
II).數據庫的設計
常用的方式有主從數據庫的設計以及讀寫分離,對於一些訪問量大的網站或應用,我們還需要做主從數據庫的設計,和數據庫的讀寫分離。
III)數據庫的選擇
數據庫通常分爲SQL和NoSQL類型,具體他們的區別建議看這篇文章:Sql or NoSql,看這一篇就夠了 ,關於選擇SQL還是NoSQL,一般的建議是,如果公司的業務併發量不大的情況下,可以選擇Mysql此類的Sql數據庫,Mysql的服務穩定,數據一致性更好一些,但是如果公司的業務併發量比較大,那麼非常建議使用NoSQL類型的數據庫,常見的代表類型是MongoDB和Redis,Redis以其高性能,高併發,吞吐量大在電商、遊戲等行業內應用普遍。加之Redis是在內存中處理一些操作的,在使用RDB或者AOF來持久化到硬盤的方式,決定了Redis是天生的性能強者。 關於Redis 的運用我會再另外寫一篇的文章來介紹。
the end>>>>>>>>>>>>>>>>>>
關於頁面的優化的一些淺顯的認識,後面在實戰過程中有好的經驗,我會繼續更新到這裏,大家有好的經驗也歡迎寫到留言區裏面。