Nginx

来源:互联网 发布:淘宝app是h5开发的吗 编辑:程序博客网 时间:2024/05/20 02:53

1.

每个worker进程都是从master进程fork过来的,在master进程里面,先建立好需要listen的socket(listanfd)之后,然后fork出来多个worker进程。所有worker进程的listenfd会在新连接到来时候变的可读,为了保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,在返回给客户端,最后断开连接。一个请求完全在worker进程中处理,而且只在一个worker进程中处理。
nginx采用异步非堵塞。

connection

在nginx中connection就是对tcp的封装,其中包括连接的socket,读事件、写事件。利用nginx封装的connection,我们可以很方便的使用nginx来处理与连接相关的事情。

  • 1.nginx启动的时候,解析配置文件,得到需要监听的端口与ip地址,然后在nginx的master进程里面,先初始化这个监听的socket(创建socket,设置addreuse等,绑定到指定的IP地址端口,在listen),然后fork出来多个子进程,子进程会竞争accept新的连接
  • 2.客户端向nginx发起连接。当客户端与服务器端通过三次握手建立好连接,nginx的某一个子进程会accept连接成功,得到这个建立好的连接socket,然后创建nginx对连接的封装,即ngx_connection_t结构体
  • 3.设置读写事件处理函数并添加读写事件来与客户端进行数据交换
  • 4.nginx或者客户端主动关闭连接
  • 5.连接关闭

worker连接池

连接池保存的不是真实的连接,只是一个worker_connection大小的ngx_connection_t结构的数组,并且nginx会通过一个链表的free_connetions来保存所有空闲的ngx_connection_t,每次取一个连接时,就会从空闲连接链表中获取一个,用完在放回空闲空闲链表里面。
worker_connection是每个worker进程所能建立连接的最大值。

nginx_accept_disable

nginx会控制进程是否添加accept事件,使用ngx-accept_disabled的变量来控制是否去竞争accept_mutex锁。

http中的request

ngx_http_request_t:封装了一个http请求,包含请求行,请求头,请求体,响应行,响应头,响应体。
http请求是典型的请求-响应类型的网络协议,而http是文件协议。

ngx_http_init_request

在这个函数中,设置读事件为ngx_http_process_request_line,处理事件的第一步就是处理请求行;通过ngx_http_read_request_header来读取请求数据。ngx_http_parse_request_line函数来解析请求请求行。
解析完请求行后会设置读事件handler为ngx_http_process_request_headers,后续请求就在ngx_http_process_request_headers中完成。ngx_http_process_request_headers调用ngx_http_read_request_header来读取请求头,调用ngx_http_parse_header_line来解析一行请求头,解析到的请求头会保存到ngx_http_request_t的域headers_in中,headers_in是一个链表结构,保存所有的请求头。在HTTP中某些请求需要特殊处理,这些请求头与请求处理函数存放在一个映射表里面,即ngx_http_headers_in,在初始化时,会生成一个hash表,当每解析一个请求头后,就会在这个hash表中查找。如果找到,则调用相应的处理函数来处理这个请求头。比如host头的处理函数是ngx_http_process_host
1.当nginx解析到两个回车换行符,就代表请求头结束,调用ngx_http_process_request处理请求。
2.ngx_http_process_request会设置当前连接读写事件处理函数为ngx_http_request_handler,然后调用ngx_http_handler来真正处理一个完整的http请求;
3.读写事件处理函数都是ngx_http_request_handler,其实在这个函数中会根据当前事件是读还是写事件分别调用ngx_http_request_t中的read_eventhandler或者是write_event_handler.
nginx将一个http请求处理成多个阶段,ngx_http_core_run_pharses最后会产生数据。

ngx_table_elt_t

typedef struct {    ngx_uint_t hash;    ngx_str_t key;    ngx_str_t value;    u_char *lowcase_key;}ngx_table_elt_t;

ngx_table_elt_t是为HTTP头部‘量身订制’的,其中key存储头部名称(如Content-Length),value存储对应的值(如1024),lowcase_key是为了忽略HTTP头部名称的大小写(如有些客户端发来的HTTP请求头部是content-length,Nginx希望与大小写敏感的Content-Length做相同处理)。hash用于快速检索头部

ngx_buf_t

是Nginx处理大数据的关键数据结构,它既应用于内存数据也应用于磁盘数据。

ngx_chain_t

ngx_chain_t是与ngx_buf_t配合使用的链表数据结构;
typedef struct ngx_chain_s;
struct ngx_chain_s{
ngx_buf_t *buf;
ngx_chain_t *next;
};
buf指向当前的ngx_buf_t缓冲区,next则用来指向下一个ngx_chain_t.如果这是最后一个ngx_chain_t,则需要把next设置为NULL;

config文件的写法

config文件其实是一个可执行的shell脚本;config文件中需要定义3个变量
1.ngx_addon_name:仅在configure执行时候使用,一般设置为模块名称;
2.HTTP_MODULES:保存所有的HTTP模块名称。每个HTTP模块间由空格符相连。
“$HTTP_MODULES ngx_http_mytest_module”
3.NGX_ADDON_SRCS:用于指定新增模块的源代码,多个待编译的源代码间以空格符相连。

因此对于mytest模块,可以这样编写config文件:
ngx_addon_name=ngx_http_mytest_module
HTTP_MODULES=”HTTPMODULESngxhttpmytestmoduleNGXADDONSRCS=NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_module.c”