HTTP與私有二進制協議之間的區別


簡單的文本協議、二進制協議

 
  寫網絡程序躲不過協議,協議其實就是定義了消息的格式,以及消息是如何交換的。協議可簡單可復雜,復雜精密如TCP協議,簡單奔放如HTTP的協議。這里將我所接觸到的協議稍微總結一下,最后拋出一個個人設計的簡單通用的文本協議。
  設計一個協議不是一件很容易的事情,尤其是當對設計的要求包含很好的描述性和可擴展性的時候。如果再將效率考慮在內,則更是件耗腦力的活。在繼續討論下去之前,先看看現有的一些協議吧。這里主要討論的是應用層的協議,應用層的協議大多是請求響應模式(除了zeromq這個變態的家伙,后面再說),所以這里側重討論消息格式。
 
HTTP協議
  這可能是大家接觸得最多的協議了,HTTP協議是一個比較簡單的基於文本的協議。消息格式基於文本,換行分隔鍵值串,鍵和值用冒號分隔,同時定義了一些標准的鍵和值。這個協議描述性教強——人類可讀。擴展性強——加自定義的頭很容易,也幾乎不會有副作用(除了消息體積增加一點點)。但是,缺點就是標准定義的東西太多了,細節太多。解析較復雜。
 
memcached協議
  memcached有兩種協議,文本協議和二進制協議,文本協議以換行表示一個請求結束。請求內部參數以空格分隔。為了二進制安全,在二進制數據前要加上長度這個參數,如set x 3 abc\r\n。
文本協議固然簡單,可是當請求很小的時候,過多的協議本身的數據則顯得浪費(比如每個HTTP請求只發送一個字母,可HTTP頭可能有上百的字符,太浪費了),而且,server在接收到請求之后還要做文本解析,也耗cpu,於是memcached又推出了二進制協議,為了錦上添花,是的memcached更加高效。二進制協議的優點就是高效,因為所有信息都以最少的數據量來表達,且server解析請求時做的是數學比較而不是字符串比較,效率高很多。
  memcached的協議比起HTTP來就輕得多了(當然,兩者所面向的場景不一樣,故這個比較沒太大意義)。但是,也有缺點,就是擴展性較差,協議定得比較死,哪個位置上有哪些東西,是什么意義是定死的。所以,直接哪來用在不同的場景下不大現實。
 
redis協議
  redis的協議也是文本協議,但是設計得比較小心和通用(我后面自己定義的協議深受其影響),在保證描述性的同時盡量減少協議本身的數據量,比如,在memcached的文本協議中,錯誤用“ERROR\r\n”來表示,而redis使用“-”來表示,用“:”開頭的行表示整數等等。這樣的設計結合了文本協議的簡單和一部分二進制協議的高效。用在redis這個場合,很是適合。交換方式同樣是請求響應。redis協議有一個缺點,就是,一個消息有多少參數是需要在開頭指定的。不像HTTP協議用空行來表示結束。這就帶來一個缺點,不好流水操作,也就是說消息必須在發送第一個字節之前被完全確定,因為第一個東西就是參數個數:-(。
上面討論的基本都是文本協議,當然還有很多采用二進制協議的服務,如gearman、 mysql等,二進制協議就相當於壓縮版的文本協議,提高了傳輸效率,但是降低了描述性和靈活性(萬一那個位置預留的位數不夠就囧了)。
  總的來說,這就是一個平衡的過程。如果消息體不是很小(比如每次只傳一個字節的消息就很小了),那么采用文本協議還是值得的。畢竟文本協議簡單,好擴展,利於調試(telnet就可以當客戶端用),雖說消息是讓計算機讀的,但有時候也要人去看。所以,能用文本還是用文本吧。
 
簡單文本協議
  最后我定義了一個簡單的基於文本的協議,叫做simpletp(Simple Text based Protocol),詳細定義在這里http://simpletp.org,這個協議是為了簡單的RPC而設計,結合了HTTP協議的靈活(以空行結束),redis協議的輕量(size+data)。但為了簡單通用,沒有采用redis的單字符表示類型的設計,因為這樣就會引入額外的復雜性,如表示整數用“:”,那么浮點數、復數等等怎么辦,干脆什么類型都沒有,就簡單的傳輸size+data串(有點類似zeromq,但是比zeromq做的事情少),而具體的類型則交由其他機制去處理,如protocol buffer。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM