高性能webserver
    lighttpd有一個功能,就是收到SIGHUP信號時會重新打開日志文件。這樣在日志切分時很有用。但最近發現了一個bug。

    就是如果有子進程掛掉。父進程新fork出的子進程accesslog會默認打日志到最最開始父進程啟動時的那個文件里。


   看了下代碼。原來父進程在收到SIGHUP的時候只是把errorlog重新打開了下。沒有重新打開accesslog(沒辦法,這個句柄是mod_accesslog模塊搞的)。所以父進程維護的accesslog句柄一直是最老的。它本身不打accesslog日志倒無所謂。但它fork出的子進程是打的。這樣就有問題了。



    一個最簡單方法。就是外部腳本判斷進程有更新的時候發一個SIGHUP信號過去。

    根治方法就是父進程重新啟動子進程時給其發一個SIGHUP信號。

    至于父進程自己處理SIGHUP時重新打開句柄這個我感覺不太好。畢竟那是模塊內部數據。lighttpd主干不應該關心。





Tags: ,

lighttpd中CONST_STR_LEN的用法

[| 不指定 2012/07/05 19:49]
    今天遇到一個問題,在獲取http頭的時候怎么也獲取不到,手動core出來和gdb上去調試發現都是空的,應該是開了O2優化的緣故,于是在程序中打印http頭,正常。

    不得已,單步gdb進匹配函數里,發現一個四字符的key值長度被判定為8,很奇怪,查代碼原來是用了個CONST_STR_LEN來代替了本來應該填ptr, strlen(ptr)的位置。而CONST_STR_LEN是一個宏,內容為:x, x ? sizeof(x) - 1 : 0。顯然,如果傳一個指針進去的話,sizeof指針的結果是8(字節,x64),這個宏只能在內容是字符串常量的時候用,不可以用在指針上。當時用的時候看lighttpd代碼中一些地方用了這個宏,于是想當然認為到處都可用。。看來還是要注意一些。









Tags:
    有一個問題,是在一個環境上的lighttpd一打日志就出core,很奇怪,看堆棧信息是出在mod_accesslog里,今天看了下,發現原來是試圖打印%i導致的。
    lighttpd支持在日志中打印請求頭中的字段,方法是%{key}i,這樣就能在請求頭中的key字段打印到日志里,打印referer等東西的時候比較方便。

    但如果直接寫%i的話,由于沒有指定key,導致NULL指針,lighttpd沒有校驗導致出core。

    恰好%I是打印請求長度,大寫I還是比較容易誤按成小寫的。所以有了這個問題



Tags: ,
    最近接觸到一個Transfer-Encoding: chunked相關的問題,原來http在應答時,有兩種方式來標示應答body的長度,一種就是用content-length方式直接指明body長度,還有一種就是chunk模式。

    在這種模式下,應答正文分段發送,每個chunk由長度段和數據段組成,每個段均由\r\n結束,當服務器發送完數據后,發送一個長度為0的chunk,即:0\r\n\r\n。其中長度段為十六進制表示。


舉例一個長度11的chunk:

b\r\n12345678901\r\n



    chunk模式多用于結果長度未定的情況下,比如用php輸出一個長字符串的時候,就默認使用的chunk模式,當然可以通過header來指定使用content-length模式。不過需要自己算出應答body的長度。

    chunk模式的一個好處是可以進行分段壓縮,服務器對每個chunk進行gzip壓縮發送給客戶端。


Tags:
    之前按字面意思理解handle_start_backend是說連接后端服務端口(webserver,fastcgi等等),今天發現并非如此。
    這個hook是在CON_STATE_HANDLE_REQUEST_HEADER狀態時,
如果con->mode仍舊是DIRECT類型且con->physical.path為空,會先調用:
plugins_call_handle_uri_raw
plugins_call_handle_uri_clean
plugins_call_handle_docroot
plugins_call_handle_physical

如果con->mode還是DIRECT,那么會判斷con->physical.path指定的文件是否存在,
    若存在,如果是軟鏈但是con->conf.follow_symlink為0,那么403,如果是目錄但請求url不是路徑名,則301跳轉到目錄路徑(在末尾加/)
    若無權限訪問,返回403
    若找不到文件,返回404
    若ENOTDIR(對文件做了目錄操作),則考慮path_info
    若EMFILE(進程句柄不足),則返回HANDLER_WAIT_FOR_FD
    若不是以上情況,打印錯誤日志,返回500


如果con->physical.path存在且無錯誤發生,或為ENOTDIR,那么又判斷了一次是否存在(這里代碼設計比較惡心)
    如果是普通文件且沒有軟鏈問題,那么break出去執行plugins_call_handle_start_backend。
    反之則一直向上遍歷,直到遍歷到一個真實存在的文件,如果找不到,那么404,如果找到了,將pathinfo串放入con->request.pathinfo。然后截短con->uri.path。

然后才會去調用plugins_call_handle_start_backend。
所以對于很多動態請求是不會調用plugins_call_handle_start_backend的。

這個鉤子被mod_access調用用來實現deny_all功能。
被mod_indexfile調用用來實現默認文件功能(請求/時映射到index.php等)
    lighttpd內部使用了狀態機處理每個請求,在狀態機中插入了若干個鉤子來供擴展使用,在執行到鉤子函數那里時,會按擴展載入順序,依次回調使用了該鉤子的各擴展指定的函數,這樣會有一些編程中隱藏的易錯點。

    1,順序在后面的鉤子不能假定前面的鉤子函數一定會被執行到。
         之前遇到過這樣的問題,在一個擴展中使用了兩個鉤子函數,第一個里面申請了一些資源,第二個里面使用并釋放,結果實際中發現對于某些請求,第一個鉤子可能沒有被執行就到了第二個鉤子那里,于是出core。
          查了一下原因,原來排在該擴展前面的mod_access擴展在第一個鉤子被調用時返回了HANDLER_FINISH,這樣,對于后續調用該鉤子的其他擴展不會被回調。于是該擴展的第一個鉤子函數未被調用到。
    
    2,同一個鉤子可能會被調用多次。
          一些情況下,連接狀態會rollback,這樣的話同一個hook會被回調多次,還有一些情況會導致調用多次,比如給多個鉤子指定了同一個處理函數。


    有時我們需要為每個擴展在每個連接生命周期內維護一個變量,這時可以用到con->plugin_ctx[p->id],這是一個void *指針,把數據指針存入該變量,并在連接釋放時釋放掉即可。
Tags:

lemon語法分析器模板初探

[| 不指定 2012/04/18 00:24]
    今天看了一下lighttpd解析http頭的過程,之前一直以為是單純用遍歷字符串的形式做的,今天發現除了遍歷字符串,還用到了語法分析器來做解析,生成語法分析器模板的就是lemon,語法比較直觀,不看文檔就能大概看出邏輯,不過深入研究就要借助文檔了,文檔比較晦澀,需要仔細研究。

    大概用法:使用lemon的語法編寫一個.y文件,然后調用lemon命令或使用lemon源文件將.y轉化成.c和.h,轉化后的.c看起來就很暈了,完全看不懂的說。
    這個東西還是挺有意思的,lighttpd還用它來解析配置文件。不過配置文件用lua也很不錯啊。我準備以后多使用lua作為配置文件,方便靈活。
Tags: ,

etag生成規則的配置-lighttpd

[| 不指定 2012/04/11 15:20]
    最近兩天調試一個程序的時候遇到一個問題,發現把一個文件兩行對換位置的時候lighttpd不會載入新文件,增加或刪除一行就會,考慮到lighttpd有stat cache,懷疑是不是不考慮mtime,只看inode,于是cp了一下,發現還是不行。沒辦法開gdb調試了一下,囧,原來生成的etag只用到了文件size這一個參數。怪不得。


    # 生成ETag的時候是否考慮文件的inode
    etag.use-inode = "enable"
  
    # 生成ETag的時候是否考慮文件的mtime
    etag.use-mtime = "enable"

    # 生成ETag的時候是否考慮文件的size
    etag.use-size  = "enable"


    這是引發困擾的三個參數。平時建議全部開啟,或開啟后兩個。
Tags: ,

lighttpd日志切分

[| 不指定 2012/03/09 18:56]
    之前在讀代碼的時候發現lighttpd在收到SIGHUP信號后會把日志重新打開一下,一直沒有理解這么做的意義是什么。今天終于用到了這個功能。
    一個新模塊沒有使用cronlog等日志切分工具,直接打印日志到文件,(使用管道切分日志有風險,被打印程序一旦hang住,lighttpd也就卡住了),但如何切分日志文件就變成了一個問題。mv的話由于不改變inode,還是往同一個文件打。cp代價太大。直接清空日志的話又太粗暴。這里就用到了sighup功能。只要將文件mv到新名字,然后用killall -s SIGHUP lighttpd,這樣lighttpd就會自動重新打開lighttpd.log打印了。
Tags: , ,
    最近有一個困擾近兩個月的bug終于解決了,心情愉快。503問題之前一直沒找到頭緒,壓力一大就開始有,越大就越多。剛開始一直認為503是正常現象,后端負載能力不足的必然結果。加之之前后端用的自己寫的模擬server,性能什么的沒什么保證。所以一直在看是不是程序邏輯上有什么漏洞會導致封禁所有后端,一直找不到頭緒。

    周五測試同學突然說:現在用的后端server肯定能力要強于前邊這個啊,怎么可能會因為負載力不足導致503呢?一想確實啊,肯定是流量調度部分的問題。開gdb仔細一找,結果大跌眼鏡,原來是跟后端的連接池的最大允許并發連接數開的太小了。。

    之前那個值設置的比較小是有道理的,因為php是每個進程處理一個請求的,所以并發數肯定不會超過啟動的php進程數。但現在后端改用了lighttpd,lighttpd可以承載的并發數是很多的,這樣的話在高并發請求的情況下后端連接池很容易就用完了。

    由此有兩個感觸,一是不同場景下配置項一定要仔細想想如何調優。二是bug并不都是邏輯錯誤導致的,還有可能是配置錯了。。。。
Tags:
分頁: 1/2 第一頁 1 2 下頁 最后頁 [ 顯示模式: 摘要 | 列表 ]
一级a做爰片_免费一级特黄大片_日本一级特黄大片 <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>