//下面是个人以时间,事件和读写为断点进行数据捕获得出的结论(以tomcat为后端服务器)
//如果对内部处理流程,不是很清楚的,可以参考个人文章“nginx 请求处理流程(非配置upstream)”,请求的接受和处理包括发送,应该基本一直
//conf配置:
upstream tomcat_server {
65 server 127.0.0.1:8080;
66 }
67
68 server {
69 listen 8888;
70 server_name jueduiyingxiong.oicp.net;
71 index index.html index.htm index.jsp default.jsp index.do default.do;
72 root /data0/htdocs/www;
73
74 if (-d $request_filename)
75 {
76 rewrite ^/(.*)([^/])$ permanent;
77 }
84 location / {
85 proxy_buffering off;
86 proxy_pass
87 }
//参数说明: ep = 5 为epoll套接口;c->fd = 8为 listen 套接口;fd=9为客户端请求套接口;c->fd = 10为后端服务器tomcat套接口
//只是添加epoll事件
//未循环 //把监听事件加入可读事件
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { ep = 5 c->fd = 8
//处理接受存放新链接事件(接受客户)
//第一次序循环 //循环处理接受(并发)把接受的套接口加入可读事件
1/events = epoll_wait(ep, event_list, (int) nevents, timer);
2/rev->handler = 0x4958f0 c->fd = 8
3/ngx_add_timer(rev, c->listening->post_accept_timeout); fd=9
4/if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) c->fd = 9 ep = 5
//读取客户端请求数据,创建后端链接(读客户,链接服务)
//第二次循环 //从客户端读取请求信息,解析完后,创建套接口,链接后端服务器,添加客户处理可写事件和后端服务可写事件
5/events = epoll_wait(ep, event_list, (int) nevents, timer); ep = 5
6/rev->handler = 0x439183 c->fd = 9
7/n = recv(c->fd, buf, size, 0); n =515 c->fd = 9
8/ngx_del_timer(c->read); c->fd = 9 //如果不走这里那么错误
9/c->write->handler = ngx_http_request_handler; fd = 9
10/if (ngx_add_event(c->write, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) ep = 5 c->fd = 9
11/if (ngx_add_conn(c) == NGX_ERROR) { //添加10的可写事件,这里加的是读写事件,所以引起第四次循环
12/rc = connect(s, pc->sockaddr, pc->socklen); s = 10 rc = -1 (错误是115 原因是设置非堵塞的原因,不回影响程序调用)
13/c->write->handler = ngx_http_upstream_handler; c->read->handler = ngx_http_upstream_handler;fd = 10
10/ngx_add_timer(c->write, u->conf->connect_timeout);//添加定时器 fd = 10
//处理特需操作和向后端服务器转发请求消息(写服务)
//第三次循环 //处理客户可写事件(特需处理才操作),向后端服务器发送请求关闭写操作事件
14/events = epoll_wait(ep, event_list, (int) nevents, timer);//nevents为512,timer500毫秒 c->fd = 9
15/wev->handler = 0x43c4b5 fd = 9
16/wev->handler = 0x445aaa c->fd = 10
17/if (ev->write) {u->write_event_handler(r, u);
18/u->write_event_handler = 0x446b17
19/rc = writev(c->fd, header.elts, header.nelts);c->fd = 10 rc = 447
20/ngx_del_timer(c->write); fd = 10
21/ngx_add_timer(c->read, u->conf->read_timeout); fd=10
//读取后端服务器数据,写入客户端(读后端,写客户)
//第四次循环 //读取后端服务器返回数据,向客户端发送数据信息(发送两次待查),再次接受客户端请求,如果有数据,可能走到第二次循环(待查)
22/events = epoll_wait(ep, event_list, (int) nevents, timer);//nevents为512,timer500毫秒 fd = 10
23/rev->handler = 0x445aaa
if (ev->write) {} else {u->read_event_handler(r, u);
24/u->read_event_handler = 0x446be8
25/n = recv(c->fd, buf, size, 0); c->fd = 10 n =0 n = 1308
26/rc = writev(c->fd, header.elts, header.nelts); c->fd = 9 rc=837
27/ngx_del_timer(c->read); fd = 10
28/rc = writev(c->fd, header.elts, header.nelts);c->fd = 9 rc =20
ngx_del_conn(c, NGX_CLOSE_EVENT);//删除链接
29/ngx_add_timer(rev, clcf->keepalive_timeout); fd = 9
30/rev->handler = ngx_http_keepalive_handler;
31/n = recv(c->fd, buf, size, 0);c->fd = 9 n = -1
32/ngx_del_timer(c->read);
//重复请求 如果没有accept那么先走accept流程和上面流程一样
//接受客户端数据,链接服务器(读客户,链接后端)
//第一次循环 //接受客户端数据,添加后端服务器事件,链接到后端服务器
1/events = epoll_wait(ep, event_list, (int) nevents, timer);//nevents为512,timer500毫秒
2/rev->handler = ngx_http_keepalive_handler
//重复接收后
ngx_reusable_connection(c, 0); //连续请求,需要重用connection
ngx_http_init_request(rev);
3/n = recv(c->fd, buf, size, 0); n =515 c->fd = 9
4/ngx_http_init_request(rev); fd =9
5/ngx_del_timer(c->read);fd =9
6/c->write->handler = ngx_http_request_handler;
7/if (ngx_add_conn(c) == NGX_ERROR) {
8/rc = connect(s, pc->sockaddr, pc->socklen); s=10 rc=-1
9/c->write->handler = ngx_http_upstream_handler;
10/ngx_add_timer(c->write, u->conf->connect_timeout);//添加定时器
//把数据发送给后端服务器(写后端)
//第二次循环,//处理客户可写事件(特需处理才操作),向后端服务器发送请求关闭写操作事件
11/wev->handler(wev);
12/wev->handler = 0x445aaa
13/if (ev->write) {u->write_event_handler(r, u);
14/rc = writev(c->fd, header.elts, header.nelts);
15/ngx_del_timer(c->write);
16/ngx_add_timer(c->read, u->conf->read_timeout);
//读取后端服务器数据,写入客户端(读后端,写客户(读写))
//第三次循环 //读取后端服务器返回数据,向客户端发送数据信息(发送两次待查),再次接受客户端请求,如果有数据,可能走到第二次循环(待查)
17/events = epoll_wait(ep, event_list, (int) nevents, timer);//nevents为512,timer500毫秒
18/rev->handler = 0x445aaa
19/u->read_event_handler(r, u);
20/n = recv(c->fd, buf, size, 0);
21/rc = writev(c->fd, header.elts, header.nelts);
22/ngx_del_timer(c->read);
23/rc = writev(c->fd, header.elts, header.nelts);
ngx_del_conn(c, NGX_CLOSE_EVENT);//删除链接
24/ngx_add_timer(rev, clcf->keepalive_timeout);
25/n = recv(c->fd, buf, size, 0); //确定是否接受完,没完成设置事件,次循环处理
26/ngx_del_timer(c->read);
//出错发送默认错误页面
//第三次如果出错(什么情况会出错具体带查)
rev->handler(rev); //处理接收rev->handler = 0x445aaa
rc = writev(c->fd, header.elts, header.nelts);c->fd = 9 rc =20 //发送错误页面的头
rc = sendfile(c->fd, file->file->fd, &offset, file_size);c->fd = 9 rc = 20 //发送错误页面的体
ngx_del_conn(c, NGX_CLOSE_EVENT);//删除链接
ngx_add_timer(rev, clcf->keepalive_timeout);
n = recv(c->fd, buf, size, 0); n=-1 c->fd = 9 //这里确定是否有可接受的,如果有,重新添加事件
if (n == NGX_AGAIN) {
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
//请求链接url
//错误页面显示
JSP 2.0 Examples - Hello World SimpleTag Handler
This tag handler simply echos "Hello, World!" It's an example of a very basic SimpleTag handler with no body.
Result: Hello, world!
//总结
1、看上面的接收情况可以了解整个流程
2、虽然具体内容不是很了解,但是通过上面,您完全可以写出一个非http的,基于upstream的大并发服务器
3、如果不使用upstream的服务器,可以参考本人的文章“nginx 请求处理流程(非配置upstream)”,即可写出非upstream大并非服务器
//未解决问题:
1、什么情况会出错,然后转向发送错误页面?(可能有时间因素)
异常情况,不会发生后端服务器写的事件
" cl->buf->pos" = 0x0000000000725b50 202
HTTP/1.1 502 Bad Gateway\r\nServer: nginx/1.0.12\r\nDate: Wed, 06 Feb 2013 02:32:29 GMT\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 401\r\nConnection: keep-alive\r\n\r\n
400 Bad Request
400 Bad Request
nginx/1.0.12
2、服务器给客户端发送数据的时候,发送两次,具体什么情况?(可能是分头和体吧)
3、错误页面发送,发送后,具体是什么发送?(发送体是不是需要保存到一个临时文件,头比体数据大)
4、客户端转发请求前,是不是需要解析?
阅读(6764) | 评论(0) | 转发(0) |