亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Nginx丟棄http包體處理實(shí)例詳解

 更新時(shí)間:2017年06月30日 14:18:56   投稿:lqh  
這篇文章主要介紹了Nginx丟棄http包體處理實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下

Nginx丟棄http包體處理實(shí)例詳解

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

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

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

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

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

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

一、丟包初始化流程

        ngx_http_discard_request_body是被http模塊調(diào)用,用于丟棄包體的函數(shù)。對(duì)于模塊來講是一個(gè)透明的操作。也就是說模塊只需要調(diào)用這個(gè)接口就可以丟棄http請(qǐng)求包體,而不需要知道http框架是如何實(shí)現(xiàn)這個(gè)接口的。縱使框架一次調(diào)度沒有丟棄完所有包體,下一次調(diào)度執(zhí)行時(shí)會(huì)再次進(jìn)行丟包操作,但對(duì)模塊來說,他們是不知道的。

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

         在接收http請(qǐng)求頭部時(shí),如果也順便接收了http包體數(shù)據(jù),這個(gè)時(shí)候就沒有必要繼續(xù)執(zhí)行剩余的操作,丟棄包體成功,函數(shù)直接返回。如果一次調(diào)度沒有丟棄完所有包體,則會(huì)設(shè)置http請(qǐng)求結(jié)構(gòu)ngx_http_request_s的讀事件read_event_handler為:ngx_http_discarded_request_body_handler, 下一次被調(diào)度時(shí)由這個(gè)函數(shù)負(fù)責(zé)丟棄剩余的包體。因此ngx_http_discard_request_body只會(huì)被http模塊首次調(diào)用。

        函數(shù)也會(huì)調(diào)用實(shí)際的丟包函數(shù)ngx_http_read_discarded_request_body開始進(jìn)行接收包體后直接丟棄處理。

二、丟包處理 

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

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

        函數(shù)內(nèi)部只是使用一個(gè)臨時(shí)的緩沖區(qū)變量存放每次接收來自內(nèi)核的包體數(shù)據(jù)。并沒有把這部分?jǐn)?shù)據(jù)保存到http請(qǐng)求結(jié)構(gòu)中的request_body緩沖區(qū)。因此包體數(shù)據(jù)沒有交給http模塊,相當(dāng)于被丟棄了。在所有包體從內(nèi)核中接收完成時(shí),設(shè)置http請(qǐng)求結(jié)構(gòu)ngx_http_request_s的讀事件read_event_handler回調(diào)設(shè)置為: ngx_http_block_reading, 表示再收到來自客戶端的數(shù)據(jù),則不進(jìn)行任何處理了。因?yàn)橐呀?jīng)接收完所有的包體數(shù)據(jù),也就不需要理會(huì)來自客戶端瀏覽器的其它數(shù)據(jù)。

三、丟棄剩余的包體

        ngx_http_discarded_request_body_handler用于在一次調(diào)度中沒有丟棄完所有包體,則該函數(shù)會(huì)表調(diào)用,用于丟棄剩余的包體。函數(shù)內(nèi)部也會(huì)調(diào)用實(shí)際的丟棄包體函數(shù),進(jìn)行接收包體然后丟棄操作。nginx服務(wù)器做了一個(gè)優(yōu)化處理,會(huì)設(shè)置一個(gè)總超時(shí)時(shí)間,如果超過這個(gè)時(shí)間都還沒有丟棄完全部的包體,則會(huì)關(guān)閉這個(gè)連接。這是一種對(duì)服務(wù)器保護(hù)的措施,避免長時(shí)間的丟包操作占用服務(wù)器資源。

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

        ngx_http_discarded_request_body_handler這個(gè)函數(shù)是怎么被事件對(duì)象調(diào)用的呢? 在前面的文章已經(jīng)分析了,ngx_connection_s讀事件的回調(diào)設(shè)置為ngx_http_request_handler。   因此在讀事件發(fā)生時(shí),會(huì)回調(diào)請(qǐng)求結(jié)構(gòu)的讀回調(diào)。如果還不是不清楚這個(gè)調(diào)用過程,可以參考: nginx處理http請(qǐng)求這篇文章

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

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

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

相關(guān)文章

  • Nginx提高安全與性能的最好配置詳解

    Nginx提高安全與性能的最好配置詳解

    這篇文章主要介紹了Nginx提高安全與性能的最好配置詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Nginx報(bào)404錯(cuò)誤的詳細(xì)解決方法

    Nginx報(bào)404錯(cuò)誤的詳細(xì)解決方法

    最近打開網(wǎng)站看看結(jié)果提示:nginx 404 not found,所以這篇文章主要給大家介紹了關(guān)于Nginx報(bào)404錯(cuò)誤的簡單解決方法,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Nginx實(shí)現(xiàn)動(dòng)靜分離的示例代碼

    Nginx實(shí)現(xiàn)動(dòng)靜分離的示例代碼

    這篇文章主要介紹了Nginx實(shí)現(xiàn)動(dòng)靜分離的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01
  • nginx+lua+redis防刷和限流的實(shí)現(xiàn)

    nginx+lua+redis防刷和限流的實(shí)現(xiàn)

    本文將介紹如何使用nginx lua redis實(shí)現(xiàn)防刷和限流,首先,我們將了解防刷和限流的基本概念和必要性,然后,我們將詳細(xì)介紹如何使用nginx lua redis實(shí)現(xiàn)防刷和限流,感興趣的可以了解一下
    2023-09-09
  • nginx配置二級(jí)域名的示例代碼

    nginx配置二級(jí)域名的示例代碼

    這篇文章主要介紹了nginx配置二級(jí)域名的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • centos7系統(tǒng)下nginx安裝并配置開機(jī)自啟動(dòng)操作

    centos7系統(tǒng)下nginx安裝并配置開機(jī)自啟動(dòng)操作

    這篇文章主要介紹了centos7系統(tǒng)下nginx安裝并配置開機(jī)自啟動(dòng)操作方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02
  • PHP的Symfony和CodeIgniter框架的Nginx重寫規(guī)則配置

    PHP的Symfony和CodeIgniter框架的Nginx重寫規(guī)則配置

    這篇文章主要介紹了PHP的Symfony和CodeIgniter框架的Nginx重寫規(guī)則配置,文中截取配置中關(guān)鍵的一些rewrite寫法進(jìn)行講解,需要的朋友可以參考下
    2016-01-01
  • Nginx如何配置Http、Https、WS、WSS的方法步驟

    Nginx如何配置Http、Https、WS、WSS的方法步驟

    這篇文章主要介紹了Nginx如何配置Http、Https、WS、WSS的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Nginx使用ngx_http_upstream_module實(shí)現(xiàn)負(fù)載均衡功能示例

    Nginx使用ngx_http_upstream_module實(shí)現(xiàn)負(fù)載均衡功能示例

    本文主要介紹了Nginx使用ngx_http_upstream_module實(shí)現(xiàn)負(fù)載均衡功能示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • nginx正向代理的配置和使用教程

    nginx正向代理的配置和使用教程

    本文主要介紹了nginx正向代理的配置和使用教程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07

最新評(píng)論