http上傳文件深度解析-高性能http傳輸

    最近在做web服務器的時候將一些應用集成在了服務器裏面,比如說文件上傳,結果調試用了一個星期的時間,搞得自己頭昏腦漲,現在總於解決了,現將注意細節敘述如下:
   http上傳協議很簡單,用post協議,協議頭部包含Content-Length項,這是一次上傳的所有body部分長度總和,包括多文件之間的分割等等,所以也就難怪了,http上傳要比ftp等慢,其實慢就慢在body解析上,下面對於文件分割作一些闡述。
一個典型的http上傳協議頭類似於這樣:

   POST /public/upload.action HTTP/1.1
     ost: maiit.com:8088
     User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9b5) Gecko/2008041514                  Firefox/3.0b5
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    ccept-Encoding: gzip,deflate
    ccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive
    Referer: http://maiit.com:8088/public/up.html
    Content-Type: multipart/form-data;      boundary=---------------------------88739631214394723612117964652
    Content-Length: 3433
其中,boundary是文件分割符號,每個文件以如下字段開頭
      
     -----------------------------88739631214394723612117964652
     Content-Disposition: form-data; name="file"; filename="hashtables.h"
     Content-Type: text/x-chdr
以如下字段結尾:
      
     -----------------------------88739631214394723612117964652
    Content-Disposition: form-data; name="uploadButton"

    up
    -----------------------------88739631214394723612117964652--

其中並沒有包含單個文件的長度,這就是對於傳輸大文件性能不高的關鍵所在,因爲應用服務器必須對每次的數據進行比對,查找文件分割符號,加入傳輸一個100M的文件,服務器端cpu必須對這100M的文件每一個字節進行字符串比對,那麼有沒有解決辦法呢?
     web服務器一般只將請求的數據直接轉發給應用層,不做任何處理(除了HTTP協議頭),假設你可以直接控制web服務器,類似於我現在的狀況,就有了解決辦法,比如我的服務器模型是epoll事件驅動,通過分析發現,對於flash等上傳途徑flash已經做了優化,數據並不是一股腦地發送過來,而是先發送協議頭部,然後發送一個文件分割符部分數據,在然後纔是正文,正文最後一個數據包不管是否等於socketBuffer,結尾標識有可能會下次發送,這樣一個過程就給了我們一個解決途徑,幾乎不用分析(除了文件名稱)任何一個文件數據包就能完成地保存下來文件,因爲數據是分段發送的,並沒有粘滯在一起,通過比對發送次數就可以確定,http協議頭的第一個數據包肯定是單獨發送的,然後纔會轉向文件處理程序,然後接收第2個數據包,並且flash上傳文件不管是多文件還是單文件其實都是按照單個文件分次上傳的,這樣傳送過程就可控了。
   注意上面的“有可能”幾個字,這幾天困擾我的也在於此,flash並不是想象中的穩定的,不同版本之間是不一樣的,linux上和windows上的解析也是不一樣的,這樣就不能給我們一個統一的解決途徑,我也是在測試中才發現這樣的問題的,不僅僅如此,flash的很多特性as3和as2根本不兼容,一個不向下兼容的軟件這樣流行真是讓人費解,並且上述的解決途徑不不適合傳送的頁面http上傳,頁面上傳基本上就是直接混合在一起的,所以這個最高效的解決途徑看來要放棄了,幾天的測試改進發現還還是有解決辦法的,於是就有了下面的處理模式。
   既然對於沒個文件都是有一個開頭標識和結尾標識,那不防在這上面做作文章,如果能只分析開頭和結尾而不分析中間數據,那麼對於大型文件http傳送將是一件幸事,開頭倒是好分析,對沒個數據包分析知道有文件開頭爲止,問題就在於結尾,不知道文件長度的情況下你怎麼知道何時分析一個數據包是否包含結尾?幸好有這樣一個共同特性,對於單個文件傳送,最後一個包含結尾的數據包在總length傳送=0的時候總是完整地發送地(不會有一部分放在前一個socket交互另一個放在後一個,估計這是瀏覽器在發送沒個文件的時候後面不會主動將文本附加在最後一個數據包),所以當總length小於SocketBuffer得時候就是分析文件結尾的時候,這樣我們最總最多分析2次開頭,2次結尾,我在緩存設爲16K的時候局域網就可以達到3M的上傳速度,最大64k緩存(剛好等於socket最大緩存)的時候能大到9M/秒的上傳速度,幾乎等於UDP的速度,對於大型文件的優勢可想而知。

    這裏依然存在的問題是之支持flash多文件上傳和http單文件上傳,當然,如果你是一個視頻上傳等程序這足夠用了,這裏拋磚引玉,望高手共同探討
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章