thttpd增加gzip壓縮響應報文體功能,以減少傳輸資料量

來源:互聯網
上載者:User

標籤:

thttpd

thttpd是一個非常小巧的輕量級web server,它非常非常簡單,僅僅提供了HTTP/1.1和簡單的CGI支援,在其官方網站上有一個與其他web server(如Apache, Zeus等)的對比圖+Benchmark,可以參考參考。此外,thttpd 也類似於lighttpd,對於並發請求不使用fork()來派生子進程處理,而是採用多工(Multiplex)技術來實現。因此效能很好。

thttpd 支援多種平台,如FreeBSD, SunOS, Solaris, BSD, Linux, OSF等。對於小型web server而言,速度快似乎是一個代名詞,通過官方站提供的Benchmark,可以這樣認為:thttpd至少和主流的web server一樣快,在高負載下更快,因為其資源佔用小的緣故。

thttpd還有一個較為令人信服的特點:基於URL的檔案流量限制,這對於下載的流量控制而言是非常方便的。象Apache就必須使用外掛程式實現,效率較thttpd低。

安裝調試,見:

http://blog.csdn.net/21aspnet/article/details/7045845

http://blog.csdn.net/orzlzro/article/details/7568338

HTTP協議壓縮

對響應報文體進行壓縮,可以減少報文傳輸的資料量, 以提高頁面響應速度。特別是對當今web應用豐富的情況下, 頁面形成了很大的指令碼, 則效果明顯。

 

壓縮伺服器端和用戶端使用同一種壓縮演算法。HTTP協議對壓縮演算法有什麼規定? 是怎麼協商壓縮演算法的?

 

如下描述:

1、 HTTP支援的壓縮演算法包括 gzip compress deflate identity(不壓縮)

2、 HTTP協議規定, 用戶端發起的請求中使用accept-encoding報文頭,告知伺服器端, 用戶端可以接受哪幾種壓縮演算法, 伺服器端分析此頭域值, 知道其支援解壓的演算法, 如果演算法伺服器端也支援, 則伺服器端對響應報文體, 進行壓縮, 將壓縮後的內容, 作為報文體傳給用戶端,報文頭中要包括content-encoding,其值指明壓縮使用的演算法。 注意content-length這時候, 就是壓縮後的內容長度。

 

如報文頭,accept-encoding 和 content-encoding:

 

http://www.w3.org/Protocols/rfc2616/rfc2616.txt

Content coding values indicate an encoding transformation that has   been or can be applied to an entity. Content codings are primarily   used to allow a document to be compressed or otherwise usefully   transformed without losing the identity of its underlying media type   and without loss of information. Frequently, the entity is stored in   coded form, transmitted directly, and only decoded by the recipient.       content-coding   = token   All content-coding values are case-insensitive. HTTP/1.1 uses   content-coding values in the Accept-Encoding (section 14.3) and   Content-Encoding (section 14.11) header fields. Although the value   describes the content-coding, what is more important is that it   indicates what decoding mechanism will be required to remove the   encoding.   The Internet Assigned Numbers Authority (IANA) acts as a registry for   content-coding value tokens. Initially, the registry contains the   following tokens:   gzip An encoding format produced by the file compression program        "gzip" (GNU zip) as described in RFC 1952 [25]. This format is a        Lempel-Ziv coding (LZ77) with a 32 bit CRC.   compress        The encoding format produced by the common UNIX file compression        program "compress". This format is an adaptive Lempel-Ziv-Welch        coding (LZW).        Use of program names for the identification of encoding formats        is not desirable and is discouraged for future encodings. Their        use here is representative of historical practice, not good        design. For compatibility with previous implementations of HTTP,        applications SHOULD consider "x-gzip" and "x-compress" to be        equivalent to "gzip" and "compress" respectively.   deflate        The "zlib" format defined in RFC 1950 [31] in combination with        the "deflate" compression mechanism described in RFC 1951 [29].   identity        The default (identity) encoding; the use of no transformation        whatsoever. This content-coding is used only in the Accept-        Encoding header, and SHOULD NOT be used in the Content-Encoding        header.   New content-coding value tokens SHOULD be registered; to allow   interoperability between clients and servers, specifications of the   content coding algorithms needed to implement a new value SHOULD be   publicly available and adequate for independent implementation, and   conform to the purpose of content coding defined in this section.
gzip壓縮公用程式

http://www.gzip.org/

gzip工具的網站上指出:

Can I adapt the gzip sources to perform in-memory compression?

Use the zlib data compression library instead.

zlib

http://www.zlib.net/

https://github.com/madler/zlib

主要的壓縮函數 http://www.zlib.net/manual.html#Basic:

ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush.

 

通用封裝的壓縮函數, compress compress2, 這兩方法,不會產生gzip格式頭:

使用方法參考: http://blog.csdn.net/turingo/article/details/8148264

 

產生gzip格式頭的壓縮函數,  gzcompress gzdecompress   參考:

http://www.oschina.net/code/snippet_65636_22542

gzcompress 是我們今天無需要使用的函數, 伺服器端壓縮, 報文體。

 

修改要點

對file_address內容進行壓縮, 壓縮儲存記憶體開闢以compressBound計算大小,儲存地址為file_address_gz,

gzcompress 執行壓縮行為, 儲存在file_address_gz中,

同時修改, send_mime調用的 len。

 


#include <zlib.h> 
#include <zconf.h> 

 

static int
really_start_request( httpd_conn* hc, struct timeval* nowP ) 。。。

   else
    {
    hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP );
    if ( hc->file_address == (char*) 0 )
        {
        httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl );
        return -1;
        }

    /* 計算壓縮結果*/
        uLong blen = 0; 
printf("enter file address %s!\n", hc->file_address); 
        /* 計算緩衝區大小,並為其分配記憶體 */ 
        blen = compressBound(hc->sb.st_size+1); /* 壓縮後的長度是不會超過blen的 */ 
        if((hc->file_address_gz = (char*)malloc(sizeof(char) * blen)) == NULL) 
        { 
            printf("no enough memory!\n"); 
            return -1; 
        } 
     
        /* 壓縮 */ 
        if(gzcompress(hc->file_address, hc->sb.st_size, hc->file_address_gz, &blen) != Z_OK) 
        { 
            printf("compress failed!\n"); 
            return -1; 
        } 
   
    send_mime(
        hc, 200, ok200title, hc->encodings, "", hc->type, blen,
        hc->sb.st_mtime );
    }

    return 0;
    }

 

send_mime中 hc->encoding內容(gzip),由於accept-encoding值決定,如果其值含有gzip,則此值為gzip

for ( i = 0; i < n_enc_tab; ++i )
    {
    if ( (ext_len == enc_tab[i].ext_len && strncasecmp( ext, enc_tab[i].ext, ext_len ) == 0)
        /* 用戶端請求支援gzip,伺服器端對於非gzip檔案, 可以採用gzip壓縮演算法 */
        || ( strcasestr(hc->accepte, "gzip") && strncasecmp( "gz", enc_tab[i].ext, ext_len ) == 0 ) )
    {
    if ( n_me_indexes < sizeof(me_indexes)/sizeof(*me_indexes) )
        {
        me_indexes[n_me_indexes] = i;
        ++n_me_indexes;
        }
    goto next;
    }
    }
/* No encoding extension found.  Break and look for a type extension. */
break;

 

發送階段 handle_send 函數中, 將 file_address修改為 file_address_gz

    /* Do we need to write the headers first? */
    if ( hc->responselen == 0 )
    {
    /* No, just write the file. */
    sz = write(
        hc->conn_fd, &(hc->file_address_gz[c->next_byte_index]),
        MIN( c->end_byte_index - c->next_byte_index, max_bytes ) );
    }
    else
    {
    /* Yes.  We‘ll combine headers and file into a single writev(),
    ** hoping that this generates a single packet.
    */
    struct iovec iv[2];

    iv[0].iov_base = hc->response;
    iv[0].iov_len = hc->responselen;
    iv[1].iov_base = &(hc->file_address_gz[c->next_byte_index]);
    iv[1].iov_len = MIN( c->end_byte_index - c->next_byte_index, max_bytes );
    sz = writev( hc->conn_fd, iv, 2 );
    }

 

實驗結果

以下載http協議為測試對象, http://www.w3.org/Protocols/rfc2616/rfc2616.txt

 

未實現gzip壓縮前, 回應檔大小為 422KB,回應時間為 19ms, 載入時間為 373ms

 

實現gzip壓縮後, 回應檔大小為 115KB,回應時間為 38ms, 載入時間為 396ms

從上面兩者對比,可以看出, 回應時間變長, 可以理解為伺服器端進行壓縮耗時 和 用戶端進行解壓耗時, 這兩個原因的耗時, 僅僅會比原來增加 20ms, 本文是執行的本地區域網路測試,

但是體積縮小了進四分之一,很是顯著, 如果是考慮互連網上的環境僅僅增加2oms的事件, 可以讓體積降低四分之是很划算的, 因為互連網上的耗時都耗費在傳輸上, 體積上減少四分之一, 則傳輸速度提高四倍,

例如互連網上資源很有可能傳輸都要以秒計算時間,原來3秒, 壓縮後0.7s:

 

響應報文內容:

thttpd增加gzip壓縮響應報文體功能,以減少傳輸資料量

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.