Nginx启动初始化过程(转载)

main函数做的第一件事情就是对参数选项进行处理,和普通的Linux程序如出一辙,如下:

if (ngx_get_options(argc, argv) != NGX_OK) { return 1; }

Nginx用此函数对参数选项进行解析,从而采取相应的动作,比如:显示版本、测试配置等功能。其实此函数实现的很简陋,远没有Linux提供的getopt()那么强悍,但却可以达到跨平台的目的。

     ngx_time_init();
#if (NGX_PCRE)
    ngx_regex_init();
#endif
    ngx_pid = ngx_getpid();
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

上述几行代码的功能如其名,主要完成Nginx在时间和日志等方面的初始化工作。

    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK){
        return 1;
    }

将命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv这几个全局的变量中。这算是一个备份存储,方便以后master进程做热代码替换之用。

     if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

完成操作系统的一些信息获取,如内存页面大小、系统限制资源等信息;所有的这些资源都将会被保存在对应的全局变量中,因此后续访问将会很便利。

    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

初始化一个做循环冗余校验的表,由此可以看出后续的循环冗余校验将采用高效的查表法。crc算法此处就不做分析,网上一堆一堆的相关资料,有兴趣的同学可以了解。

    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。在NGINX环境变量中,每个socket中间用冒号或分号隔开。完成继承同时设置全局变量ngx_inherited为1。

    ngx_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = ngx_max_module++;
    }

额!!!这个循环中的ngx_modules数组好像没见定义,难不成是火星来的?当然不是,如其名,这就是一个存储所有模块的信息,包括自己开发的模块都会放到这个数组中,而这个神秘的数组却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中。这个循环的目的是清晰可见的——对所有模块进行索引编号,方便以后访问;同时借助ngx_max_module对所有模块进行了一次点数,确定究竟有多少模块。而神秘数组ngx_modules的长相大概如下:

ngx_module_t *ngx_modules[] = {
    &ngx_core_module,
    &ngx_errlog_module,
    &ngx_conf_module,
    &ngx_events_module,
    &ngx_event_core_module,
    &ngx_epoll_module,
    &ngx_openssl_module,
    &ngx_http_module,
    。。。
};
    cycle = ngx_init_cycle(&init_cycle);

这里将会初始化很多的东东到全局变量cycle中,是Nginx启动初始化的核心之处。ngx_init_cycle函数的过程比较多,放下一篇blog中逐段分析。

    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

注册一堆信号处理程序,需要注册的信号及相应的信号处理函数被放在一个类型为ngx_signal_t的数组signals中。数组定义在src/os/unix/ngx_process.c中。ngx_signal_t结构类型定义了信号值,信号名字,信号对应动作名以及信号处理函数。

     if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }
        ngx_daemonized = 1;
    }

ngx_daemon肯定就是用来实现守护进程的函数了,此处就不多废话了,有需要写server程序的,可以直接copy这段代码实现守护进程。

    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

玩过Nginx的人都知道,Nginx启动后有一个记录进程id的文件,这个文件里面就一个pid。原来这个pid就是在这个地方记录下来的。查看ngx_create_pidfile函数可以看到这样的一行代码

if (ngx_process > NGX_PROCESS_MASTER) {
return NGX_OK;
},这行代码就说明了,不是master进程时,就不创建这样的一个pid文件。

    if (ngx_process == NGX_PROCESS_SINGLE) {
        ngx_single_process_cycle(cycle);
    } else {
        ngx_master_process_cycle(cycle);
    }

到此就基本完成Nginx的启动初始化过程了,即将开始进程相关的工作了,这里最重要的ngx_master_process_cycle这个过程,在这个过程里实现了master-worker模式的进程模型,也是生成环境下Nginx的常用模型。既然此处已不再是初始化工作,那么就留到后续分析吧。

上述所有过程都是在main函数里完成的,下一篇分析ngx_init_cycle函数。

From: http://www.tbdata.org/archives/1092

顽皮的小男孩

广岛原子弹事件是指1945年8月6日美国在日本广岛投掷原子弹。1945 年夏,日本败局已定。美国总统杜鲁门和美国政府想尽快迫使日本投降,也想以此抑制苏联,选定日本东京、京都、广岛、长崎、小仓、新潟等城市作为投掷原子弹的备选目标。此前,美国、英国和中国发表了《波茨坦公告》,敦促日本投降。7月28日,日本政府拒绝接受《波茨坦公告》。8月6日和9日美军对日本广岛和长崎投掷原子弹。

章鱼变身记

╭( ▔▽▔)╮变章鱼!

╭( ▔▽▔)╯要开始了~

╰( ≧﹏≦)╯恩……

( ▔◎▔) 喔耶~~厉害吧
╱│││╲

(∥▔◎▔)  喔…
╱│││╲

(∥= ◎ = ) 喔 ,变不回去了…
╱│││╲

Adobe FMS Open File

这边有个需求是替换adobe fms 热点文件的时候防止删除正在访问的文件,保证用户请求不中断

但是发现adobe fms open的文件lsof看不到,但是iostat能证实该磁盘是在读取的,很奇怪

尝试用inotify去捕捉事件,可以发现:

[@dg_80_65 inotify-tools-3.14]# inotifywait -m  \
 --timefmt  '%d/%m/%y %H:%M' --format  '%T %e %w%f'  \
/data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
Setting up watches.
Watches established.
01/11/10 18:37 OPEN /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 CLOSE_NOWRITE,CLOSE /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 OPEN /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:37 CLOSE_NOWRITE,CLOSE /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 OPEN /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 CLOSE_NOWRITE,CLOSE /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 OPEN /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 ACCESS /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4
01/11/10 18:38 CLOSE_NOWRITE,CLOSE /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4

所有文件迅速的打开,读取,关闭,所以lsof捕捉不到

adobe的文档是这么说的:

When a stream is requested from the server, segments of the stream are stored in a cache on the server. As long as the cache has not reached capacity, the server places segments in the cache. Each time a stream attempts to access a segment, the server checks the cache. If the segment is available, the server gives the stream a reference to the segment for playback. If the segment is not available, the server retrieves the segment from its source, inserts it into the cache, and returns a reference to that segment to the stream.
When the cache is full, the server removes unused segments, starting with the least recently used. After removing all unused segments, if there still isn’t enough room for a new segment, the server notifies the client that the stream is not available and makes an entry in the core log file.

When a stream is requested from the server, segments of the stream are stored in a cache on the server. As long as the cache has not reached capacity, the server places segments in the cache. Each time a stream attempts to access a segment, the server checks the cache. If the segment is available, the server gives the stream a reference to the segment for playback. If the segment is not available, the server retrieves the segment from its source, inserts it into the cache, and returns a reference to that segment to the stream.
When the cache is full, the server removes unused segments, starting with the least recently used. After removing all unused segments, if there still isn’t enough room for a new segment, the server notifies the client that the stream is not available and makes an entry in the core log file.

大意是说fms是从缓存区取文件的,如果不存在该文件的这一部分,就会从源文件读取,放入缓存区,再给用户

因此,比较可以接受的办法是删除文件之前判断下access time的时间戳

stat -c %X /data/video/ssdcached/stream/20100525/57d4f5a6-fc8d-4f8f-b0f7-c00020f6c7ac.mp4

双网卡bond 配置

最近公司的服务器配置做了更改,LVS+双公网策略路由出了问题,所以干脆改成bonding来做

bonding的各种模式:

按照卢瑟同学的介绍,bonding有7种模式:

Mode=0(balance-rr) 表示负载分担round-robin,和交换机的聚合强制不协商的方式配合。
Mode=1(active-backup) 表示主备模式,只有一块网卡是active,另外一块是备的standby
这时如果交换机配的是捆绑,将不能正常工作,因为交换机往两块网卡发包,有一半包是丢弃的。
Mode=2(balance-xor) 表示XOR Hash负载分担,和交换机的聚合强制不协商方式配合。(需要xmit_hash_policy)
Mode=3(broadcast) 表示所有包从所有interface发出,这个不均衡,只有冗余机制...和交换机的聚合强制不协商方式配合。
Mode=4(802.3ad) 表示支持802.3ad协议,和交换机的聚合LACP方式配合(需要xmit_hash_policy)
Mode=5(balance-tlb) 是根据每个slave的负载情况选择slave进行发送,接收时使用当前轮到的slave
Mode=6(balance-alb) 在5的tlb基础上增加了rlb。
5和6不需要交换机端的设置,网卡能自动聚合。4需要支持802.3ad。0,2和3理论上需要静态聚合方式
但实测中0可以通过mac地址欺骗的方式在交换机不设置的情况下不太均衡地进行接收。

决定使用最简单的模式6来做

bonding的配置

modprobe.conf

在这个文件加入

alias bond0 bonding
options bond0 miimon=100 mode=5

网卡配置文件修改

ifcfg-eth1

DEVICE=eth1
USERCTL=no
ONBOOT=yes
MASTER=bond0
SLAVE=yes
BOOTPROTO=none

ifcfg-eth2

DEVICE=eth2
USERCTL=no
ONBOOT=yes
MASTER=bond0
SLAVE=yes
BOOTPROTO=none

ifcfg-bond0

DEVICE=bond0
IPADDR="Your IP Adress"
NETMASK="Your NetMask"
ONBOOT=yes
BOOTPROTO=none
USERCTL=no

变更修改

/etc/init.d/network stop;modprobe -r bonding;/etc/init.d/network start

附录:转发方式

layer2 (1): (source MAC XOR destination MAC) modulo slave count
layer2+3 (2): (((source IP XOR dest IP) AND 0xffff) XOR ( source MAC XOR destination MAC )) modulo slave count
layer3+4 (3): ((source port XOR dest port) XOR ((source IP XOR dest IP) AND 0xffff) modulo slave count
为了能更加均衡,可采用 mac ip 异或 哈希:xmit_hash_policy=2