编写nginx的http模块需要注意一些细节

1,在申请buffer的时候需要注意这些buffer是用在哪里的,是需要从哪里去申请。
    在handler函数中,比如,一般申请buffer都是从ngx_http_request_t *r的r->pool中去申请。但是如果需要改变r->connection->addr_text.data的buffer,去申请更大的一块内存,那么,如果从r->pool申请,是会有问题,这个需要注意,在项目中刚开始没有注意,到时从r->pool中去申请内存,但是,access.log刷出来的信息,remote_ip 却不是ip字符串,也影响一些代码的操作。
如 u_char * addr_buf = ngx_pnalloc(r->connection->pool,r->connection->addr_text.len + 1 + sizeof(long));
ngx_memcpy(addr_buf,r->connection->addr_text.data,r->connection->addr_text.len);
addr_buf[r->connection->addr_text.len] = 0;
...



2.这个情况是我遇到的,可能放在另外一个环境就不会发生。
在使用ngx_http_output_filter(r,&out)发送content的时候
如果 out 有两个,那么,在组织的时候,
ngx_chain_t out1,out2;
ngx_buf_t *buf1,*buf2;
buf1 = ngx_pnalloc(..)
buf1->pos = ngx_pnalloc(..);
buf2 = ngx_pnalloc(..)
buf2->pos = ngx_pnalloc(..);
out1->buf = buf1;
out2->buf = buf2;
out2->next = NULL;
out1->next = &out2;
ngx_http_output_filter(r,&out1);
通过这个方式在发送2份content的时候,在copy filter阶段的ngx_output_chain_as_is这个函数内,检测是否content是否在文件中
并且采用directio方式的这个判断,会有段错误,因为out->file=NULL;
后来,将2个out弄成一个,数据都放到一个buf->pos里。
再测试时,还是偶尔会在上面说的地方发送段错误,因此考虑了下,我的数据是在buffer中,而不是在file中
因此设置下buf->in_file=0;之后就一切ok了。

3.自己实现的第三方模块,一般来说,主要是为了去处理请求,并生成内容,那么其实实质就是编写handler和将请求提交给自己实现的处理线程。
1)那么要注意的是,是在模块的上下文中的postconfiguration阶段去指定个函数,并在该函数
中去指定将这个handler是压在处理的哪个阶段,最近的项目用的是nginx的1.0.13这个版本,在该项目中,初期,我们是压的content阶段,但是,在handler处理内部要指定delay,一直进不去,后来改成了
preaccess阶段。关于指定不了content的原因,我以前在另外的一篇文章中有说到。
2)指定delay函数,在需要由自己定义的线程去处理,可能没有第一时间返回,那么我们就需要用到定时器,设置超时时间,在隔一段时间后再去访问是否处理好,这样可以不阻塞影响后面的请求处理。
//设置超时函数
r->write_event_handler = ngx_http_recommend_service_delay;
//设置定时器时间
ngx_add_timer(r->connection->write, (ngx_msec_t)DELAY_TIME);

4.处理线程的载入
这个毋庸置疑了,是在进程初始化阶段去初始化我们自己实现的处理线程。
为什么需要这个线程,我举个例子,比如分层架构,前端是web server 接受请求,后端是分布式redis组
那么这里,通过自己实现的处理线程去接受web server 接受到的请求,简单处理后提交给处理线程去到redis server组中取实际数据,这个过程可能不是立即完成。因此,就有上面说的一点,需要设置定时器。


最后,这篇文章中间隔了一段时间了,可能写的不是很流畅,以后再做到类似的项目时,在仔细编排编排,将各种要注意的细节全部整理下。

你可能感兴趣的:(技术分析,项目经验,nginx,redis)