本文章收錄於:後端工程師面試題目總結(提供參考答案)
目錄
2. Session和Cookie的區別?Session如何管理?
6. 解釋一下socket長連接?和Websocket協議的區別?
10. CLOSE_WAIT什麼時候出現?什麼場景出現大量CLOSE_WAIT?如何解決?
1. GET和POST區別是什麼,HTTP狀態碼瞭解哪些?
相同:兩者都是基於TCP協議工作的。
區別:
1.1 GET請求一般會被瀏覽器主動cache,POST不會
(這點很重要,cache刷新頁面瀏覽器不會再請求服務器,如果設置了max-age的話,減輕服務器負載,提升用戶體驗)
1.2 GET請求中傳送的參數是有長度限制的(協議規範沒有,各個瀏覽器有,IE最短是2083bytes),
POST沒有(但受服務器處理能力影響)。程序內部調用則URL長度不受限制。
1.3 GET參數是明文保存在URL中,POST參數保存在body中。
2. Session和Cookie的區別?Session如何管理?
相同:兩者都是用來跟蹤瀏覽器用戶身份的會話方式
區別:
- 2.1 cookie保存在客戶端,session在服務器端
- 2.2 保存在客戶端就意味着cookie可能被分析並用來實施cookie欺騙,而session不會(也只是相對安全)
- 2.3 session存在服務器端就意味着需要消耗服務器性能。
- 2.4 cookie的大小會被瀏覽器限制,一般是4KB(包括key-value),session沒有理論限制。
小結:cookie和session兩者各有優缺點,實際使用中可將兩者結合。
- session管理:
第一種:保存在服務端,由服務端將所有用戶的會話信息保存在內存中,然後返回一個唯一對應的sessionid給瀏覽器,瀏覽器將其保存在cookie中,下次請求發送cookie即可,如果服務器是集羣部署或者分佈式,可以用redis來存儲session。
第二種:cookie-based,即將用戶會話信息以cookie形式保存在瀏覽器,這種方式服務器無壓力。只是cookie大小受制於瀏覽器。
第三種:token-based,服務器將第一次登錄傳入的賬戶密碼做了驗證後,將時間戳+賬戶ID通過對稱加密後得到的子串發給瀏覽器作爲token,下次把明文賬戶ID和token放在header或者URL中帶過來就行了,服務端解密token驗證賬戶ID是否正確以及時間戳是否過期即可。
3. HTTPS的解釋?爲什麼要有HTTPS?
和HTTP一樣也屬於應用層,基於TCP協議,區別是:
HTTP默認工作在80端口;後者是443端口
HTTPS在HTTP基礎上加了一個加密的身份驗證層,即SSL。
全稱是:超文本傳輸安全協議。
爲什麼要有HTTPS(主要作用):
1. 建立一個信息安全通道,保證數據傳輸安全(HTTP是明文傳輸數據)。
2. 確認網站真實性,使用HTTPS必須註冊有效證書,證書包含註冊人相關信息。
4. 簡述HTTPS密鑰協商過程?(參考文章:https://www.cnblogs.com/binyue/p/4500578.html)
- 4.1 客戶端瀏覽器先將自己支持的一套加密規則發給網站服務器
- 4.2 服務器從中選出一套加密算法與HASH算法,並加上證書發回給瀏覽器。
證書中包含網站地址、加密公鑰、證書CA等信息。
- 4.3 然後瀏覽器做以下驗證:
1. 驗證CA是否合法,以及證書中的網站地址是否就是正在訪問的地址,若都正常則再驗證證書是否過期,
若過期則頁面會提示用戶,用戶自己選擇是否信任該證書。
2. 若證書有效或用戶選擇信任證書,瀏覽器會生成一串隨機密碼(這個很關鍵),並用公鑰加密。
3. 然後用之前約定好的HASH算法對握手消息進行HASH後得到一個hash值,
再用隨機密碼對明文握手消息【對稱加密】得到一個加密的握手消息。
將上面生成的:
a. 公鑰加密過的隨機密碼
b. 握手消息的hash值
c. 握手消息的對稱加密值
發送給服務器。
- 4.4 服務器收到一堆信息後做如下操作:
1. 用自己的私鑰解密取出隨機密碼
2. 用隨機密碼解密握手消息
3. 用協商好的hash算法對握手消息進行hash再匹配傳過來的hash值是否一致
4. 都OK,則用隨機密碼對稱加密一個自己的握手消息和這個握手消息的hash值發給瀏覽器
- 4.5 瀏覽器用隨機密碼提取握手消息,並計算hash值是否正確。
* 至此密鑰協商結束,隨機密碼就是後續的對稱加密解密的密鑰。
HTTPS一般使用的加密與HASH算法如下:
非對稱加密算法:RSA,DSA/DSS
對稱加密算法:AES,RC4,3DES
HASH算法:MD5,SHA1,SHA256
小結:HTTPS的通信過程分兩階段:密鑰協商階段+數據傳輸階段,前者使用非對稱加密,後者使用對稱加密。
每個客戶端協商的密鑰不同,服務器將維護多個密鑰
爲什麼後面要用相比不太安全的的對稱加密?
答:因爲相較於非對稱,對稱加密不需要過多數學計算,更快更高效。
備註:證書申請之後,自己會有兩個證書相關文件,一個是包含證書公鑰、綁定域名、CA相關信息的文件,另一個是證書私鑰,用來在HTTPS祕鑰協商過程中使用的,證書文件的後綴可以是pem/cer/crt等,私鑰文件後綴一般是pem,可參考此鏈接下文部分說明。
擴展:SSL證書申請過程
5. 簡述跨域產生背景以及常見解決方案?
- 5.1 產生背景
實際開發工作中經常會有跨域的情況發生,比如
1. 一個公司一般都有多個項目,自然也會有多個子域名,項目之間會有相互調用對方的功能/資源的需求,
可以節省許多不必要的開發工作。
2. 現在需要項目都是前後端分離,前端調用後端資源就是跨域請求。
- 5.2 解決方案
a. CORS(跨域資源共享)
1. 需要瀏覽器支持,不過現在的瀏覽器幾乎都支持。
2. 這種方案會使得瀏覽器多出一次附加的預檢請求(針對非簡單請求)
一般在nginx中進行配置,之後就不用再app中配置。
在nginx的enable-cors.conf文件進行header配置,可以指定允許的跨域源URL。然後在nginx.conf
中include [enable-cors.conf]這個文件。
擴展:服務器返回的“Access-Control-Max-Age” 是什麼作用?
答:用來指定本次預檢的有效期,單位秒。有效期類同一個URL無需再發預檢請求。
b. jsonp跨域(僅支持GET方式)
6. 解釋一下socket長連接?和Websocket協議的區別?
Socket長連接其實指的就是TCP長連接的(UDP沒有連接)
指的是一個TCP連接上可以連續發送多個數據報,在連接空閒時,通過心跳包(keep-alive)維持,兩端都有超時機制。
優勢:降低資源消耗,提高數據傳輸速率。(連接的建立和銷燬比較浪費時間和資源)
使用場景:訪問量(連接數)較少,通訊頻繁的情況,如聊天室、數據庫連接。
和Websocket協議的區別?
socket長連接是允許一個TCP連接存活更久,更靠近底層,但消息邊界需要自己處理,而且是單工的,即客戶方是固定的。
websocket則是一種全新的協議,它基於http協議建立一個長久的連接,不需要處理消息邊界問題,而且是一個全雙工的模式;
不需要心跳來維持,但是實際情況中可能會因爲網絡質量差或nginx訪問超時設置等原因導致連接斷開,所以一般都會
在客戶端設置心跳機制(30s一次)。
7. 談談select和poll和epoll
select:時間複雜度是O(n)
是對所有scoket句柄(fd)進行定時輪詢,發現有準備就緒的fd,就對其操作。
fd越多,輪詢時間越長,當有準備就緒的fd是排在最後時,效率很低。
poll:時間複雜度是O(n)
本質上和select無差別,都是輪詢機制,只是它沒有最大fd數量限制。
epoll:時間複雜度是O(1)
這是一種事件驅動的機制,epoll能直接知道哪個fd狀態變化,然後直接調用對應回調函數。
這是一種非常高效率的機制,fd數量增加也不會影響其效率,上面兩種會直接受到影響。
8. TCP與UDP區別;簡述三次握手和四次揮手過程
相同:傳輸層協議,用於報文傳輸
不同:TCP比UDP可靠,是面向連接的,擁有三次握手和四次揮手、以及流量管理、擁塞控制等機制來保證傳輸過程可靠,安全。
而UDP傳輸過程簡單,快速高效,且開銷小,因爲沒有建立連接的過程,報文頭部僅8字節,TCP頭部20字節以及40字節可選項。
但是它沒有ACK和序列號機制,無法解決報文丟失和順序錯亂問題。
TCP只能點對點(P2P),UDP可以一對一,一對多,多對多(P2MP)。
- 三次握手:
1. client發送SYN(seq=x)報文 => server(client狀態變爲SYN_SENT)
2. server發送ACK(seq=x+1)以及SYN(seq=y)報文 =>client (server狀態變爲SYN_RECV)
3. client發送ACK(seq=y+1) => server (client變爲ESTABLISHED,服務器收到後也變爲ESTABLISHED)
- 四次揮手:
1. client發送FIN(seq=x) =>server (client變爲FIN_WAIT_1)
2. server先回復ACK(seq=x+1) => client (server只要收到FIN報文就會變爲CLOSE_WAIT, client變爲FIN_WAIT_2)
3. server發送完剩餘的數據報文後,再發送FIN(seq=y) =>client (server變爲LAST_CHECK)
4. client發送ACK(seq=y+1) => server (client變爲TIME_WAIT)
server收到ACK後直接就關閉closed狀態,但client要等2MSL(最大報文生存時間)纔會變爲closed。
client的狀態轉變順序:established-->fin_wait_1->fin_wait_2->time_wait->closed
server的狀態轉變順序: established-->close_wait->last_ack->closed
9. TIME_WAIT過多的原因?如何解決?
注意:TIME_WAIT只出現在“客戶端”,這個“客戶端”指的是先發FIN報文的一方。那麼這裏出現過多的TIME_WAIT的一方肯定不是我們常見的那個客戶端,而是後臺服務器,後臺主動斷開連接,那麼它自然就成了所謂的“客戶端”。
這種情況一般出現在服務器短時間內處理了大量TCP請求,主動關閉連接時就會有這個狀態,這個狀態將持續可能1-4分鐘。
在這些連接狀態變爲CLOSED前其佔用端口都不能再使用,即無法建立新的連接。
修改內核配置/etc/sysctl.conf:
net.ipv4.tcp_syncookies = 1 表示開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,
可防範少量SYN攻擊,默認爲0,表示關閉;
net.ipv4.tcp_tw_reuse = 1 表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉;
net.ipv4.tcp_tw_recycle = 1 表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉。
net.ipv4.tcp_fin_timeout 表示如果套接字由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。
net.ipv4.tcp_max_tw_buckets = 10000 表示系統同時保持TIME_WAIT套接字的最大數量
使之生效: /sbin/sysctl -p
10. CLOSE_WAIT什麼時候出現?什麼場景出現大量CLOSE_WAIT?如何解決?
CLOSE_WAIT是被動關閉方收到FIN報文後的狀態,然後等待自身數據傳輸完成後,就會變爲LAST_ACK狀態。
什麼場景出現大量CLOSE_WAIT:
主動關閉方發送了FIN報文,但被動關閉方收到之後沒有響應(一般是因爲上層服務沒有及時調用socket的close方法,
原因可能是程序死鎖導致的耗時過久),主動關閉方會在自己設置的tcp連接超時時間結束後關閉socket,而被動關閉方則一直保持CLOSE_WAIT,直至超時。(默認CLOSE_WAIT會保持2小時)
解決:檢查服務端(出現CLOSE_WAIT)的機器本身對應進程的問題。
如果程序本身沒有問題,則修改內核參數:
net.ipv4.tcp_keepalive_time = 1800 TCP連接的超時時間,默認7200s,適當減小這個值
net.ipv4.tcp_keepalive_probes = 3 超時後探測包發送的次數,達到上面這個時間後以及探測包發送次數上限後,斷開連接。
net.ipv4.tcp_keepalive_intvl = 15 超時後探測包發送的時間間隔
11. 一個http請求由哪幾部分組成?
由請求方法、請求頭、空行、請求體組成。
12. 談談HTTP長連接和短連接
短連接就是一個http請求完成後即斷開TCP連接,下次來仍然需要建立連接。
長連接是一個http請求完成後仍然保持TCP連接,同域名下依然可以用這個通道傳輸數據。
HTTP1.1 默認保持長連接,HTTP1.0就需要設置 Connection: Keep-alive。
設置Connection: close 則不使用長連接。
通過Keep-Alive : timeout-20(或max=20) 查看長連接最大空閒時間/單個長連接最大請求次數。
當然服務端有可能不會告訴客戶端連接保持時間,這不影響什麼,服務端最後會用四次揮手來關閉連接,客戶端
會知道該連接不可用然後重新建立連接。
長連接通過兩種方式來識別單次傳輸結束:
1. 通過Content-Length字段
2. 若數據是動態生成,沒有Content-Length,那就是分塊傳輸(chunked),通過header中的Transfer-Encoding:chunk設置, 這時候通過最後一個長度爲0的chunk來判斷該次傳輸結束。
13. HTTP長連接與TCP長連接的關係
前者處於應用層協議機制,後者是傳輸層機制,前者實現基於後者。
HTTP中的keep-alive表示客戶端希望服務器持久化本次TCP連接通道;
TCP中的keep-alive是TCP協議的長連接機制,通過配置keep-alive超時時間來設置TCP連接的最大空閒時間,
TCP連接空閒超時後,未關閉的socket會定時發送探測包來檢測通道是否正常,若發送N次都未收到迴應,則認爲對方已關閉,然後關閉自己的socket。