• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            那誰的技術(shù)博客

            感興趣領(lǐng)域:高性能服務(wù)器編程,存儲(chǔ),算法,Linux內(nèi)核
            隨筆 - 210, 文章 - 0, 評(píng)論 - 1183, 引用 - 0
            數(shù)據(jù)加載中……

            lighttpd1.4.18代碼分析(五)--處理超時(shí)連接

            本節(jié)相對(duì)簡(jiǎn)單, 講講lighttpd中如何處理超時(shí)的連接.
            方法很簡(jiǎn)單, lighttpd創(chuàng)建一個(gè)每隔一秒觸發(fā)的定時(shí)器, 被觸發(fā)后查找當(dāng)前的所有連接, 看它們的時(shí)間是否已經(jīng)超過了最長(zhǎng)的生存期, 如果是就關(guān)閉連接.

            創(chuàng)建定時(shí)器的代碼在server.c的main函數(shù)中:
            #ifdef USE_ALARM
                
            struct itimerval interval;

                interval.it_interval.tv_sec 
            = 1;
                interval.it_interval.tv_usec 
            = 0;
                interval.it_value.tv_sec 
            = 1;
                interval.it_value.tv_usec 
            = 0;
            #endif


            #ifdef USE_ALARM
                
            // 定時(shí)
                signal(SIGALRM, signal_handler);

                
            /* setup periodic timer (1 second) */
                
            if (setitimer(ITIMER_REAL, &interval, NULL)) {
                    log_error_write(srv, __FILE__, __LINE__, 
            "s""setting timer failed");
                    
            return -1;
                }

                getitimer(ITIMER_REAL, 
            &interval);
            #endif
            定時(shí)器觸發(fā)的時(shí)候產(chǎn)生ALARM信號(hào),此時(shí)在服務(wù)器主循環(huán)中輪詢所有的連接,這段代碼同樣在server.c的main函數(shù)中:
                    // 如果產(chǎn)生了alarm信號(hào) 那么一秒鐘過去了
                    if (handle_sig_alarm) {
                        
            /* a new second */

            #ifdef USE_ALARM
                        
            /* reset notification */
                        handle_sig_alarm 
            = 0;
            #endif

                        
            /* get current time */
                        
            // 獲得當(dāng)前的時(shí)間
                        min_ts = time(NULL);

                        
            // 如果當(dāng)前時(shí)間不等于server上次記錄的時(shí)間
                        if (min_ts != srv->cur_ts) {
                            
            int cs = 0;
                            connections 
            *conns = srv->conns;
                            handler_t r;

                            
            switch(r = plugins_call_handle_trigger(srv)) {
                            
            case HANDLER_GO_ON:
                                
            break;
                            
            case HANDLER_ERROR:
                                log_error_write(srv, __FILE__, __LINE__, 
            "s""one of the triggers failed");
                                
            break;
                            
            default:
                                log_error_write(srv, __FILE__, __LINE__, 
            "d", r);
                                
            break;
                            }

                            
            /* trigger waitpid */
                            
            // 更新server的當(dāng)前時(shí)間
                            srv->cur_ts = min_ts;

                            
            /* cleanup stat-cache */
                            
            // 每秒清空一次stat cache
                            stat_cache_trigger_cleanup(srv);
                            
                            
            /**
                             * check all connections for timeouts
                             
            */
                            
            // 檢查所有連接是否已經(jīng)超時(shí)
                            for (ndx = 0; ndx < conns->used; ndx++) {
                                
            int changed = 0;
                                connection 
            *con;
                                
            int t_diff;

                                con 
            = conns->ptr[ndx];

                                
            if (con->state == CON_STATE_READ ||
                                    con
            ->state == CON_STATE_READ_POST) {
                                    
            if (con->request_count == 1) {
                                        
            // 如果當(dāng)前時(shí)間與read_idle_ts之差大于max_read_idle, 超時(shí)
                                        if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
                                            
            /* time - out */

                                            connection_set_state(srv, con, CON_STATE_ERROR);
                                            changed 
            = 1;
                                        }
                                    } 
            else {
                                        
            // 如果當(dāng)前時(shí)間與read_idle_ts之差大于max_keep_alive_idle, 超時(shí)
                                        if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
                                            
            /* time - out */

                                            connection_set_state(srv, con, CON_STATE_ERROR);
                                            changed 
            = 1;
                                        }
                                    }
                                }

                                
            if ((con->state == CON_STATE_WRITE) &&
                                    (con
            ->write_request_ts != 0)) {
                                    
            // 如果當(dāng)前時(shí)間與write_request_ts之差大于max_write_idle, 超時(shí)
                                    if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
                                        
            /* time - out */
            #if 1
                                        log_error_write(srv, __FILE__, __LINE__, 
            "sbsosds",
                                                
            "NOTE: a request for",
                                                con
            ->request.uri,
                                                
            "timed out after writing",
                                                con
            ->bytes_written,
                                                
            "bytes. We waited",
                                                (
            int)con->conf.max_write_idle,
                                                
            "seconds. If this a problem increase server.max-write-idle");
            #endif
                                        connection_set_state(srv, con, CON_STATE_ERROR);
                                        changed 
            = 1;
                                    }
                                }
                                
                                
            /* we don't like div by zero */
                                
            // 如果接收連接的時(shí)間 = server當(dāng)前時(shí)間
                                if (0 == (t_diff = srv->cur_ts - con->connection_start)) 
                                    t_diff 
            = 1;

                                
            if (con->traffic_limit_reached &&            // 如果已經(jīng)達(dá)到了傳輸?shù)臉O限
                                    (con->conf.kbytes_per_second == 0 ||    // 似乎這個(gè)值一直是0啊
                                     ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {    // 如果每秒發(fā)送的數(shù)據(jù)量小于kbytes_per_second * 1024
                                    /* enable connection again */
                                    
            // 傳輸極限不再
                                    con->traffic_limit_reached = 0;

                                    changed 
            = 1;
                                }

                                
            // 如果狀態(tài)發(fā)生了改變, 那么進(jìn)入狀態(tài)機(jī)進(jìn)行處理
                                if (changed) {
                                    connection_state_machine(srv, con);
                                }

                                con
            ->bytes_written_cur_second = 0;
                                
            *(con->conf.global_bytes_per_second_cnt_ptr) = 0;

                            }

                            
            if (cs == 1
                                fprintf(stderr, 
            "\n");
                        }
                    }
                    

            需要注意的是, 由于lighttpd采用了這種方式處理超時(shí)連接, 會(huì)觸發(fā)大量的ALARM信號(hào)產(chǎn)生,在編碼的時(shí)候要特別注意被信號(hào)中斷的情況.


            posted on 2008-09-05 19:33 那誰 閱讀(3380) 評(píng)論(1)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程服務(wù)器設(shè)計(jì)Linux/Unixlighttpd

            評(píng)論

            # re: lighttpd1.4.18代碼分析(五)--處理超時(shí)連接  回復(fù)  更多評(píng)論   

            在程序中并沒有定義宏USE_ALARM,唯一的一處定義也被作者注釋掉了:
            /*
            * IRIX doesn't like the alarm based time() optimization
            */
            /*
            * #define USE_ALARM
            */
            好像每次循環(huán)中
            // 如果產(chǎn)生了alarm信號(hào) 那么一秒鐘過去了
            if (handle_sig_alarm) {。。。
            都會(huì)運(yùn)行,因?yàn)閔andle_sig_alarm始終是1.
            2010-03-18 22:24 | hcykernel
            久久亚洲AV成人无码软件| www.久久热.com| 久久人人爽人人爽人人片AV高清 | 久久精品免费观看| 久久天天躁狠狠躁夜夜2020老熟妇 | 精品国产91久久久久久久a| 国产精品久久波多野结衣| 久久人人超碰精品CAOPOREN | 国产精品无码久久综合| 国产精品伊人久久伊人电影| 久久福利资源国产精品999| 亚洲欧美日韩精品久久| 亚洲午夜久久久久妓女影院| 国产精品九九久久免费视频 | 国产福利电影一区二区三区久久久久成人精品综合 | 99久久久久| 精品国产日韩久久亚洲| 99久久精品免费| 狠狠色噜噜狠狠狠狠狠色综合久久| 无夜精品久久久久久| 精品久久久无码中文字幕天天| 久久久女人与动物群交毛片| 亚洲第一永久AV网站久久精品男人的天堂AV| 东京热TOKYO综合久久精品| 一本色综合网久久| 久久亚洲日韩看片无码| 色综合久久久久综合99| 久久婷婷五月综合97色直播| 伊人久久大香线蕉精品| 欧美日韩中文字幕久久伊人| 久久久久免费看成人影片| 99久久国产精品免费一区二区| 久久青青草原精品国产软件| 久久久久亚洲av成人无码电影| 精品久久久久久久中文字幕| 韩国三级中文字幕hd久久精品| 久久99国产精一区二区三区| 情人伊人久久综合亚洲| 国产99久久久国产精品~~牛| 91久久国产视频| 久久国产精品波多野结衣AV|