存档

‘nginx’ 分类的存档

nginx least_conn 模块源码剖析

2012年7月11日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx least_conn 模块源码剖析

nginx在1.3.1添加了一个新模块 least_conn,也就是我们常说的最少连接负载均衡算法,简单来说就是每次选择的都是当前最少连接的一个server(这个最少连接不是全局的,是每个进程都有自己的一个统计列表)。

在看最少连接模块之前需要对round robin模块有一定的了解,这里我就不对round robin模块进行分析了,想要看这块代码,可以去我们组 卫岳的blog的这篇文章
http://blog.sina.com.cn/s/blog_7303a1dc01014i0j.html

ok,接下来就来看这个模块,首先来看如何打开least_conn模块:

static ngx_command_t  ngx_http_upstream_least_conn_commands[] = {

    { ngx_string("least_conn"),
      NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
      ngx_http_upstream_least_conn,
      0,
      0,
      NULL },

      ngx_null_command
};

阅读全文…

Share

Nginx配置文件解析详解

2012年4月28日 1 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: Nginx配置文件解析详解

Nginx的配置解析相关的部分比较绕,比如为何要有4重指针,比如NGX_MAIN_CONF , loc_conf,NGX_DIRECT_CONF有什么区别呢?这些我前面的blog都有些涉及,这次主要是把配置这块完全拿出来然后来分析下。

首先来看配置解析时的数据结构,这里主要是ngx_conf_t,这个结构保存了解析配置文件所需要的一些域,这个是非常重要的一个数据结构,我们详细来看这个结构:

struct ngx_conf_s {
//当前解析到的命令名
    char                 *name;
//当前命令的所有参数
    ngx_array_t          *args;

//使用的cycle
    ngx_cycle_t          *cycle;
//所使用的内存池
    ngx_pool_t           *pool;
//这个pool将会在配置解析完毕后释放。
    ngx_pool_t           *temp_pool;
//这个表示将要解析的配置文件
    ngx_conf_file_t      *conf_file;
//配置log
    ngx_log_t            *log;

//主要为了提供模块的层次化(后续会详细介绍)
    void                 *ctx;
//模块类型
    ngx_uint_t            module_type;
//命令类型
    ngx_uint_t            cmd_type;

//模块自定义的handler
    ngx_conf_handler_pt   handler;
//自定义handler的conf
    char                 *handler_conf;
};

阅读全文…

Share

nginx中cache的设计和实现(一)

2012年3月21日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx中cache的设计和实现(一)

Nginx的cache实现比较简单,没有使用内存,全部都是使用文件来对后端的response进行cache,因此nginx相比varnish以及squid之类的专门做cache的server,可能效果不会那么好。特别如果cache内容比较大的话。不过还有一种折衷的处理,那就是挂载一个内存盘,然后让nginx cache到这个盘。

我这里的看的代码是1.1.17.

首先来看Nginx中如何开启cache,http cache主要是应用在upstream中的,因此upstream对应的两个命令来启用cache,一个是xxx_cache_path(比如proxy_cache_path),它主要是用来创建管理cache的共享内存数据结构(红黑树和队列).一个是xxx_cache,它主要是使用前面创建的zone。

先来看第一个命令,xxx_cache_path,它会调用ngx_http_file_cache_set_slot函数,在看这个函数之前,先来看ngx_http_file_cache_t这个数据结构,它主要用来管理所有的cache文件,它本身不保存cache,只是保存管理cache的数据结构。每一个xxx_cache_path都会创建一个ngx_http_file_cache_t.
阅读全文…

Share
分类: nginx, server 标签: , ,

nginx的upstream分享

2012年1月5日 2 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx的upstream分享

今天给同事做的分享.

Share
分类: nginx, server 标签:

nginx中upstream的设计和实现(五)

2011年8月17日 2 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx中upstream的设计和实现(五)

这次主要来分析upstream中的发送数据给client, 以及当buf不足,将一部分写到temp file的部分,他们对应的函数分别是ngx_event_pipe_write_to_downstream和ngx_event_pipe_write_chain_to_temp_file.

先来看ngx_event_pipe_write_to_downstream,这个函数顾名思义,就是写buf到临时文件。而所写的buf就是p->in,也就是将要发送给client的数据。
这个函数,它会处理两类的情况,一类是cache打开,一类是cache未打开。我们这里主要来分析cache关闭的情况。

首先来看这个函数的第一部分的代码,这部分代码主要是遍历p->in,然后计算能写多少buf到文件(temp file的size是有限制的).

//out就是将要保存到file的数据
    if (p->buf_to_file) {
//cache打开的情况
        fl.buf = p->buf_to_file;
        fl.next = p->in;
        out = &fl;

    } else {
//得到数据
        out = p->in;
    }
//如果cache没有打开
    if (!p->cacheable) {

        size = 0;
        cl = out;
        ll = NULL;

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0,
                       "pipe offset: %O", p->temp_file->offset);
//开始遍历out
        do {
//计算大小
            bsize = cl->buf->last - cl->buf->pos;
.....................................................
//看是否超过限制限制
            if ((size + bsize > p->temp_file_write_size)
               || (p->temp_file->offset + size + bsize > p->max_temp_file_size))
            {
                break;
            }

            size += bsize;
            ll = &cl->next;
            cl = cl->next;

        } while (cl);

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "size: %z", size);

        if (ll == NULL) {
            return NGX_BUSY;
        }
//cl存在则说明只有一部分buf能够写入到temp file,此时p->in保存剩下的chain
        if (cl) {
           p->in = cl;
           *ll = NULL;

        } else {
//否则说明所有的buf都写入到了temp file,此时p->in则设置为空
           p->in = NULL;
           p->last_in = &p->in;
        }

    } else {
//cache打开的情况,可以看到和上面类似.
        p->in = NULL;
        p->last_in = &p->in;
    }

阅读全文…

Share
分类: nginx, server 标签: , ,

nginx中upstream的设计和实现(四)

2011年8月6日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx中upstream的设计和实现(四)

这此主要是分析发送数据到客户端的部分以及buffering状态下,nginx接收upstream数据的部分,这也是upstream的最复杂的部分,这里我还是忽略了cache部分,以后我会专门写blog来分析nginx的cache部分。

这部分的函数入口是ngx_http_upstream_send_response,这里有一个很重要的标记,那就是u->buffering,这个标记的含义就是nginx是否会尽可能多的读取upstream的数据。如果关闭,则就是一个同步的发送,也就是接收多少,发送给客户端多少。默认这个是打开的。也就是nginx会buf住upstream发送的数据。

不管buffering是否打开,后端发送的头都不会被buffer,首先会发送header,然后才是body的发送,而body的发送就需要区分buffering选项了。如下图所示:

upstream_ac
阅读全文…

Share
分类: nginx, server 标签:

nginx fastcgi模块的一个bug

2011年6月1日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx fastcgi模块的一个bug

上周服务器更新到nginx的0.8.X之后,nginx出现了core dump的情况,而在0.7.X并不会出现,通过察看core dump文件以及nginx 0.8.x和0.7.x的比较,发现core dump是nginx 0.8.40引入下面这个feature才导致的:

*) Feature: a “fastcgi_param” directive with value starting with
“HTTP_” overrides a client request header line.

在nginx 0.8.40之后,如果你的fastcgi_param定义的变量以HTTP_开头,则传递给后端的头会忽略request header中的这个头,比如定义了一个 fastcgi_param $HTTP_HOST test, 那么传递给后端时,host这个头的值就是test.

这里的逻辑是这样子的,当nginx创建一个fastcgi request的时候,会先计算所需要的长度,首先是计算header的长度,在计算之前会先分配一个ignored数组(用来保存将要被忽略的头),它的大小是配置文件中fastcgi_param定义的以HTTP_开头的变量的个数. 然后遍历所有的request header,如果发现header的名字和fastcgi_param中定义的变量的(HTTP_开头)名字相同(使用hash),则将这个header指针放到ignored数组中,最后在拷贝request header的时候直接在这个数组里面查找,如果有则跳过,否则拷贝头以及它的值。

看起来没什么问题,可是这里忽略了request header有可能会有重复的这个情况,此时ignored数组可能就会越界,从而导致core dump.

阅读全文…

Share
分类: nginx, server 标签:

nginx中upstream的设计和实现(三)

2011年4月27日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx中upstream的设计和实现(三)

这次主要来分析当upstream发送过来数据之后,nginx是如何来处理。不过这里我忽略了cache部分,以后我会专门来分析nginx的cache部分。

在前面blog我们能得知upstream端的读回调函数是ngx_http_upstream_process_header,因此这次我们就从ngx_http_upstream_process_header的分析开始。

下面是ngx_http_upstream_process_header执行的流程图.

upstream_process_header

阅读全文…

Share
分类: nginx, server 标签:

nginx中upstream的设计和实现(二)

2011年4月14日 没有评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx中upstream的设计和实现(二)

这次主要来看upstream的几个相关的hook函数。

首先要知道,对于upstream,同时有两个连接,一个时client和nginx,一个是nginx和upstream,这个时候就会有两个回调,然后上篇blog中,我们能看到在upstream中,会改变read_event_handler和write_event_handler,不过这里有三个条件,分别是
1 没有使用cache,
2 不忽略client的提前终止
3 不是post_action

//条件赋值
    if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
//然后给读写handler赋值
        r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
        r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
    }

阅读全文…

Share

nginx中upstream的设计和实现(一)

2011年4月8日 8 条评论

原创文章,转载请注明: 转载自pagefault

本文链接地址: nginx中upstream的设计和实现(一)

在nginx的模块中,分为3种类型,分别是handler,filter和upstream,其中upstream可以看做一种特殊的handler,它主要用来实现和后端另外的服务器(php/jboss等)进行通信,由于在nginx中全部都是使用非阻塞,并且是一个流式的处理,所以upstream的实现很复杂,接下来我会通过几篇blog来详细的分析下nginx中upstream的设计和实现。

upstream顾名思义,真正产生内容的地方在”上游”而不是nginx,也就是说nginx是位于client和后端的upstream之间的桥梁,在这种情况下,一个upstream需要做的事情主要有2个,第一个是当client发送http请求过来之后,需要创建一个到后端upstream的请求。第二个是当后端发送数据过来之后,需要将后端upstream的数据再次发送给client.接下来会看到,我们编写一个upstream模块,最主要也是这两个hook方法。

首先来看如果我们要写一个upstream模块的话,大体的步骤是什么,我们以memcached模块为例子,我们会看到如果我们自己编写upstream模块的话,只需要编写upstream需要的一些hook函数,然后挂载到upstream上就可以了。
阅读全文…

Share
分类: nginx, server, 源码阅读 标签: