做爲一名後端屌絲程序員,對算法、併發、性能樂此不疲。可是,隨着年齡和閱歷的增長,顯然葉落而不知秋的心態是不太能混了。尤爲是,某T面試官在明知我是後端,且明確表示對HTTP協議不太熟的狀況下,強行讓我解釋HTTP狀態碼200至600的含義。這,即是本篇的初衷,講一講後端眼裏的前端故事。內容基於《深刻分析JavaWeb技術內幕》,加入了本身的理解,思惟會比較跳躍,須要後端基礎。html
做爲一名從CS架構轉入BS架構的後端,不得不說,BS是趨勢也是方向,兩個好處:前端
- 客戶端使用統一的瀏覽器,使用配置簡單
- 服務端基於統一的HTTP,簡化開發模式,而且開源服務器衆多,開發成本低
CS架構一般是長連接交互數據,而BS架構是經過基於HTTP協議的無狀態的短連接通信。當在瀏覽器輸入http://www.cnblogs.com/1024Community/
時,會發生一系列動做,最終將須要的信息返回到瀏覽器。其中涉及不少概念,如DNS解析、CDN、負載均衡等(後續會詳解),可是基本架構仍是差很少,基本流程是:java
瀏覽器輸入URL---DNS解析成對應IP---負載均衡服務器---CDN---服務端系統---分佈式緩存---文件系統/DB
linux
包含CDN的架構圖:程序員
歸納爲,經過URL解析到服務器IP,創建socket連接,發送符合HTTP規範的輸入流,等待服務器返回數據,而後斷開連接。linux中curl+URL命令,能夠簡單發起一個HTTP請求。web
HTTP是BS網絡架構的核心,程序員殺人放火之必備。
首先,要了解的是HTTP header部分,它控制着數據傳輸、瀏覽器渲染、服務器執行邏輯。
常見HTTP請求頭:
面試
常見響應頭:
算法
常見錯誤碼:
後端
總結:設計模式
HTTP請求頭,charset、encoding、language、host、User-Agent、Connection
HTTP響應頭,Server、type、encoding、language、length、Keep-Alive
HTTP常見狀態碼,200成功,302臨時跳轉,400請求語法錯誤,403服務器收到請求,拒絕服務,404請求資源不存在,500服務端異常
複雜而又重要,經常使用ctrl+F5組合鍵刷新界面,來得到最新數據。其原理是,在header中添加了兩項,Pragma:no-cache和Cache-Control:no-cache。對於緩存相關的header參數,主要以下:
Pragma/Cache-Control
緩存控制,Cache-Control優先級較高,和其餘請求字段同時存在時(如Expires),會覆蓋其餘字段。Pragma相似,經常使用就是Pragma:no-cache,可選值以下:
Expires
指定一個日期,超過這個日期,緩存超時,從新請求
Last-Modified/Etag
服務端響應頭中返回一個Last-Modified字段,告訴瀏覽器這個頁面的最後修改時間。當瀏覽器再次請求時,在header中添加If-Modified-Since
字段,來詢問頁面是否最新,最新則返回304,服務器也不會傳送數據。
Etag相似功能,爲每個頁面分配一個惟一編號,後端比較難處理,須要記住網站全部資源。
將域名解析成地址,很是重要。整個HTTP通訊都是基於TCP/IP協議簇的,沒有IP地址就無法通訊,可是IP地址是一串數字,難記,因此有了IP和域名的對應關係。有了對應關係,就要有解析,知道域名經過對應關係,就能獲得IP,從而創建起通訊。
看書說話,咱們來捋一捋,當你在瀏覽器輸入一串URL時,怎麼找到的對應服務器IP
Tips:
win下使用nslookup,linux使用dig查詢解析過程。 兩個緩存地方LDS和本地機器,可用命令刷新,JVM也會緩存DNS結果,使用InetAddress時,注意使用單例模式,避免性能問題。
Content Delivery Network(內容分佈網絡)相似鏡像+緩存+總體LB,一般緩存靜態資源,用戶主站取動態數據,CDN下載靜態數據。目標:可擴展,安全性,可靠性。
看圖說話,經過域名解析,一般會CNAME到CDN全局中的DNS負載均衡服務器,在經過這個GTM(廣域網流量管理)分配到離用戶最近的CDN節點。用戶就能夠到這個節點訪問靜態文件了。
負載均衡,分爲鏈路LB(DNS解析成不一樣IP)、集羣LB(分爲硬件和軟件,硬件貴,性能好,但不能動態擴容,如F5;軟件LB,如LVS)、操做系統LB(軟中斷和硬件中斷,如多隊列網卡)。
總結爲,經過CDN的DNS解析中經過動態的鏈路探測尋找回源最佳路徑,而後經過DNS調度將全部請求調度到選定的路徑上回源,加速用戶訪問效率
IO問題是人機交互的核心問題,是獲取和交換信息的渠道,向來是應用系統的瓶頸,Java也在持續優化,如1.4版本引入了NIO。整個java.io包幾十個類,有些概念再也不詳細介紹了(如字節流、字符流、io包繼承結構),整體上看IO大致分爲:
首先,數據持久化或網絡傳輸都是以字節進行的,這就涉及一個字符和字節轉化的問題,其中最重要的就是字符集編碼問題,不然很容易出現常見的亂碼問題,字符解碼類圖以下:
其中InputStreamReader類是從字節到字符轉化橋樑,過程當中要指定字符集,不然使用操做系統默認。
補充個UML知識,上圖中使用的是組合,是總體與部分的關係,代碼實現就是成員變量,以下
讀的時候,字節流轉化爲字符,要解碼(StreamDecoder),一樣道理,寫入是從字符到字節,須要編碼(StreamEncoder)
訪問文件,讀取和寫入是調用操做系統的IO接口,由於磁盤是由操做系統管理。而只要是系統調用就會存在內核空間和用戶空間切換問題,這自己是操做系統保護自己運行安全的機制,這就會出現一個問題,內核空間和用戶空間的數據複製
,因爲內核空間訪問快,用戶空間訪問慢,因此,出現了緩存。這是基本原理,幾種訪問文件方式以下:
數據複製
操做)File對象是個虛擬的描述,解碼類StreamDecoder、真正的文件描述類FileDescriptor,一圖勝萬言,以下,
序列化就是將一個對象轉爲爲一串二進制的字節數組,經過保存或轉移這些字節數據來達到持久化的目的。接口,java.io.Serializable。
對象序列化以後,查看二進制數組,會包含序列化協議、版本、是否新對象、class完整類名、UID、標記、所含域的個數、域類型、域名城、父類信息、類各屬性的實際值。
幾個Java序列化要點:
純Java環境,序列化能夠很好的工做。多語言環境見仍是推薦使用通用的數據結構如XML、JSON。
TCP創建過程,三次握手和四次揮手,過程以下:
兩個問題:
爲何A還要發送一次確認呢?能夠二次握手嗎?
爲了防止已失效的鏈接請求報文段忽然又傳送到了B,於是產生錯誤
爲何鏈接的時候是三次握手,關閉的時候倒是四次握手?
由於當Server端收到Client端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時,當Server端收到FIN報文時,極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端全部的報文都發送完了,我才能發送FIN報文,所以不能一塊兒發送。故須要四步握手。
底層TCP/IP協議,Socket和ServerSocket(accept以前是阻塞的)創建鏈接,經過字節流傳輸,傳輸過程當中,操做系統會爲InputStream和OutputStream分配必定大小緩衝區,數據讀寫經過緩衝區完成。
BIO方式,無論是網絡仍是磁盤,一旦有阻塞,線程都會失去CPU使用權。當須要大量HTTP長連接的狀況,或者提高個別IO請求優先級,或者競態資源同步,BIO處理起來會很是複雜,此時,NIO閃亮登場。顯然,這個話題須要一個嶄新的大篇幅來介紹,此處省略一萬字=。=
- 增長緩存,減小磁盤訪問次數 - 優化磁盤管理系統,設計最優的磁盤尋址策略(太底層) - 設計合理的磁盤存儲數據塊 - 應用合理的RAID策略提高磁盤IO
- 32位系統一般只有65535個端口,0~1024受保護,查看可用端口數量,較少時能夠經過更改tcp_fin_timeout位更小的值來快速釋放。經常使用信息: cat /proc/net/netstat :查看TCP統計信息 cat /proc/net/snmp :查看當前系統鏈接狀況 netstat -s :查看網絡統計信息
- 減小網絡交互次數 - 減小網絡傳輸數據量大小 - 減小編碼(重要,網絡流是字節形式,字符轉字節比較耗時,儘可能以字節形式傳輸或提早轉碼) - 同步和異步的選擇(同步就是一個任務的完成須要依賴另一個任務的完成) - 阻塞與非阻塞的選擇(阻塞就是CPU停下來等待一個慢的操做完成才接着完成其餘的工做) - 同步、異步、阻塞、非阻塞混搭組合(根據場景來選擇)
如下高能,須要功底:
適配器模式,關鍵點:Adapter完成源到目標的適配,通常是繼承源或持有源(構造器注入、方法注入等),實現目標接口。
裝飾器模式,關鍵點:在不改變源的接口的狀況下,進行功能擴展。io包InputStream各類裝飾器(FilterInputStream、BufferedInputStream等)經過持有源(構造器注入)來完成功能擴展。
二者都對類進行了包裝,二者的本質區別在於是否改變了源的接口
。
以上來自天團運營總監:坤少