首页 > 网站 > Nginx > 正文

Nginx丢弃http包体处理实例详解

2024-08-30 12:25:31
字体:
来源:转载
供稿:网友

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)实际的丢包处理,也就是接收包体后,直接丢弃。

        从图中可以看出这三个过程中,丢包流程是一个公共的功能。也就是说不管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框架是如何实现这个接口的。纵使框架一次调度没有丢弃完所有包体,下一次调度执行时会再次进行丢包操作,但对模块来说,他们是不知道的。

//功能: 丢弃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; }              
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表