nginx做为HTTP服务器,有以下几项基本特性:
处理静态文件,索引文件以及自动索引;打开文件描述符缓冲.
无缓存的反向代理加速,简单的负载均衡和容错.
FastCGI,简单的负载均衡和容错.
模块化的结构。包括gzipping, byte ranges, chunked responses,以及 SSI-filter等filter。如果由FastCGI或其它代理服务器处理单页中存在的多个SSI,则这项处理可以并行运行,而不需要相互等待。
支持SSL 和 TLSSNI.
Nginx专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率。它支持内核 epoll、kqueue 等高性能并发模型,能经受高负载的考验。
Nginx具有很高的稳定性。其它HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失去响 应,只能重启服务器。例如当前apache一旦上到200个以上进程,web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术,使得它的 CPU与内存占用率非常低。nginx官方表示保持10,000个没有活动的连接,它只占2.5M内存,所以类似DOS这样的攻击对nginx来说基本上 是毫无用处的。就稳定性而言,nginx比lighthttpd更胜一筹。
Nginx支持热部署。它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。
Nginx采用master-slave模型,能够充分利用SMP的优势,且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时,还可以限制每个进程的连接数。
Nginx代码质量非常高,代码很规范,手法成熟, 模块扩展也很容易。特别值得一提的是强大的Upstream与Filter链。 Upstream为诸如reverse proxy,与其他服务器通信模块的编写奠定了很好的基础。而Filter链最酷的部分就是各个filter不必等待前一个filter执行完毕。它可以 把前一个filter的输出做为当前filter的输入,这有点像Unix的管线。这意味着,一个模块可以开始压缩从后端服务器发送过来的请求,且可以在 模块接收完后端服务器的整个请求之前把压缩流转向客户端。
当然,nginx还很年轻,多多少少存在一些问题,比如:Nginx是俄罗斯人创建,目前文档方面还不是很完善.因为文档大多是俄语,所以文档方面这也是个障碍.尽管nignx的模块比较多,但它们还不够完善。对脚本的支持力度不够。
|
这里我们下载了 nginx-1.0.0 的源码,然后准备开发一个 module_dev_urlquery 的module嵌入到nginx中
|
typedef struct { } ngx_http_p2s_conf_t; static char *ngx_http_p2s_urlquery_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void *ngx_http_p2s_create_conf(ngx_conf_t *cf); static uint8_t* get_raw_http_body( ngx_http_request_t* r, size_t* body_len ); static ngx_command_t ngx_http_p2s_commands[] = { ngx_string("p2s_urlquery"), //The command name, it MUST BE the same as nginx.conf location block's command NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ngx_null_command static ngx_http_module_t ngx_http_p2s_module_ctx = NULL, /* create main configuration */ NULL, /* create server configuration */ ngx_http_p2s_create_conf, /* create location configration */ ngx_module_t ngx_http_p2s_module = /** ngx_buf_t* buf = NULL; if ( r->headers_in.content_length == NULL ) // malloc space for data_buf content_length = atoi( (char*)(r->headers_in.content_length->value.data) ); data_buf = ( uint8_t* )ngx_palloc( r->pool , content_length + 1 ); size_t buf_length = 0; while ( bufs ) bufs = bufs->next; buf_length = buf->last - buf->pos ; if( *body_len + buf_length > content_length ) memcpy( data_buf + *body_len, buf->pos, content_length - *body_len ); break; memcpy( data_buf + *body_len, buf->pos, buf->last - buf->pos ); if ( *body_len ) return data_buf; /** ngx_http_p2s_conf_t *conf = NULL; struct timeval tv; /* Prepare for output, 128 is preserved for robust */ b->last = ngx_sprintf(b->pos, "%s", conf->ini_buf); r->headers_out.status = NGX_HTTP_OK; b->last_buf = 1;/* there will be no more buffers in the request */ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) ngx_http_output_filter(r, &out); /** return NGX_DONE; /** clcf = (ngx_http_core_loc_conf_t *)ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); return NGX_CONF_OK; static void * conf = (ngx_http_p2s_conf_t *)ngx_pcalloc(cf->pool, sizeof(ngx_http_p2s_conf_t)); conf->consume = 0; /* we open the nginx config file and send it back to client*/ fseek(fp, 0, SEEK_END); return conf; |
|
第一次错误,我们现在这个freebsd系统上没有pcre库,太悲催了,不过还好,这里给出了提示,说可以通过 --without-http_rewrite_module 来禁用使用pcre库的 HTTP rewrite 模块,我们试一试:
|
重点看到上面几行信息,说明我们自己写的模块module_dev_urlquery已经被nginx接纳,生成makefile成功。
|
默认的配置文件是下面(将‘#’开头的注释行删除之后)
|
我们在最上面添加如下选项:daemon off; 可以让程序不以daemon的方式运行,这样我们可以看到一些调试的打印信息。
另外,在 server 里面添加一个 URI :
location /urlquery {
p2s_urlquery;
}
最后,我们修改下http监听的端口号,从默认的80改为8088,因为有些时候,我们并没有权限在80端口上监听连接。
修改之后的配置文件全文如下:
|
好了,到此为止,我们的所有工作就都准备好了,可以启动nginx
|
新开一个终端,用curl来发起一个http post请求,post数据由-d参数指定:
http { |
然后可以看看nginx服务器的一些输出信息:
|
ngx_null_command nginx.conf 中的 location 字段的配置是这样的: |
|
NULL, /* create main configuration */ NULL, /* create server configuration */ ngx_http_p2s_create_conf, /* create location configration */ |
到此,我们完成了一个很简单的模块的开发和调试工作,也不是那么困难。
同时对一些函数调用,配置文件关系等等比较含糊的地方做了详细说明。