OSI七層模型 vs. TCP/IP 五層模型(有時候也說四層)及各層協議
七層:物理層:為數據端設備提供傳送數據的通路, IEEE802
?????? ? 數據鏈路層:提供介質訪問和鏈路管理, ARP,MTU
?????? ? 網絡層:IP選址及路由選擇,IP,ICMP
?????? ? 傳輸層:建立,管理和維護端到端的連接,TCP,UDP
?????? ? 會話層:建立,管理和維護會話
?????? ? 表示層:數據格式轉化,數據加密
?????? ? 應用層:為應用層序提供服務,FTP,SMTP,DNS,Telnet,HTTP
?
給定一個網址,訪問這個網址經過了那些過程?涉及哪些協議?
(1) 瀏覽器通過域名判斷使用哪種協議訪問服務器
(2) 瀏覽器向DNS請求解析域名對應的IP地址
(瀏覽器緩存>本地host>本地DNS服務器>DNS服務器緩存>根DNS服務器或轉發模式下的上一級DNS服務器)
(3) 域名系統DNS解析出IP地址
(4) 瀏覽器與該服務器建立TCP連接
(5) 瀏覽器發出HTTP請求,請求百度首頁
(6) 服務器通過HTTP響應把首頁文件發送給瀏覽器
(7) 瀏覽器將首頁文件進行解析,并將Web頁顯示給用戶
涉及協議:HTTP/HTTPS,DNS,UDP,TCP,IP,ARP(將本機默認網關 ip 地址映射成物理 MAC 地址,這樣數據包便可以在以太網上傳輸)
HTTP概述
HTTP(hypertext transport protocol),即超文本傳輸協議。這個協議詳細規定了瀏覽器和萬維網服務器之間互相通信的規則。
HTTP就是一個通信規則,通信規則規定了客戶端發送給服務器的內容格式,也規定了服務器發送給客戶端的內容格式。其實我們要學習的就是這個兩個格式!客戶端發送給服務器的格式叫“請求協議”;服務器發送給客戶端的格式叫“響應協議”。???
請求協議
請求協議的格式如下:
請求首行; 包括請求類型,要訪問的資源以及所使用的HTTP版本. 請求頭信息; 空行; \r\n???? ?DOS/Windows:’\r\n’?????? UNIX/Linux:’\n’??????? Mac:’\r’ 請求體。 |
?
瀏覽器發送給服務器的內容就這個格式的,如果不是這個格式服務器將無法解讀!在HTTP協議中,請求有很多請求方法,其中最為常用的就是GET和POST。不同的請求方法之間的區別,后面會一點一點的介紹。
GET請求
打開IE,在訪問hello項目的index.jsp之間打開HttpWatch,并點擊“Record”按鈕。然后訪問index.jsp頁面。查看請求內容如下:
GET /hello/index.jsp HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Cookie: JSESSIONID=369766FDF6220F7803433C0B2DE36D98
?
- GET /hello/index.jsp HTTP/1.1:GET請求,請求服務器路徑為/hello/index.jsp,協議為1.1;
- Host:localhost:請求的主機名為localhost;
- User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0:與瀏覽器和OS相關的信息。有些網站會顯示用戶的系統版本和瀏覽器版本信息,這都是通過獲取User-Agent頭信息而來的;
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8:告訴服務器,當前客戶端可以接收的文檔類型,其實這里包含了*/*,就表示什么都可以接收;
- Accept-Language: zh-cn,zh;q=0.5:當前客戶端支持的語言,可以在瀏覽器的工具à選項中找到語言相關信息;
- Accept-Encoding: gzip, deflate:支持的壓縮格式。數據在網絡上傳遞時,可能服務器會把數據壓縮后再發送;
- Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7:客戶端支持的編碼;
- Connection: keep-alive:客戶端支持的鏈接方式,保持一段時間鏈接,默認為3000ms;(無狀態的)
- Cookie: JSESSIONID=369766FDF6220F7803433C0B2DE36D98:因為不是第一次訪問這個地址,所以會在請求中把上一次服務器響應中發送過來的Cookie在請求中一并發送去過
POST請求
為了演示POST請求,我們需要修改index.jsp頁面,即添加一個表單:
<form action="" method="post"> ? 關鍵字:<input type="text" name="keyword"/> ? <input type="submit" value="提交"/> </form> |
?
打開HttpWatch,輸入hello后點擊提交,查看請求內容如下:
POST /hello/index.jsp HTTP/1.1Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*Referer: http://localhost:8080/hello/index.jspAccept-Language: zh-cn,en-US;q=0.5User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.2; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)Content-Type: application/x-www-form-urlencodedAccept-Encoding: gzip, deflateHost: localhost:8080Content-Length: 13Connection: Keep-AliveCache-Control: no-cacheCookie: JSESSIONID=E365D980343B9307023A1D271CC48E7Dkeyword=hello
POST請求是可以有體的,而GET請求不能有請求體。
- Referer: http://localhost:8080/hello/index.jsp:請求來自哪個頁面,例如你在百度上點擊鏈接到了這里,那么Referer:http://www.baidu.com;如果你是在瀏覽器的地址欄中直接輸入的地址,那么就沒有Referer這個請求頭了;
- Content-Type: application/x-www-form-urlencoded:表單的數據類型,說明會使用url格式編碼數據;url編碼的數據都是以“%”為前綴,后面跟隨兩位的16進制,例如“傳智”這兩個字使用UTF-8的url編碼用為“%E4%BC%A0%E6%99%BA”;
- Content-Length:13:請求體的長度,這里表示13個字節。
- keyword=hello:請求體內容!hello是在表單中輸入的數據,keyword是表單字段的名字。
?
Referer請求頭是比較有用的一個請求頭,它可以用來做統計工作,也可以用來做防盜鏈。
統計工作:我公司網站在百度上做了廣告,但不知道在百度上做廣告對我們網站的訪問量是否有影響,那么可以對每個請求中的Referer進行分析,如果Referer為百度的很多,那么說明用戶都是通過百度找到我們公司網站的。
防盜鏈:我公司網站上有一個下載鏈接,而其他網站盜鏈了這個地址,例如在我網站上的index.html頁面中有一個鏈接,點擊即可下載JDK7.0,但有某個人的微博中盜鏈了這個資源,它也有一個鏈接指向我們網站的JDK7.0,也就是說登錄它的微博,點擊鏈接就可以從我網站上下載JDK7.0,這導致我們網站的廣告沒有看,但下載的卻是我網站的資源。這時可以使用Referer進行防盜鏈,在資源被下載之前,我們對Referer進行判斷,如果請求來自本網站,那么允許下載,如果非本網站,先跳轉到本網站看廣告,然后再允許下載。
?
HTTP方法及相互區別
GET 用于獲取資源,而 POST 用于傳輸實體主體。
GET 和 POST 的請求都能使用額外的參數,但是 GET 的參數是以查詢字符串出現在 URL 中,而 POST 的參數存儲在實體主體中。不能因為 POST 參數存儲在實體主體中就認為它的安全性更高,因為照樣可以通過一些抓包工具(Fiddler)查看
因為 URL 只支持 ASCII 碼,因此 GET 的參數中如果存在中文等字符就需要先進行編碼。例如中文會轉換為%E4%B8%AD%E6%96%87 ,而空格會轉換為%20。POST參數支持標準字符集。
GET請求在URL中傳送的參數是有長度限制的,而POST么有
HEAD獲取報文首部,和 GET 方法類似,但是不返回報文實體主體部分
?
其他請求方法
GET(SELECT):從服務器取出資源(一項或多項)。
POST(CREATE):在服務器新建一個資源。
PUT(UPDATE):在服務器更新資源(客戶端提供改變后的完整資源,數據輸入必須與由 GET 接收的數據表示保持一致)。
PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。
DELETE(DELETE):從服務器刪除資源。
HEAD:獲取資源的元數據。
OPTIONS:
1、獲取服務器支持的HTTP請求方法
2、用來檢查服務器的性能
?
響應內容
響應協議的格式如下:
響應首行;由HTTP協議版本號, 狀態碼, 狀態消息 三部分組成。 響應頭信息; 空行; 響應體。 |
?
響應內容是由服務器發送給瀏覽器的內容,瀏覽器會根據響應內容來顯示。
HTTP/1.1 200 OKServer: Apache-Coyote/1.1Content-Type: text/html;charset=UTF-8Content-Length: 724Set-Cookie: JSESSIONID=C97E2B4C55553EAB46079A4F263435A4; Path=/helloDate: Wed, 25 Sep 2012 04:15:03 GMT<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="http://localhost:8080/hello/"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">???<meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body><form action="" method="post">關鍵字:<input type="text" name="keyword"/><input type="submit" value="提交"/></form></body></html>
- HTTP/1.1 200 OK:響應協議為HTTP1.1,狀態碼為200,表示請求成功,OK是對狀態碼的解釋;
- Server: Apache-Coyote/1.1:服務器的版本信息;
- Content-Type: text/html;charset=UTF-8:響應體使用的編碼為UTF-8;
- Content-Length: 724:響應體為724字節;
- Set-Cookie: JSESSIONID=C97E2B4C55553EAB46079A4F263435A4; Path=/hello:響應給客戶端的Cookie;
- Date: Wed, 25 Sep 2012 04:15:03 GMT:響應的時間,這可能會有8小時的時區差;
HTTP and HTTPS
1、https協議需要到ca申請證書,一般免費證書較少,因而需要一定費用。
2、http信息是明文傳輸,https則是通過TLS加密后傳輸。
3、http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
HTTP缺點
- 明文傳輸,內容可能會被竊聽
- 不驗證通信方的身份,因此有可能遭遇偽裝
- 無法證明報文的完整性,所以有可能已遭篡改
HTTP+加密+認證+完整性保護=HTTPS
用SSL將通信的報文主體內容進行加密,使用SSL建立http的安全通信線路,SSL處于http與TCP通信之間,這樣的SSL與HTTP組合被稱為HTTPS。
HTTPS 采用對稱加密和非對稱加密兩者并用的混合加密機制
SSL/TLS
SSL(Secure Socket Layer安全套接字層)TLS(Transport Layer Security)SSL發展到3.0版本后改成了TLS。
TLS主要提供三個基本服務
- 加密
- 身份驗證
- 消息完整性校驗
通常,HTTP 直接和 TCP 通信。當使用 SSL 時,則演變成先和 SSL 通信,再由 SSL 和 TCP 通信了。用 SSL 建立安全通信線路之后,就可以在這條線路上進行 HTTP 通信了。
SSL 是獨立于 HTTP 的協議,所以不光是 HTTP 協議,其他運行在應用層的 SMTP 和 Telnet 等協議均可配合 SSL 協議使用。可以說 SSL 是當今世界上應用最為廣泛的網絡安全技術。
雖然使用 HTTP 協議無法確定通信方,但如果使用 SSL 則可以。SSL 不僅提供加密處理,而且還使用了一種被稱為證書的手段,可用于確定雙方身份。
證書由值得信任的第三方機構頒發,用以證明服務器和客戶端是實際存在的。另外,偽造證書從技術角度來說是異常困難的一件事。所以只要能夠確認通信方(服務器或客戶端)持有的證書,即可判斷通信方的真實意圖。
?
HTTP報文格式
請求報文:請求行,消息頭部,請求正文
響應報文:狀態行,響應頭部,響應正文
?
HTTP的無狀態
因為它的每個請求都是完全獨立的,每個請求包含了處理這個請求所需的完整的數據,發送請求不涉及到狀態變更。即使在HTTP/1.1上,同一個連接允許傳輸多個HTTP請求的情況下,如果第一個請求出錯了,后面的請求一般也能夠繼續處理(當然,如果導致協議解析失敗、消息分片錯誤之類的自然是要除外的)可以看出,這種協議的結構是要比有狀態的協議更簡單的,一般來說實現起來也更簡單,不需要使用狀態機
對于有狀態協議來說,如果將會話狀態與連接綁定在一起,那么如果連接意外斷開,整個會話就會丟失,重新連接之后一般需要從頭開始
而HTTP這樣的無狀態協議,使用元數據(如Cookies頭)來維護會話,使得會話與連接本身獨立起來,這樣即使連接斷開了,會話狀態也不會受到嚴重傷害,保持會話也不需要保持連接本身。另外,無狀態的優點還在于對中間件友好,中間件無需完全理解通信雙方的交互過程,只需要能正確分片消息即可,而且中間件可以很方便地將消息在不同的連接上傳輸而不影響正確性,這就方便了負載均衡等組件的設計。
具體無狀態解決
客戶端和服務器在某次會話中產生的數據,從而【無狀態】就意味著,這些數據不會被保留;協議對于事務處理沒有記憶能力,服務器不知道客戶端是什么狀態。但是通過增加cookie和session機制,現在的網絡請求其實是有狀態的。在沒有狀態的http協議下,服務器也一定會保留你每次網絡請求對數據的修改,但這跟保留每次訪問的數據是不一樣的,保留的只是會話產生的結果,而沒有保留會話。
與之相對的是TCP,TCP是有狀態的,因為每一條消息的seq和ack(還有一堆滑動窗口,擁塞的控制參數,等)都和前面消息相關。
HTTP并不會在內存里保留前次請求相關的任何狀態,僅僅以協議邏輯(打包解包)存在,所以是它無狀態的。
?
無狀態的設計會加強透明度(visibility),穩定度(reliability)和伸縮度(scalability)。提高透明度是因為系統無需通過請求內容以外的信息判斷請求的完整內容;提高穩定度是指在部分失敗的情況下,減輕了恢復的難度;提高伸縮度的原因是無需儲存請求間的狀態使服務器端可以很快釋放資源并簡化實現。
優點在于解放了服務器,每一次請求“點到為止”不會造成不必要連接占用,缺點在于每次請求會傳輸大量重復的內容信息。
?
HTTP狀態碼
100 Continue :表明到目前為止都很正常,客戶端可以繼續發送請求或者忽略這個響應。
200 OK
204 No Content :請求已經成功處理,但是返回的響應報文不包含實體的主體部分。一般在只需要從客戶端往服務器發送信息,而不需要返回數據時使用。
206 Partial Content :表示客戶端進行了范圍請求,響應報文包含由 Content-Range 指定范圍的實體內容。
301 Moved Permanently :永久性重定向
302 Found :臨時性重定向
303 See Other :和 302 有著相同的功能,但是 303 明確要求客戶端應該采用 GET 方法獲取資源。
304 Not Modified :表示資源在由請求頭中的If-Modified-Since或If-None-Match參數指定的這一版本之后,未曾被修改。在這種情況下,由于客戶端仍然具有以前下載的副本,因此不需要重新傳輸資源。
307 Temporary Redirect :臨時重定向,與302相反,當重新發出原始請求時,不允許更改請求方法。
400 Bad Request :請求報文中存在語法錯誤
401 Unauthorized :該狀態碼表示發送的請求需要有認證信息。如果之前已進行過一次請求,則表示用戶認證失敗
403 Forbidden :請求被拒絕
404 Not Found :請求失敗,請求所希望得到的資源未被在服務器上發現,但允許用戶的后續請求。
500 Internal Server Error :服務器正在執行請求時發生錯誤
503 Service Unavailable :服務器暫時處于超負載或正在進行停機維護,現在無法處理請求。
504 Gateway Timeout作為網關或者代理工作的服務器嘗試執行請求時,未能及時從上游服務器
?
HTML中指定響應頭
在HTMl頁面中可以使用<meta http-equiv="" content="">來指定響應頭,例如在index.html頁面中給出<meta http-equiv="Refresh" content="3;url=http://www.itcast.cn">,表示瀏覽器只會顯示index.html頁面3秒,然后自動跳轉到http://www.itcast.cn。
?
?
HTTP 1.0 vs 1.1 vs 2.0
HTTP1.0只保持短暫的連接,連接無法復用,瀏覽器每次請求都和服務器經過三次握手和慢啟動。http1.0被抱怨最多的就是連接無法復用,和head of line blocking(請求隊列的第一個請求因為服務器正忙(或請求格式問題等其他原因),導致后面的請求被阻塞)這兩個問題。
HTTP1.1 支持持久連接 一個TCP連接可以傳送多個http請求和響應,減少了TCP建立連接和關閉連接的消耗。另外http1.1允許客戶端不用等待上一次請求結果返回,就可以發出下一次請求,但服務器端必須按照接收到客戶端請求的先后順序依次回送響應結果,以保證客戶端能夠區分出每次請求的響應內容。
節約帶寬 HTTP 1.1支持只發送header信息(不帶任何body信息),如果服務器認為客戶端有權限請求服務器,則返回100,否則返回401。客戶端如果接受到100,才開始把請求body發送到服務器.這樣當服務器返回401的時候,客戶端就可以不用發送請求body了,節約了帶寬。另外HTTP還支持傳送內容的一部分。這樣當客戶端已經有一部分的資源后,只需要跟服務器請求另外的部分資源即可。這是支持文件斷點續傳的基礎。
HOST域 web server上的多個虛擬站點可以共享同一個ip和端口。HTTP1.0是沒有host域的,HTTP1.1才支持這個參數。
HTTP2.0 多路復用 HTTP2.0使用了多路復用的技術,做到同一個連接并發處理多個請求,而且并發請求的數量比HTTP1.1大了好幾個數量級。
數據壓縮 HTTP1.1不支持header數據的壓縮,HTTP2.0使用HPACK算法對header的數據進行壓縮,這樣數據體積小了,在網絡上傳輸就會更快。
服務器推送 當我們對支持HTTP2.0的web server請求數據的時候,服務器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次創建連接發送請求到服務器端獲取。
服務器推送還有一個很大的優勢:可以緩存!也讓在遵循同源的情況下,不同頁面之間可以共享緩存資源成為可能。
?
HTTP安全性
使用明文進行通信,內容可能會被竊聽;
不驗證通信方的身份,通信方的身份有可能遭遇偽裝;
無法證明報文的完整性,報文有可能遭篡改。
?
TCP 及 UDP
傳輸控制協議 TCP(Transmission Control Protocol)是面向連接的,提供可靠交付,有流量控制,擁塞控制,提供全雙工通信,面向字節流(把應用層傳下來的報文看成字節流,把字節流組織成大小不等的數據塊),每一條 TCP 連接只能是點對點的(一對一)。
用戶數據報協議 UDP(User Datagram Protocol)是無連接的,盡最大可能交付,沒有擁塞控制,面向報文(對于應用程序傳下來的報文不合并也不拆分,只是添加 UDP 首部),支持一對一、一對多、多對一和多對多的交互通信。
?
TCP如何保證可靠傳輸?
1、確認和重傳:接收方收到報文就會確認,發送方發送一段時間后沒有收到確認就重傳。
2、數據校驗
3、數據合理分片和排序
4、流量控制:當接收方來不及處理發送方的數據,能提示發送方降低發送的速率,防止包丟失。
5、擁塞控制:當網絡擁塞時,減少數據的發送。
?
TCP的三次握手和四次揮手及其原因
第三次握手是為了防止失效的連接請求到達服務器,讓服務器錯誤打開連接。客戶端發送的連接請求如果在網絡中滯留,那么就會隔很長一段時間才能收到服務器端發回的連接確認。客戶端等待一個超時重傳時間之后,就會重新請求連接。但是這個滯留的連接請求最后還是會到達服務器,如果不進行三次握手,那么服務器就會打開兩個連接。如果有第三次握手,客戶端會忽略服務器之后發送的對滯留連接請求的連接確認,不進行第三次握手,因此就不會再次打開連接
客戶端發送了 FIN 連接釋放報文之后,服務器收到了這個報文,就進入了 CLOSE-WAIT 狀態。這個狀態是為了讓服務器端發送還未傳送完畢的數據,傳送完畢之后,服務器會發送 FIN 連接釋放報文。
客戶端接收到服務器端的 FIN 報文后進入TIME_WAIT狀態,此時并不是直接進入 CLOSED 狀態,還需要等待一個時間計時器設置的時間 2MSL。這么做有兩個理由:
確保最后一個確認報文能夠到達。如果 B 沒收到 A 發送來的確認報文,那么就會重新發送連接釋放請求報文,如果沒有TIME_WAIT,那么B重傳就無法到達A,連接可能無法斷開。
等待一段時間是為了讓本連接持續時間內所產生的所有報文都從網絡中消失,使得下一個新的連接不會出現舊的連接請求報文。
?
TCP的流量控制與滑動窗口
流量控制是為了控制發送方發送速率,保證接收方來得及接收。接收方發送的確認報文中的窗口字段可以用來控制發送方窗口大小,從而影響發送方的發送速率。將窗口字段設置為0,則發送方不能發送數據。
TCP滑動窗口是緩存的一部分,用來暫時存放字節流。發送方和接收方各有一個窗口,接收方通過 TCP 報文段中的窗口字段告訴發送方自己的窗口大小,發送方根據這個值和其它信息設置自己的窗口大小。接收窗口只會對窗口內最后一個按序到達的字節進行確認,例如接收窗口已經收到的字節為 {31, 34, 35},其中 {31}按序到達,而 {34, 35} 就不是,因此只對字節 31 進行確認。發送方得到一個字節的確認之后,就知道這個字節之前的所有字節都已經被接收
TCP使用累計確認(發送方一次發送多個連續包,接收方只需要確認最后一個包),快速重傳(收到3個冗余的ACK包立馬重傳,不用等待超時)以及選擇重傳(只對丟失的包進行重傳)提高效率
?
TCP的擁塞控制與擁塞窗口
擁塞控制:防止過多的數據注入到網絡中,這樣可以使網絡中的路由器或鏈路不致過載。擁塞控制所要做的都有一個前提:網絡能夠承受現有的網絡負荷。擁塞控制是一個全局性的過程,涉及到所有的主機、路由器,以及與降低網絡傳輸性能有關的所有因素。
發送方維持一個擁塞窗口 cwnd的狀態變量。擁塞窗口的大小取決于網絡的擁塞程度,并且動態地在變化。發送方讓自己的發送窗口等于擁塞。發送方控制擁塞窗口的原則是:只要網絡沒有出現擁塞,擁塞窗口就再增大一些,以便把更多的分組發送出去。但只要網絡出現擁塞,擁塞窗口就減小一些,以減少注入到網絡中的分組數。
幾種擁塞控制方法:慢開始、擁塞避免、快重傳和快恢復。
慢開始算法:當主機開始發送數據時,如果立即將大量數據字節注入到網絡,那么就有可能引起網絡擁塞,因為現在并不清楚網絡的負荷情況。因此,較好的方法是先探測一下,即由小到大逐漸增大發送窗口,也就是說,由小到大逐漸增大擁塞窗口數值。通常在剛剛開始發送報文段時,先把擁塞窗口 cwnd 設置為一個最大報文段MSS的數值。而在每收到一個對新的報文段的確認后,把擁塞窗口增加至多一個MSS的數值。用這樣的方法逐步增大發送方的擁塞窗口 cwnd ,可以使分組注入到網絡的速率更加合理。
慢開始門限ssthresh的用法如下:
??? 當 cwnd < ssthresh 時,使用上述的慢開始算法
??? 當 cwnd > ssthresh 時,停止使用慢開始算法而改用擁塞避免算法。
??? 當 cwnd = ssthresh 時,既可使用慢開始算法,也可使用擁塞控制避免算法。
擁塞避免算法:讓擁塞窗口cwnd緩慢地增大,即每經過一個往返時間RTT就把發送方的擁塞窗口cwnd加1,而不是加倍。這樣擁塞窗口cwnd按線性規律緩慢增長,比慢開始算法的擁塞窗口增長速率緩慢得多。
無論在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞(其根據就是沒有收到確認),就要把慢開始門限ssthresh設置為出現擁塞時的發送方窗口值的一半(但不能小于2)。然后把擁塞窗口cwnd重新設置為1,執行慢開始算法。這樣做的目的就是要迅速減少主機發送到網絡中的分組數,使得發生擁塞的路由器有足夠時間把隊列中積壓的分組處理完畢。
快速恢復算法:發送方認為網絡很可能沒有發生擁塞,因此與慢開始不同之處是現在不執行慢開始算法(即擁塞窗口cwnd現在不設置為1),而是把cwnd值設置為慢開始門限ssthresh減半后的數值,然后開始執行擁塞避免算法(“加法增大”),使擁塞窗口緩慢地線性增大。
?
TCP的拆包粘包
TCP粘包或拆包有原因:
1、要發送的數據大于TCP發送緩沖區剩余空間大小,將會發生拆包。
2、待發送數據大于MSS(最大報文長度),TCP在傳輸前將進行拆包。
3、要發送的數據小于TCP發送緩沖區的大小,TCP將多次寫入緩沖區的數據一次發送出去,將會發生粘包。
4、接收數據端的應用層沒有及時讀取接收緩沖區中的數據,將發生粘包。
解決辦法:
1、發送端給每個數據包添加包首部,首部中應該至少包含數據包的長度,這樣接收端在接收到數據后,通過讀取包首部的長度字段,便知道每一個數據包的實際長度了。
2、發送端將每個數據包封裝為固定長度(不夠的可以通過補0填充),這樣接收端每次從接收緩沖區中讀取固定長度的數據就自然而然的把每個數據包拆分開來。
3、可以在數據包之間設置邊界,如添加特殊符號,這樣,接收端通過這個邊界就可以將不同的數據包拆分開。
?
Socket編程
對于一個套接字上的輸入操作,第一步通常涉及等待數據從網絡中到達。當所等待數據到達時,它被復制到內核中的某個緩沖區。第二步就是把數據從內核緩沖區復制到應用進程緩沖區。
阻塞式 I/O(BIO)
應用進程被阻塞,直到數據從內核緩沖區復制到應用進程緩沖區中才返回。應該注意到,在阻塞的過程中,其它應用進程還可以執行,因此阻塞不意味著整個操作系統都被阻塞。因為其它應用進程還可以執行,所以不消耗 CPU 時間,這種模型的 CPU 利用率會比較高。
非阻塞式 I/O(NIO)
應用進程執行系統調用之后,如果kernel中的數據還沒有準備好,那么它并不會block用戶進程,而是立刻返回一個error。應用進程可以繼續執行,但是需要不斷的執行系統調用來獲知I/O 是否完成,這種方式稱為輪詢(polling),并且當內核數據準備好后,拷貝數據到用戶內存會是阻塞的。由于 CPU 要處理更多的系統調用,因此這種模型的 CPU 利用率比較低。
IO復用
也叫做事件驅動IO,select/epoll(實現IO復用的兩個函數)的好處就在于單個process就可以同時處理多個網絡連接的IO。它的基本原理就是select/epoll 函數會不斷的輪詢所負責的所有socket,當某個socket有數據到達了,就通知用戶進程。
異步 I/O(AIO)
應用進程執行 aio_read 系統調用會立即返回,應用進程可以繼續執行,不會被阻塞,內核會在所有操作完成之后向應用進程發送信號,沒有任何阻塞過程。
異步 I/O 與I/O 復用的區別在于,異步I/O不阻塞進程,而I/O復用會阻塞在調用函數階段。異步 I/O 的信號是通知應用進程 I/O 完成,而I/O 復用是通知應用進程可以開始 I/O。
并且I/O復用也是要輪詢查看數據是否就緒,而異步I/O則不需要。
AIO與NIO的區別在于:NIO雖然進程大部分時間都不會被block,但是它仍然要求進程去主動的check,并且當數據準備完成以后,也需要進程主動的再次調用recvfrom來將數據拷貝到用戶內存。而AIO則完全不同。它就像是用戶進程將整個IO操作交給了kernel完成,然后完成之后發信號通知。在此期間,用戶進程不需要去檢查IO操作的狀態,也不需要主動的去拷貝數據。
?
IO多路復用:select poll epoll
select,poll,epoll都是IO多路復用的機制。I/O多路復用就是通過一種機制,一個進程可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程序進行相應的讀寫操作。
Select將socket添加到select監視中,然后在while內一直調用select獲取被激活的socket,一旦socket可讀,便調用read函數將socket中的數據讀取出來。雖然上述方式允許單線程內處理多個IO請求,但是每個IO請求的過程還是阻塞的(在select函數上阻塞),平均時間甚至比同步阻塞IO模型還要長。如果用戶線程只注冊自己感興趣的socket或者IO請求,然后去做自己的事情,等到數據到來時再進行處理,則可以提高CPU的利用率。IO多路復用模型使用了Reactor設計模式實現了這一機制。
select目前幾乎在所有的平臺上支持,其良好跨平臺支持也是它的一個優點。select的一個缺點在于單個進程能夠監視的文件描述符的數量存在最大限制,在Linux上一般為1024,可以通過修改宏定義甚至重新編譯內核的方式提升這一限制,但是這樣也會造成效率的降低。
pollfd結構包含了要監視的event和發生的event,不再使用select“參數-值”傳遞的方式。同時,pollfd并沒有最大數量限制(但是數量過大后性能也是會下降)。 和select函數一樣,poll返回后,需要輪詢pollfd來獲取就緒的描述符。
從上面看,select和poll都需要在返回后,通過遍歷文件描述符來獲取已經就緒的socket。事實上,同時連接的大量客戶端在一時刻可能只有很少的處于就緒狀態,因此隨著監視的描述符數量的增長,其效率也會線性下降。
epoll是在2.6內核中提出的,是之前的select和poll的增強版本。相對于select和poll來說,epoll更加靈活,沒有描述符限制。epoll使用一個文件描述符管理多個描述符,將用戶關系的文件描述符的事件存放到內核的一個事件表中,這樣在用戶空間和內核空間的copy只需一次。
epoll對文件描述符的操作有兩種模式:LT(level trigger)和ET(edge trigger)。LT模式是默認模式,LT模式與ET模式的區別如下:
LT模式:當epoll_wait檢測到描述符事件發生并將此事件通知應用程序,應用程序可以不立即處理該事件。下次調用epoll_wait時,會再次響應應用程序并通知此事件。
ET模式:當epoll_wait檢測到描述符事件發生并將此事件通知應用程序,應用程序必須立即處理該事件。如果不處理,下次調用epoll_wait時,不會再次響應應用程序并通知此事件。
在 select/poll中,進程只有在調用一定的方法后,內核才對所有監視的文件描述符進行掃描,而epoll事先通過epoll_ctl()來注冊一個文件描述符,一旦基于某個文件描述符就緒時,內核會采用類似callback的回調機制,迅速激活這個文件描述符,當進程調用epoll_wait() 時便得到通知(此處去掉了遍歷文件描述符,而是通過監聽回調的機制。這正是epoll的魅力所在)
epoll的優點主要是一下幾個方面:
- 監視的描述符數量不受限制,它所支持的FD上限是最大可以打開文件的數目,這個數字一般遠大于2048,舉個例子,在1GB內存的機器上大約是10萬左右,具體數目可以cat /proc/sys/fs/file-max察看,一般來說這個數目和系統內存關系很大。select的最大缺點就是進程打開的fd是有數量限制的。這對于連接數量比較大的服務器來說根本不能滿足。雖然也可以選擇多進程的解決方案( Apache就是這樣實現的),不過雖然linux上面創建進程的代價比較小,但仍舊是不可忽視的,加上進程間數據同步遠比不上線程間同步的高效,所以也不是一種完美的方案。
- IO的效率不會隨著監視fd的數量的增長而下降。epoll不同于select和poll輪詢的方式,而是通過每個fd定義的回調函數來實現的。只有就緒的fd才會執行回調函數。
緩存
?
強緩存與協商緩存
瀏覽器HTTP緩存可以分為強緩存和協商緩存。強緩存和協商緩存最大也是最根本的區別是:強緩存命中的話不會發請求到服務器(比如chrome中的200 from memory cache),協商緩存一定會發請求到服務器,通過資源的請求首部字段驗證資源是否命中協商緩存,如果協商緩存命中,服務器會將這個請求返回,但是不會返回這個資源的實體,而是通知客戶端可以從緩存中加載這個資源(304 not modified)。
控制強緩存的字段按優先級介紹
- Pragma ???????Pragma是HTTP/1.1之前版本遺留的通用首部字段,僅作為于HTTP/1.0的向后兼容而使用。雖然它是一個通用首部,但是它在響應報文中時的行為沒有規范,依賴于瀏覽器的實現。RFC中該字段只有no-cache一個可選值,會通知瀏覽器不直接使用緩存,要求向服務器發請求校驗新鮮度。因為它優先級最高,當存在時一定不會命中強緩存。
- Cache-Control ???????Cache-Control是一個通用首部字段,也是HTTP/1.1控制瀏覽器緩存的主流字段。和瀏覽器緩存相關的是如下幾個響應指令:
指令 | 參數 | 說明 |
private | 無 | 表明響應只能被單個用戶緩存,不能作為共享緩存(即代理服務器不能緩存它) |
public | 可省略 | 表明響應可以被任何對象(包括:發送請求的客戶端,代理服務器,等等)緩存 |
no-cache | 可省略 | 緩存前必需確認其有效性 |
no-store | 無 | 不緩存請求或響應的任何內容 |
max-age=[s] | 必需 | 響應的最大值 |
- max-age(單位為s)設置緩存的存在時間,相對于發送請求的時間。只有響應報文首部設置Cache-Control為非0的max-age或者設置了大于請求日期的Expires(下文會講)才有可能命中強緩存。當滿足這個條件,同時響應報文首部中Cache-Control不存在no-cache、no-store且請求報文首部不存在Pragma字段,才會真正命中強緩存。
- no-cache? 表示請求必須先與服務器確認緩存的有效性,如果有效才能使用緩存(協商緩存),無論是響應報文首部還是請求報文首部出現這個字段均一定不會命中強緩存。Chrome硬性重新加載(Command+shift+R)會在請求的首部加上Pragma:no-cache和Cache-Control:no-cache。
- no-store? 表示禁止瀏覽器以及所有中間緩存存儲任何版本的返回響應,一定不會出現強緩存和協商緩存,適合個人隱私數據或者經濟類數據。
- public 表明響應可以被瀏覽器、CDN等等緩存。
- private 響應只作為私有的緩存,不能被CDN等緩存。如果要求HTTP認證,響應會自動設置為private。
- Expires ???????Expires是一個響應首部字段,它指定了一個日期/時間,在這個時間/日期之前,HTTP緩存被認為是有效的。無效的日期比如0,表示這個資源已經過期了。如果同時設置了Cache-Control響應首部字段的max-age,則Expires會被忽略。它也是HTTP/1.1之前版本遺留的通用首部字段,僅作為于HTTP/1.0的向后兼容而使用。
?
冪等性
(并非是HTTP的問題,而是服務器API設計問題)
冪等性是http層面的問題嗎,還是服務器要處理和解決的內容?
?
對HTTP協議的使用實際上存在著兩種不同的方式:一種是RESTful的,它把HTTP當成應用層協議,比較忠實地遵守了HTTP協議的各種規定;另一種是SOA的,它并沒有完全把HTTP當成應用層協議,而是把HTTP協議作為了傳輸層協議,然后在HTTP之上建立了自己的應用層協議。這里所討論的HTTP冪等性主要針對RESTful風格的,但冪等性并不屬于特定的協議,它是分布式系統的一種特性;所以,不論是SOA還是RESTful的Web API設計都應該考慮冪等性。下面將介紹HTTP GET、DELETE、PUT、POST四種主要方法的語義和冪等性。
?
HTTP GET方法用于獲取資源,不應有副作用,所以是冪等的。
比如:GET http://www.bank.com/account/123456,不會改變資源的狀態,不論調用一次還是N次都沒有副作用。請注意,這里強調的是一次和N次具有相同的副作用,而不是每次GET的結果相同。GET http://www.news.com/latest-news這個HTTP請求可能會每次得到不同的結果,但它本身并沒有產生任何副作用,因而是滿足冪等性的。
?
HTTP DELETE方法用于刪除資源,有副作用,但它應該滿足冪等性。
比如:DELETE http://www.forum.com/article/4231,調用一次和N次對系統產生的副作用是相同的,即刪掉id為4231的帖子;因此,調用者可以多次調用或刷新頁面而不必擔心引起錯誤。
?
比較容易混淆的是HTTP POST和PUT。POST和PUT的區別容易被簡單地誤認為“POST表示創建資源,PUT表示更新資源”;而實際上,二者均可用于創建資源,更為本質的差別是在冪等性方面。在HTTP規范中對POST和PUT是這樣定義的:POST所對應的URI并非創建的資源本身,而是資源的接收者。比如:POST http://www.forum.com/articles的語義是在http://www.forum.com/articles下創建一篇帖子,HTTP響應中應包含帖子的創建狀態以及帖子的URI。兩次相同的POST請求會在服務器端創建兩份資源,它們具有不同的URI;所以,POST方法不具備冪等性。而PUT所對應的URI是要創建或更新的資源本身。比如:PUT http://www.forum/articles/4231的語義是創建或更新ID為4231的帖子。對同一URI進行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有冪等性。
?
長輪詢與短輪詢
短輪詢相信大家都不難理解,比如你現在要做一個電商中商品詳情的頁面,這個詳情界面中有一個字段是庫存量(相信這個大家都不陌生,隨便打開淘寶或者京東都能找到這種頁面)。而這個庫存量需要實時的變化,保持和服務器里實際的庫存一致。
?
這個時候,你會怎么做?
?
最簡單的一種方式,就是你用JS寫個死循環,不停的去請求服務器中的庫存量是多少,然后刷新到這個頁面當中,這其實就是所謂的短輪詢。
?
這種方式有明顯的壞處,那就是你很浪費服務器和客戶端的資源。客戶端還好點,現在PC機配置高了,你不停的請求還不至于把用戶的電腦整死,但是服務器就很蛋疼了。如果有1000個人停留在某個商品詳情頁面,那就是說會有1000個客戶端不停的去請求服務器獲取庫存量,這顯然是不合理的。
?
那怎么辦呢?
?
長輪詢這個時候就出現了,其實長輪詢和短輪詢最大的區別是,短輪詢去服務端查詢的時候,不管庫存量有沒有變化,服務器就立即返回結果了。而長輪詢則不是,在長輪詢中,服務器如果檢測到庫存量沒有變化的話,將會把當前請求掛起一段時間(這個時間也叫作超時時間,一般是幾十秒,Object.wait)。在這個時間里,服務器會去檢測庫存量有沒有變化,檢測到變化就立即返回(Object.notify),否則就一直等到超時為止。
?
而對于客戶端來說,不管是長輪詢還是短輪詢,客戶端的動作都是一樣的,就是不停的去請求,不同的是服務端,短輪詢情況下服務端每次請求不管有沒有變化都會立即返回結果,而長輪詢情況下,如果有變化才會立即返回結果,而沒有變化的話,則不會再立即給客戶端返回結果,直到超時為止。
這樣一來,客戶端的請求次數將會大量減少(這也就意味著節省了網絡流量,畢竟每次發請求,都會占用客戶端的上傳流量和服務端的下載流量),而且也解決了服務端一直疲于接受請求的窘境。
?
但是長輪詢也是有壞處的,因為把請求掛起同樣會導致資源的浪費,假設還是1000個人停留在某個商品詳情頁面,那就很有可能服務器這邊掛著1000個線程,在不停檢測庫存量,這依然是有問題的。
?
因此,從這里可以看出,不管是長輪詢還是短輪詢,都不太適用于客戶端數量太多的情況,因為每個服務器所能承載的TCP連接數是有上限的,這種輪詢很容易把連接數頂滿。
長連接與短連接
HTTP的短連接和長連接;長連接與短連接的區別(LVS是通過長連接作負載均衡)
HTTP的長連接和短連接本質上是TCP長連接和短連接。
在HTTP/1.0中,默認使用的是短連接。也就是說,瀏覽器和服務器每進行一次HTTP操作,就建立一次連接,但任務結束就中斷連接。
?
但從 HTTP/1.1起,默認使用長連接,用以保持連接特性。使用長連接的HTTP協議,會在響應頭有加入這行代碼:Connection:keep-alive。
在使用長連接的情況下,當一個網頁打開完成后,客戶端和服務器之間用于傳輸HTTP數據的 TCP連接不會關閉,如果客戶端再次訪問這個服務器上的網頁,會繼續使用這一條已經建立的連接。Keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的服務器軟件(如Apache)中設定這個時間。實現長連接要客戶端和服務端都支持長連接。
?
長連接可以省去較多的TCP建立和關閉的操作,減少浪費,節約時間。對于頻繁請求資源的客戶來說,較適用長連接。不過這里存在一個問題,存活功能的探測周期太長,還有就是它只是探測TCP連接的存活,屬于比較斯文的做法,遇到惡意的連接時,保活功能就不夠使了。在長連接的應用場景下,client端一般不會主動關閉它們之間的連接,Client與server之間的連接如果一直不關閉的話,會存在一個問題,隨著客戶端連接越來越多,server早晚有扛不住的時候,這時候server端需要采取一些策略,如關閉一些長時間沒有讀寫事件發生的連接,這樣可以避免一些惡意連接導致server端服務受損。
?
短連接對于服務器來說管理較為簡單,存在的連接都是有用的連接,不需要額外的控制手段。但如果客戶請求頻繁,將在TCP的建立和關閉操作上浪費時間和帶寬。
?
URL
url有最大長度限制,就問長度有限制是get的原因還是url的原因,為什么長度會有限制,是http數據包的頭的字段原因還是內容字段的原因
是GET的原因,長度受到服務器和客戶端的限制。
URL編解碼
Url的編碼格式采用的是ASCII碼,而不是Unicode,這也就是說你不能在Url中包含任何非ASCII字符,例如中文。
Url中只允許包含英文字母(a-zA-Z)、數字(0-9)、-_.~4個特殊字符以及所有保留字符;
RFC3986中指定了以下字符為保留字符:! * ' ( ) ; : @ & = + $ , / ? # [ ]
?
Url編碼通常也被稱為百分號編碼(Url Encoding,also known as percent-encoding),是因為它的編碼方式非常簡單,使用%百分號加上兩位的十六進制字符。
URI&URL
URL(Uniform ResourceLocator)統一資源定位符,是專門為標識網絡上的資源位置而設計的一種編址方式。URL一般由3個部分組成:
應用層協議
主機IP地址或域名
資源所在路徑/文件名
?
統一資源標識符(Uniform Resource Identifier,或URI)是一個用于標識某一互聯網資源名稱的字符串。
URI :Uniform Resource Identifier,統一資源標識符;
URL:Uniform Resource Locator,統一資源定位符;
URN:Uniform ResourceName,統一資源名稱。
其中,URL,URN是URI的子集。
URL是一種具體的URI,它不僅唯一標識資源,而且還提供了定位該資源的信息。URI是一種語義上的抽象概念,可以是絕對的,也可以是相對的,而URL則必須提供足夠的信息來定位。
?
服務器保證公鑰正確性——數字證書
公鑰是由數字證書認證機構(CA,Certificate Authority)和其相關機關頒發的公開密鑰證書。
數字證書認證機構處于客戶端與服務器雙方都可信賴的第三方機構的立場上。服務器會將這份由數字證書認證機構頒發的公鑰證書發送給客戶端,以進行公開密鑰加密方式通信。公鑰證書也可叫做數字證書或直接稱為證書。
接到證書的客戶端可使用數字證書認證機構的公開密鑰,對那張證書上的數字簽名進行驗證,一旦驗證通過,客戶端便可明確兩件事:
認證服務器的公開密鑰的是真實有效的數字證書認證機構
服務器的公開密鑰是值得信賴的
此處認證機關的公開密鑰必須安全地轉交給客戶端。使用通信方式時,如何安全轉交是一件很困難的事,因此,多數瀏覽器開發商發布版本時,會事先在內部植入常用認證機關的公開密鑰。
過程
·? 客戶端發起HTTPS請求 這個沒什么好說的,就是用戶在瀏覽器里輸入一個HTTPS網址,然后連接到服務端的443端口。
·? 服務端的配置 采用HTTPS協議的服務器必須要有一套數字證書,可以自己制作,也可以向組織申請。區別就是自己頒發的證書需要客戶端驗證通過,才可以繼續訪問,而使用受信任的公司申請的證書則不會彈出提示頁面。這套證書其實就是一對公鑰和私鑰。
·? 傳送證書 這個證書其實就是公鑰,只是包含了很多信息,如證書的頒發機構,過期時間等等。
·? 客戶端解析證書 這部分工作是由客戶端的SSL/TLS來完成的,首先會驗證公鑰是否有效,比如頒發機構,過期時間等等,如果發現異常,則會彈出一個警示框,提示證書存在的問題。如果證書沒有問題,那么就生成一個隨機值。然后用證書(也就是公鑰)對這個隨機值進行加密。
·? 傳送加密信息 這部分傳送的是用證書加密后的隨機值,目的是讓服務端得到這個隨機值,以后客戶端和服務端的通信就可以通過這個隨機值來進行加密解密了。
·? 服務端解密信息 服務端用私鑰解密后,得到了客戶端傳過來的隨機值,然后把內容通過該隨機值(密鑰)進行對稱加密,將信息和私鑰通過某種算法混合在一起,這樣除非知道私鑰,不然無法獲取內容,而正好客戶端和服務端都知道這個私鑰,所以只要加密算法夠復雜,私鑰夠復雜,數據就夠安全。
·? 傳輸加密后的信息 這部分信息就是服務端用私鑰加密后的信息,可以在客戶端用隨機值解密還原。
·? 客戶端解密信息 客戶端用之前生產的私鑰解密服務端傳過來的信息,于是獲取了解密后的內容。整個過程第三方即使監聽到了數據,也束手無策。
客戶端獲得服務器的公鑰的過程是基于非對稱加密實現的(數字證書)
而之后客戶端和服務器之間的數據交換是基于對稱加密實現的。
更具體的過程
·? 客戶端通過發送 Client Hello 報文開始 SSL 通信。報文中包含客戶端支持的 SSL 的指定版本、加密組件(Cipher Suite)列表(所使用的加密算法及密鑰長度等)
·? 服務器可進行 SSL 通信時,會以 Server Hello 報文作為應答。和客戶端一樣,在報文中包含 SSL 版本以及加密組件。服務器的加密組件內容是從接收 到的客戶端加密組件內篩選出來的。
·? 之后服務器發送 Certificate 報文。報文中包含公開密鑰證書。
·? 最后服務器發送 Server Hello Done 報文通知客戶端,最初階段的 SSL 握手協商部分結束。
·? SSL 第一次握手結束之后,客戶端以 Client Key Exchange 報文作為回應。報文中包含通信加密中使用的一種被稱為 Pre-master secret 的隨機密碼串。該 報文已用步驟 3 中的公開密鑰進行加密。
·? 接著客戶端繼續發送 Change Cipher Spec 報文。該報文會提示服務器,在此報文之后的通信會采用 Pre-master secret 密鑰加密。
·? 客戶端發送 Finished 報文。該報文包含連接至今全部報文的整體校驗值。這次握手協商是否能夠成功,要以服務器是否能夠正確解密該報文作為判定標準。
·? 服務器同樣發送 Change Cipher Spec 報文。
·? 服務器同樣發送 Finished 報文。
·? 服務器和客戶端的 Finished 報文交換完畢之后,SSL 連接就算建立完成。當然,通信會受到 SSL 的保護。從此處開始進行應用層協議的通信,即發 送 HTTP 請求。
·? 應用層協議通信,即發送 HTTP 響應。
·? 最后由客戶端斷開連接。斷開連接時,發送 close_notify 報文。
?
SOA
Web Service也叫XML Web Service WebService是一種可以接收從Internet或者Intranet上的其它系統中傳遞過來的請求,輕量級的獨立的通訊技術。是通過SOAP在Web上提供的軟件服務,使用WSDL文件進行說明,并通過UDDI進行注冊。
SOA是一種架構風格,包括兩個方面的內容:
1)抽象出服務,這些服務滿足離散、松耦合、可復用、自治、無狀態等特征;
2)服務可以靈活地組裝和編排,滿足流程整合和業務變化的需要
?
WebService是SOA的一種實現技術,跨語言,跨平臺,提供了標準的服務定義、服務注冊、服務接入和訪問的方式。使用了XML、SOAP、WSDL、UDDI等技術。
SOA三角操作模型
1)三種角色
服務提供者:發布自己的服務,并且對服務請求進行響應
服務請求者:利用服務注冊中心查找所需要的服務,然后使用該服務
服務注冊中心:注冊已經發布的服務,對其進行分類,并提供搜索服務
2)三個操作:
發布:為了使服務可訪問,需要發布服務描述以使服務使用者可以發現它
查找:服務請求者查詢服務注冊中心來找到滿足其要求的服務
綁定:檢索到服務描述后,服務請求者繼續根據服務描述中的信息調用服務
XML
XML:(Extensible Markup Language)擴展型可標記語言。面向短期的臨時數據處理、面向萬維網絡,是Soap的基礎。
?
SOAP
SOAP:(Simple Object Access Protocol)簡單對象傳輸協議。是XML Web Service 的通信協議。當用戶通過UDDI找到你的WSDL描述文檔后,他通過可以SOAP調用你建立的Web服務中的一個或多個操作。SOAP是XML文檔形式的調用方法的規范,它可以支持不同的底層接口,像HTTP(S)或者SMTP。
?
SOAP=RPC+HTTP+XML:采用HTTP作為底層通訊協議;RPC作為一致性的調用途徑,XML作為數據傳送的格式,允許服務提供者和服務客戶經過防火墻在INTERNET進行通訊交互。
?
簡單對象傳輸協議,是輕量級的、簡單的、基于XML的用于交換數據的協議。
SOAP本質上是一個 XML文檔,包含以下元素:
1)Envelope元素:必需元素,根元素,標識此XML文檔為一條SOAP消息
可以包含命名空間和聲明額外的屬性
2)Header元素:可選元素,有關SOAP消息的應用程序專用消息
3)Body元素:必需元素,包含所有的請求和響應信息
4)Fault元素:可選元素,提供有關在處理此消息所發生錯誤的信息
?
SOAP處理模型:
1)用XML打包請求
2)將請求發送給服務器
3)服務器接收到請求,解碼XML,處理請求,以XML格式返回響應
?
SOAP并不假定傳輸數據的下層協議,因此必須設計為能在各種協議上運行。即使絕大多數SOAP是運行在HTTP上,使用URI標識服務,SOAP也僅僅使用POST方法發送請求,用一個唯一的URI標識服務的入口。
?
使用 HTTP 協議的 SOAP,由于其設計原則上并不像 REST 那樣強調與 Web 的工作方式相一致,所以,基于 SOAP 應用很難充分發揮 HTTP 本身的緩存能力。
HTTP是其通信協議/傳輸協議,SOAP是其應用協議
?
?
WSDL
WSDL:(Web Services Description Language) WSDL 文件是一個 XML 文檔,用于說明一組 SOAP 消息以及如何交換這些消息。大多數情況下由軟件自動生成和使用。
網絡服務描述語言,是基于XML的,用于描述網絡服務、服務定位和服務提供的操作的協議。
?
UDDI
UDDI (Universal Description, Discovery, and Integration) 是一個主要針對Web服務供應商和使用者的新項目。在用戶能夠調用Web服務之前,必須確定這個服務內包含哪些商務方法,找到被調用的接口定義,還要在服務端來編制軟件,UDDI是一種根據描述文檔來引導系統查找相應服務的機制。UDDI利用SOAP消息機制(標準的XML/HTTP)來發布,編輯,瀏覽以及查找注冊信息。它采用XML格式來封裝各種不同類型的數據,并且發送到注冊中心或者由注冊中心來返回需要的數據。
?
統一描述、發現、集成協議,提供基于網絡服務的注冊和發現機制