<li id="q4aaq"><object id="q4aaq"></object></li>
<xmp id="q4aaq">
  • <button id="q4aaq"><li id="q4aaq"></li></button>
  • <optgroup id="q4aaq"><sup id="q4aaq"></sup></optgroup><center id="q4aaq"><acronym id="q4aaq"></acronym></center>
  • <strong id="q4aaq"></strong>
  • <nav id="q4aaq"><menu id="q4aaq"></menu></nav>
    高性能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 下頁 最后頁 [ 顯示模式: 摘要 | 列表 ]
    色琪琪av男人的天堂-琪琪see色原网色原网站-天天谢天天谢天天要-欧美成人视频