長鏈接及在Node中的應用——HTTP/1.1 keep-alive

HTTP請求都要通過TCP三次握手創建鏈接,四次分手斷開連,若是每一個HTTP請求都要創建TCP鏈接的話是極其費時的,所以HTTP/1.1中瀏覽器默認開啓了Connection: keep-alivenginx

請求頭中的這個屬性的做用能夠在請求完成後,保持TCP鏈接一段時間而不關閉,若是這個期間又有HTTP請求的話,直接使用這個TCP鏈接,省去了創建新的鏈接的時間。因爲是瀏覽器默認添加的,因此常常沒有關注。接下來看下在Node服務中發起HTTP請求是什麼樣子。

let request = require('request');
router.get('/http1', (req, res, next) => {
    request({
        method: 'GET',
        uri: 'http://xxx:8887/xxx'
    }, (error, response, body) => {
        console.log('response', response);
    });
});
複製代碼

在Node中咱們常常使用是request模塊來發送HTTP請求,那麼就作一個實驗,先向這個8887端口發送請求,結束後再看下這個鏈接是否還在。
...
json

能夠看到,請求完成後被請求的8887端口已經沒有鏈接了。也就是,若是再次請求還須要創建TCP鏈接,那麼就像瀏覽器同樣在請求頭中設置一下 Connection: keep-alive

request({
    method: 'GET',
    uri: 'http://xxx:8887/xxx',
    headers: {
        Connection: 'keep-alive'
    }
}, (error, response, body) => {
    console.log('response', response);
});
複製代碼

結果仍是和上面同樣,鏈接數仍是0,翻看request的文檔,原來並非這麼設置,而是使用forever這個配置promise

request({
    method: 'GET',
    uri: 'http://xxx:8887/xxx',
    forever: true // 這個很重要 開啓keep-alive
}, (error, response, body) => {
    console.log('response', response);
});
複製代碼

此次,在請求結束後,8887端口還存在一個鏈接, keep-alive已經生效了,這個鏈接會保持多久?通常在nginx中有設置,默認65s。
接下來看下,使用長鏈接後,是否省去了TCP的時間。
串行上面的請求10次來實驗。

router.get('/http1', (req, res, next) => {
    async function fn() {
        for (let i = 0; i < 10; i ++) {
            await new Promise((resolve, reject) => {
                request({
                    method: 'GET',
                    uri: 'http://xxx:8887/xxx',
                    time: true, // 配置這個屬性能夠看到時間信息
                    forever: true
                }, (error, response, body) => {
                    console.log('timingPhases', response.timingPhases);
                    resolve();
                });
            });
        }
        return 'success';
    }
    fn().then(()=>{
        res.json({
            msg: 'end'
        });
    });
});
複製代碼

能夠看到只有第一次的請求消耗了tcp的時間,以後的都是複用了以前創建的TCP鏈接,至於dns爲0是由於沒有使用域名。
以上就是在Node中如何使用 keep-alive及驗證。
順便看下,若是是並行請求,會創建多少個TCP鏈接呢?

router.get('/http1con', (req, res, next) => {
    let promiseArr = [];
    for (let i = 0; i < 10; i ++) {
        let newP = new Promise((resolve, reject) => {
            request({
                method: 'GET',
                uri: 'http://xxx:8887/xxx',
                time: true,
                forever: true
            }, (error, response, body) => {
                resolve();
            });
        });
        promiseArr.push(newP);
    }
    Promise.all(promiseArr).then(() => {
        res.json({
            'msg': 'end'
        });
    });
});
複製代碼

能夠看到HTTP/1.1並行請求的時候會創建多個TCP鏈接,在瀏覽器中針對同一域名只能夠同時創建6個鏈接,雖然Node中沒有這個限制,但如何讓多個同時的請求也使用同一個TCP鏈接呢?固然是有辦法的,這就須要使用到HTTP/2.0中的單一長鏈接了,以後再來分析HTTP/2.0。
相關文章
相關標籤/搜索