標籤:
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壓縮響應報文體功能,以減少傳輸資料量