nginx
来源:互联网 发布:工厂生产数据表格 编辑:程序博客网 时间:2024/05/20 00:53
request
:在nginx中我们指的是http请求,具体到nginx的数据结构是ngx_http_request;ngx_http_request_t是对一个http请求的封装;我们知道一个http请求包含请求行,请求头,请求体,响应行,响应头,响应体。
http请求是典型的请求-响应类型的网络协议,而http是文件协议。所以我们在分析请求行与请求头,以及响应头和响应行,往往是一行一行进行处理。如果自己建立http服务器,通常在一个连接建立起来之后,客户端发送过来请求。我们读取一行数据,分析出请求行中包含的method、url、http_version信息,然后一行一行处理请求体。得到请求后,我们处理请求产需要输出的数据,然后生成响应行,响应头以及响应体。在将响应发给客户端之后,一个完整的请求就处理完了。当请求读取完成,就开始进行请求的处理。nginx通过ngx_http_request来保存生的解析请求与输出响应相关的数据。
请求来到:nginx->
nginx做法是先不去读取请求body,所以我们设置read_event_handler为ngx_http_block_reading,即不读取数据了。
最终是调用ngx_http_core_run_phases来处理请求,产生的响应头是放在ngx_http_request_t的headers_input中。nginx的各种阶段会对请求进行处理,最后调用filter函数来过滤数据,对数据进行加工,如truncated传输,gzip压缩;这里的filte包括header filter和body filter,即响应头或响应提处理。filter是一个链表结构,分别有header filter和body filter,先执行所有的header filter,然后在执行body filter中的所有filter。在header filter的最后一个filter,ngx_http_header_filter,这个filter会遍历所有的响应头,最后需要输出的响应头在一个连续的内存,然后调用ngx_http_write_filter进行输出。ngx_http_write_filter是body filter中的最后一个,所以nginx首先的body信息,在经过一系列body filter之后,会调用ngx_http_write_filter进行输出。
nginx会将整个请求头放在一个buffer中,这个buffer可以通过配置项client_header_buffer_size来设置,如果用户请求头太大,这个buffer装不下,那么nginx就会再次分一个更大的buffer来装请求头,这个大的buffer可以通过large_client_header_buffers来设置,这个large_buffer这一组buffer,比如配置4 8k,就代表四个8k大小的buffer可以用。为了保存请求行或者请求头的完整性,一个完整的请求行或者请求头,需要放在一个连续的内存中。所以一个完整的请求航或请求头,只会保存在一个buffer里面。如果一个请求行大于一个buffer返回414;如果一个请求头大小大于一个buffer,返回400;
keepalive
content-length来表明body的大小,否则返回400;也就是说请求体长度是固定的,那么响应体的长度呢
如果是keepalive的话,那么nginx在输出完响应体之后,会设置当前连接keepalive属性,等待客户端下一次请求;同时设置一个最大请求时间,这个时间是通过keepalive_timeout来配置,如果是0则表示关闭掉keepalive,无论http版本,都会强制close;
如果服务器端最后的决定是keepalive打开,那么响应的http头里面,也会包含connection头域,其值是keep-alive。所以对于请求量比较大的nginx来说,关掉keepalive最后会产生比较多的time_wait
状态的socket。所以当客户端的一次访问,需要多次访问同一个server时,打开keepalive的优势很大。比如图片服务器,通过一个而网友包含很多图片,打开keepalive会大量减少time-wait数量
pipeline
目的是一个连接做多次请求;如果客户需要提交读个请求,那么对于keepalive来说,第二个请求必须等到第一个请求响应接收完全后,才能发起,这和tcp的停止等到协议是一样的,得到响应的时间至少为2*RTT。而对于pipeline来说,不需要等到第一个请求处理完成,马上可以发起第二个请求,时间可以达到1*RTT。nginx可以直接支持pipeline。如果nginx在处理完前一个请求后,如果发现buffer里面还有数据,就认为是下一个请求的开始,然处理下一个请求,否则就设置keepalive。
lingering_close
延时关闭。当nginx关闭连接时候,并不是立即关闭,而是先关闭tcp连接的写,在等待一段时间后在关闭tcp的读。如nginx在接收客户端请求时,可能客户端或服务器端出错了,要立即响应错误信息给客户端,而nginx在响应错误信息后,大部分情况是需要关闭当前连接。nginx执行完write()系统调用把错误信息发送给客户端,write()系统 调用返回成功并不代表数据发送到客户端,有可能还在tcp连接的write buffer里。如果直接执行close()系统调用关闭tcp连接,内核首先会检查tcp的read buffer里有没有客户端发送过来的数据留着内核态而没有被用户态进程读取,如果有则发送给客户端RST报文来关闭tcp连接丢弃write buffer里的数据,如果没有则等待write buffer里的数据发送完毕,然后在经过4次分手报文断开连接。所以在某些场景下出现tcp write buffer里的数据在write()系统调用之后close()系统调用执行之前没有发送完毕,且tcp read buffer里面还有数据没有读,close()系统调用会导致客户端收到RST报文且不会拿到服务器发送过来的错误信息数据。
ngx_str_t
typedef struct{ size_t len; u_char *data;}ngx_str_t;
data指向字符串数据的第一个字符,字符串结束用长度来表示,而不是’\0’来表示;
1.通过长度来表示字符串长度,减少计算字符串的次数
2.nginx可以重复引用一段字符串内存,而不能更改原来的字符串,长度表示结束,而不是去cp一份自己的字符串(因为如果’\0’结束,而不能更改原来字符串,所以势必要cp一端字符串);如request_line /uri/args等,这些字符串的data部分,都是指向在接收数据时创建的buffer所指向的内存,uri,args没有必要cp一份出来,减少了不必要的内存分配与拷贝。正是基于此,nginx必须谨慎的修改一个字符串。
- nginx
- Nginx
- Nginx
- Nginx
- Nginx
- nginx
- nginx
- nginx
- nginx
- nginx
- nginx
- nginx
- nginx
- Nginx
- nginx
- nginx
- nginx
- nginx
- win10更新版本之后选择适合的VirtualBox&genymotion版本
- caffe 理解
- 详解Java注解(上)
- 3dmax基本操作之骨骼
- Error: [$injector:nomod] Module 'dayApp' is not available!
- nginx
- 单位转换
- 51学习库(2)--矩阵键盘
- 设计模式
- (复习)Struts2+MySQL完成登录数据是够为空的校验(二)
- 反射机制调用普通成员方法
- B. T-shirt buying(stl)
- 非递减排列 非递增排列 递减排列 递增排列
- java XML转JSON格式