亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > Nginx > 正文

Nginx丟棄http包體處理實例詳解

2024-08-30 12:29:01
字體:
來源:轉載
供稿:網友

Nginx丟棄http包體處理實例詳解

http框架丟棄http請求包體和上一篇文章http框架接收包體, 都是由http框架提供的兩個方法,供http各個模塊調用,從而決定對包體做什么處理。是選擇丟棄還是接收,都是由模塊決定的。例如靜態資源模塊,如果接收到來自瀏覽器的get請求,請求某個文件時,則直接返回這個文件內容給瀏覽器就可以了。沒有必要再接收包體數據,get請求實際上也不會有包體。因此靜態資源模塊將調用http框架提供的丟棄包體函數進行丟包處理。

        相比接收包體過程, 丟棄包體操作就簡單很多了,至少不需要把包體存放到http結構中的request_body緩沖區,也不需要考慮包體是否只存放到內存,或者只存放到文件中等問題, 框架接收完包體后就直接丟棄了。丟棄包體由三部分組成:

        (1) http模塊首次調用框架提供的ngx_http_discard_request_body函數,做些初始化操作。例如如果一次操作無法丟棄所有包體 ,則需要重新把讀事件注冊到epoll中,這樣再次調度執行時,能夠繼續執行丟包操作。再者,調用實際的丟包函數ngx_http_read_discarded_request_body進行丟棄包體操作。

        (2)如果一次操作無法丟棄所有包體,則在事件再次被調度時,繼續接收剩余的包體數據,然后丟棄。

        (3)實際的丟包處理,也就是接收包體后,直接丟棄。

Nginx,丟棄,http包體,處理,http

        從圖中可以看出這三個過程中,丟包流程是一個公共的功能。也就是說不管http模塊調用ngx_http_discard_request_body函數開始進行丟包處理,還是一次調度沒有接收完全部包體時,由ngx_http_discarded_request_body_handler負責丟棄剩余的包體操作, 都會調用公共的丟包函數ngx_http_read_discarded_request_body進行接收包體后直接丟棄操作。

一、丟包初始化流程

        ngx_http_discard_request_body是被http模塊調用,用于丟棄包體的函數。對于模塊來講是一個透明的操作。也就是說模塊只需要調用這個接口就可以丟棄http請求包體,而不需要知道http框架是如何實現這個接口的??v使框架一次調度沒有丟棄完所有包體,下一次調度執行時會再次進行丟包操作,但對模塊來說,他們是不知道的。

//功能: 丟棄http包體的首次回調函數,如果一次性不能全部接收完成并丟棄,則設置 //  讀事件的回調為ngx_http_discarded_request_body_handler ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r) {   //需要丟棄的包體不用考慮超時問題  if (rev->timer_set)  {   ngx_del_timer(rev);  }   //包體長度小于等于0,則直接返回。表示丟棄包體  //如果已經接收過包體了,這時也不需要在接收。通常情況下get請求沒有包體,因此包體長度為0  if (r->headers_in.content_length_n <= 0 || r->request_body)  {   return NGX_OK;  }   size = r->header_in->last - r->header_in->pos;  //已經預先接收了部分包體  if (size)  {   //包體未全部接收完成   if (r->headers_in.content_length_n > size)   {    r->header_in->pos += size;    r->headers_in.content_length_n -= size;    }   else   {    //包體已經全部接收    r->header_in->pos += (size_t) r->headers_in.content_length_n;    r->headers_in.content_length_n = 0;    return NGX_OK;   }  }   //設置后續讀事件的回調  r->read_event_handler = ngx_http_discarded_request_body_handler;   //注冊讀事件回調,插入到epoll  ngx_handle_read_event(rev, 0));    //接收包體內容  if (ngx_http_read_discarded_request_body(r) == NGX_OK)  {   //表示已經接收到完整的包體了,將延遲關閉清0   r->lingering_close = 0;   }  else  {   //表示需要多次調度才能完成丟棄包體這個操作,于是把引用計數加1,防止這邊在丟棄包體,而其他   //事件卻已經讓請求意外銷毀   r->count++;   //標識為正在丟棄包體   r->discard_body = 1;  }   return NGX_OK; }  

         在接收http請求頭部時,如果也順便接收了http包體數據,這個時候就沒有必要繼續執行剩余的操作,丟棄包體成功,函數直接返回。如果一次調度沒有丟棄完所有包體,則會設置http請求結構ngx_http_request_s的讀事件read_event_handler為:ngx_http_discarded_request_body_handler, 下一次被調度時由這個函數負責丟棄剩余的包體。因此ngx_http_discard_request_body只會被http模塊首次調用。

        函數也會調用實際的丟包函數ngx_http_read_discarded_request_body開始進行接收包體后直接丟棄處理。

二、丟包處理

       ngx_http_read_discarded_request_body函數負責接收來自客戶端的包體數據,然后再丟棄。因此對于模塊而言,就是丟棄包體操作,但對于框架而言,丟棄包體操作其實就是接收包體操作, 只不過接收后的包體數據沒有交給模塊使用而已。為什么框架要接收包體后再直接丟棄呢? 豈不是多此一舉。其實不然,之所以這樣做是有原因的。假設某個不健壯的客戶端瀏覽器使用阻塞的方法向nginx服務器發送了http包體數據, 如果nginx框架不接收的話,會導致客戶端瀏覽器超時沒有反應,從而導致客戶端瀏覽器關閉這個連接。因此nginx的http框架要先從內核中接收來自客戶端的包體數據, 但這些數據對于模塊而言是沒有用的,因此接收后的這些數據會直接被丟棄。

//功能: 從內核中讀取數據到nginx中,nginx不對收到的數據進行處理。相當于丟棄包體 static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r) {  //用于接收包體的臨時緩沖區  u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];   for ( ;; )  {   //已經全部丟棄成功   if (r->headers_in.content_length_n == 0)   {    //設置丟棄后的讀事件回調,再有讀事件時,不做任何處理    r->read_event_handler = ngx_http_block_reading;    return NGX_OK;   }      //從內核中接收包體到臨時緩沖區   n = r->connection->recv(r->connection, buffer, size);    //更新剩余需要接收的包體大小   r->headers_in.content_length_n -= n;  } } 

        函數內部只是使用一個臨時的緩沖區變量存放每次接收來自內核的包體數據。并沒有把這部分數據保存到http請求結構中的request_body緩沖區。因此包體數據沒有交給http模塊,相當于被丟棄了。在所有包體從內核中接收完成時,設置http請求結構ngx_http_request_s的讀事件read_event_handler回調設置為: ngx_http_block_reading, 表示再收到來自客戶端的數據,則不進行任何處理了。因為已經接收完所有的包體數據,也就不需要理會來自客戶端瀏覽器的其它數據。

三、丟棄剩余的包體

        ngx_http_discarded_request_body_handler用于在一次調度中沒有丟棄完所有包體,則該函數會表調用,用于丟棄剩余的包體。函數內部也會調用實際的丟棄包體函數,進行接收包體然后丟棄操作。nginx服務器做了一個優化處理,會設置一個總超時時間,如果超過這個時間都還沒有丟棄完全部的包體,則會關閉這個連接。這是一種對服務器保護的措施,避免長時間的丟包操作占用服務器資源。

//功能: 第1次未能全部丟棄包體時,該函數被調用。之后有讀事件時,該函數被調用 void ngx_http_discarded_request_body_handler(ngx_http_request_t *r) {  //檢測延遲關閉時間,如果總時長超過了lingering_time,則不再接收任何包體,這是一個總時間。  //總超時后,將直接光比連接  if (r->lingering_time)  {   timer = (ngx_msec_t) (r->lingering_time - ngx_time());   //已經到達了延遲關閉時間   if (timer <= 0)   {    //清空丟棄包體標識,表示包體已經丟棄    r->discard_body = 0;     //延遲關閉開關清0    r->lingering_close = 0;    ngx_http_finalize_request(r, NGX_ERROR);    return;   }   }   //接收包體后丟棄  rc = ngx_http_read_discarded_request_body(r);  //表示包體已經全部丟棄  if (rc == NGX_OK)  {   r->discard_body = 0;  //包體已經全部接收完   r->lingering_close = 0;  //清空延遲關閉標志   ngx_http_finalize_request(r, NGX_DONE);   return;  } } 

        ngx_http_discarded_request_body_handler這個函數是怎么被事件對象調用的呢? 在前面的文章已經分析了,ngx_connection_s讀事件的回調設置為ngx_http_request_handler。   因此在讀事件發生時,會回調請求結構的讀回調。如果還不是不清楚這個調用過程

static void ngx_http_request_handler(ngx_event_t *ev) {  //如果同時發生讀寫事件,則只有寫事件才會觸發。寫事件優先級更高  if (ev->write)   {   r->write_event_handler(r); //在函數ngx_http_handler設置為ngx_http_core_run_phases  }  else  {   r->read_event_handler(r); //在函數ngx_http_process_request設置為ngx_http_block_reading  } } 

        到此為止,http框架丟棄包體的流程已經分析完成了。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情按摩在线| 国产成人高清激情视频在线观看| 日韩av在线免费播放| 91精品国产色综合| 亚洲精品98久久久久久中文字幕| 亚洲free性xxxx护士hd| 久久精品国产一区二区电影| 久久久精品999| 91在线观看欧美日韩| 国产精品高清在线| 欧美日韩成人网| 亚洲成人av在线播放| 久久免费国产视频| 怡红院精品视频| 粗暴蹂躏中文一区二区三区| 日韩欧美中文免费| 国产精品网站视频| 久久99精品久久久久久青青91| 国产欧美一区二区三区视频| 精品久久久久久久久国产字幕| 欧美成年人网站| 91久久精品国产91久久| 中文字幕成人在线| 久久亚洲欧美日韩精品专区| 精品在线欧美视频| 国产精品一二区| 亚洲欧美激情另类校园| 91精品一区二区| 中文字幕精品在线视频| 久久伊人精品一区二区三区| 色多多国产成人永久免费网站| 欧美国产日韩一区二区在线观看| 亚洲深夜福利视频| 久久夜精品va视频免费观看| 97热精品视频官网| 亚洲欧美国产精品va在线观看| 国产精品h在线观看| 国产亚洲a∨片在线观看| 亚洲国产日韩欧美综合久久| 欧美高清不卡在线| 久久精品电影网站| 久久精品夜夜夜夜夜久久| 亚洲免费电影一区| 国产精品丝袜白浆摸在线| 日韩av在线免费| 精品国偷自产在线视频| 国产精品久久久久久久久免费| 91久久在线播放| 欧美午夜激情在线| 国产精品第三页| 欧美夜福利tv在线| 亚洲精品成人久久| 亚洲深夜福利视频| 久久精品色欧美aⅴ一区二区| 久久久精品999| 亚洲电影成人av99爱色| 国产成人自拍视频在线观看| 久久精品国产精品亚洲| 欧美性猛xxx| 欧美激情综合亚洲一二区| 国产精品高潮视频| 最近中文字幕日韩精品| 欧美富婆性猛交| 亚洲午夜性刺激影院| 中文字幕亚洲自拍| 国产精品视频最多的网站| 久久不射热爱视频精品| 最新国产精品亚洲| 国自产精品手机在线观看视频| 亚洲资源在线看| 欧美精品在线观看91| 日本久久久久久久久久久| 欧美精品中文字幕一区| 久久综合久久88| 亚洲国产毛片完整版| 成人精品视频99在线观看免费| 亚洲色无码播放| 精品偷拍一区二区三区在线看| 国内精品久久久久伊人av| 久久亚洲精品中文字幕冲田杏梨| 久久久之久亚州精品露出| 国产精品成熟老女人| 欧美在线激情网| 91综合免费在线| 亚洲精品网址在线观看| 亚洲最大av网| 亚洲欧美国产日韩天堂区| 亚洲欧美日韩精品久久| 成人免费淫片视频软件| 欧美理论电影在线观看| 国模极品一区二区三区| 国a精品视频大全| 日韩中文字幕第一页| 成人国产精品久久久久久亚洲| 国产在线观看91精品一区| 日韩精品在线第一页| 国产剧情日韩欧美| 国产精品久久久久久久久久久久| 亚洲性日韩精品一区二区| 热久久免费国产视频| 中文字幕免费国产精品| 亚洲社区在线观看| 国产精品日韩在线播放| 中文字幕日韩专区| 久久久精品亚洲| 欧美大片免费观看| 亚洲影视九九影院在线观看| 欧美成人国产va精品日本一级| 日本乱人伦a精品| 亚洲男人的天堂在线| 九九久久精品一区| 欧美疯狂xxxx大交乱88av| 欧美日韩精品在线视频| 欧美精品第一页在线播放| 精品国产一区二区三区久久| 亚洲精品美女在线观看播放| 国产视频精品va久久久久久| 精品国产一区二区三区久久久| 亚洲精品动漫久久久久| 欧美另类老肥妇| 日韩有码片在线观看| 日韩av在线资源| 中文字幕亚洲字幕| 原创国产精品91| 国产精品视频一区二区高潮| 国产精品私拍pans大尺度在线| 日韩av最新在线| 欧美激情videos| 精品日本美女福利在线观看| 91精品久久久久久久久久另类| 亚洲免费视频一区二区| 国产又爽又黄的激情精品视频| 日韩高清电影免费观看完整版| 国产日韩欧美中文| 国产视频精品在线| 亚洲美女av电影| 国产精品第一第二| 国产精品综合不卡av| 亚洲a一级视频| 超薄丝袜一区二区| 国产专区欧美专区| 国产成人avxxxxx在线看| 伊人男人综合视频网| 欧洲亚洲免费在线| 亚洲精品美女视频| 中文字幕欧美日韩精品| 亚洲缚视频在线观看| 国产亚洲精品久久久久久牛牛| 奇米4444一区二区三区| 欧美激情亚洲一区| 国产脚交av在线一区二区| 亚洲欧美一区二区三区情侣bbw| 伊人av综合网| 久久久久久久久亚洲| 欧美中文在线观看| 国产成人精品免费久久久久| 久久久人成影片一区二区三区观看| 日韩av在线电影网| 91亚洲精品久久久| 国产在线98福利播放视频| 亚洲网址你懂得| 亚洲伊人一本大道中文字幕| 国产日本欧美一区二区三区在线| 日韩av网址在线观看|