本文重点介绍push stream模块的构成,至于nginx如何启动、维护该模块不会详细阐述,以后有时间会做详细阐述。 
一、模块定义 
1.1.  模块配置

通用nginx模块的配置struct有三种,分别是main,server和location。本模块会涉及到main和location两个域的配置。名称分别为:ngx_http_push_stream_main_conf_t和ngx_http_push_stream_loc_conf_t.

具体模块配置请参考nginx官网:http://wiki.nginx.org/HttpPushStreamModule 
1.2.  模块指令 
  模块的指令是定义在一个叫做ngx_command_t的静态数组中的,或用于在nginx配置文件中设定模块的相关参数或处理相应请求,先简单来说下ngx_command_t的定义:

  1. struct ngx_command_t {
  2. ngx_str_t             name;//指令名称
  3. ngx_uint_t            type;//指令类型——该指令可用于ngx conf的哪个域——main?server?location?
  4. /*命令所对应的处理函数指针,参数
  5. @指向结构体 ngx_conf_t 的指针, 这个结构体里包含需要传递给指令的参数;
  6. @指向结构体 ngx_command_t 的指针;
  7. @指向模块自定义配置结构体的指针
  8. */
  9. char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  10. ngx_uint_t            conf;//指定参数存储区域(main?server?loc?)
  11. ngx_uint_t            offset;//指定数据保存位置
  12. void                 *post;//指向模块在读配置的时候需要的一些零碎变量
  13. };

比如:

  1. { ngx_string("push_stream_publisher"),
  2. NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,//指令用在location域,没有参数或1个参数
  3. ngx_http_push_stream_publisher,//发布处理函数
  4. NGX_HTTP_LOC_CONF_OFFSET,//参数存储在location域
  5. offsetof(ngx_http_push_stream_loc_conf_t, location_type),
  6. NULL },
  7. { ngx_string("push_stream_subscriber"),
  8. NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
  9. ngx_http_push_stream_subscriber,
  10. NGX_HTTP_LOC_CONF_OFFSET,
  11. offsetof(ngx_http_push_stream_loc_conf_t, location_type),
  12. NULL },

1.3.  模块上下文 
       静态的ngx_http_module_t结构体,包含一大坨函数引用,用来创建和合并三段配置 (main,server,location):

  1. static ngx_http_module_t    ngx_http_push_stream_module_ctx = {
  2. NULL,                                       /* preconfiguration */
  3. ngx_http_push_stream_postconfig,            /* postconfiguration */
  4. ngx_http_push_stream_create_main_conf,      /* create main configuration */
  5. ngx_http_push_stream_init_main_conf,        /* init main configuration */
  6. NULL,                                       /* create server configuration */
  7. NULL,                                       /* merge server configuration */
  8. ngx_http_push_stream_create_loc_conf,       /* create location configuration */
  9. ngx_http_push_stream_merge_loc_conf,        /* merge location configuration */
  10. };

1.4.  模块定义

  1. ngx_module_t    ngx_http_push_stream_module = {
  2. NGX_MODULE_V1,
  3. &ngx_http_push_stream_module_ctx,           /* module context */
  4. ngx_http_push_stream_commands,              /* module directives */
  5. NGX_HTTP_MODULE,                            /* module type */
  6. NULL,                                       /* init master */
  7. ngx_http_push_stream_init_module,           /* init module */
  8. ngx_http_push_stream_init_worker,           /* init process */
  9. NULL,                                       /* init thread */
  10. NULL,                                       /* exit thread */
  11. ngx_http_push_stream_exit_worker,           /* exit process */
  12. ngx_http_push_stream_exit_master,           /* exit master */
  13. NGX_MODULE_V1_PADDING
  14. };

二、初始化 
        由上文可以看出,nginx初始化时会调用ngx_http_push_stream_init_module和ngx_http_push_stream_init_worker两个函数,下面看下它们都干了什么 
2.1.  模块初始化(init_module)

  1. static ngx_int_t
  2. ngx_http_push_stream_init_module(ngx_cycle_t *cycle)
  3. {
  4. ngx_core_conf_t                         *ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module
  5. );
  6. if ((ngx_http_push_stream_module_main_conf == NULL) || !ngx_http_push_stream_module_main_conf->enabled) {
  7. ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "ngx_http_push_stream_module will not be used with this configu
  8. ration.");
  9. return NGX_OK;
  10. }
  11. // initialize our little IPC
  12. return ngx_http_push_stream_init_ipc(cycle, ccf->worker_processes);
  13. }

代码很简单

  • 获取conf
  • 初始化IPC

2.1.1 IPC 
       该模块的IPC是对nginx的master与worker间IPC的扩展,有关nginx的进程间通信请参见http://simohayha.iteye.com/blog/467940 
       简单来讲,master与worker直接的通信模型为:

  • master每次创建worker之前,创建一个channel(socketpair),fork后worker继承该socketpair
  • master保留所有worker的socketpair从而可以向所有worker发送控制指令。
  • worker继承socketpair时,仅保留master为自己创建的socketpair的读端以及master为其他worker创建的socketpair的写端,从而可实现worker间的进程间通信
  • 由于worker创建时序的不同,先创建的worker无法获悉后创建worker的chaneel信息,为此master每次创建channel后以将新创建的channel信息以指令的形式通知先前创建的worker

由于master为worker创建的channel(socketpair)只处理特定的指令,push stream模块创建了供自己使用的socketpair:

  • 模块初始化时为所有worker创建一个socketpair
  • master创建worker时,worker会完全继承由模块创建的socketpair读端与写端。
  • worker可借助由push stream模块创建的socketpair实现全双工通信

2.  ngx worker初始化(ngx_http_push_stream_init_worker)

nginx-push-stream模块源码学习(二)——模块初始化的更多相关文章

  1. vue 源码学习二 实例初始化和挂载过程

    vue 入口 从vue的构建过程可以知道,web环境下,入口文件在 src/platforms/web/entry-runtime-with-compiler.js(以Runtime + Compil ...

  2. Dubbo源码学习(二)

    @Adaptive注解 在上一篇ExtensionLoader的博客中记录了,有两种扩展点,一种是普通的扩展实现,另一种就是自适应的扩展点,即@Adaptive注解的实现类. @Documented ...

  3. Vue源码学习二 ———— Vue原型对象包装

    Vue原型对象的包装 在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式.在使用前都通过 new Vue({}).记录一下 Vue构造函数的包装. 在 src/core/in ...

  4. python 协程库gevent学习--gevent源码学习(二)

    在进行gevent源码学习一分析之后,我还对两个比较核心的问题抱有疑问: 1. gevent.Greenlet.join()以及他的list版本joinall()的原理和使用. 2. 关于在使用mon ...

  5. 以太坊 layer2: optimism 源码学习(二) 提现原理

    作者:林冠宏 / 指尖下的幽灵.转载者,请: 务必标明出处. 掘金:https://juejin.im/user/1785262612681997 博客:http://www.cnblogs.com/ ...

  6. Spring 源码学习 04:初始化容器与 DefaultListableBeanFactory

    前言 在前一篇文章:创建 IoC 容器的几种方式中,介绍了四种方式,这里以 AnnotationConfigApplicationContext 为例,跟进代码,看看 IoC 的启动流程. 入口 从 ...

  7. [spring源码学习]二、IOC源码——配置文件读取

    一.环境准备 对于学习源码来讲,拿到一大堆的代码,脑袋里肯定是嗡嗡的,所以从代码实例进行跟踪调试未尝不是一种好的办法,此处,我们准备了一个小例子: package com.zjl; public cl ...

  8. ngx-push-stream模块源码学习(五)——内存清理

    1.定时器         采用nginx自身的定时器管理机制,具体细节待学习过nginx源码后加以补充 2.channel的生成周期 (0).初始(诞生)         发布.订阅均有可能产生ch ...

  9. ngx-push-stream模块源码学习(四)——订阅

    一.概述 push stream模块允许三种模式的订阅者: longpolling:每收到服务端响应数据即断开连接然后迅速重连,连接耗时可以忽略 stream:与服务端保持长连接,持续不断的请求-&g ...

随机推荐

  1. TLD跟踪算法优化(一)并行化

    才学疏浅,仅仅言片语,仅仅求志同道的朋友一起交流研究. 并行化不算是算法的改进,仅仅是追求执行的实时性. 简要列举一个样例: TLD算法的C++版本号源代码里: LKTracker::trackf2f ...

  2. EF结合SqlBulkCopy

    EF结合SqlBulkCopy在项目中的使用 这是我第一次写博客,由于水平有限,写不出什么好东西,还望见谅. 我现在参与的这个项目采用的是EF框架,方便了数据库的访问.但在实际中,发现项目中导入市县E ...

  3. CRUD功能的JqGrid表格

    CRUD功能的JqGrid表格 之前的项目也曾用过JgGrid对它的基本功能也是略有了解,网上有个国外的开源的项目,但是不适合个人的风格,所以花了3天空余的时间封装了下JqGrid,也算是参加开发工作 ...

  4. 第4章2节《MonkeyRunner源码剖析》ADB协议及服务: ADB服务SERVICES.TXT翻译参考(原创)

    天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在 ...

  5. 学习Easyui

    学习Easyui 社区easyui 论坛:http://bbs.jeasyuicn.com API地址:http://www.jeasyuicn.com/api 简单桌面版:http://app.bt ...

  6. 设计模式---订阅发布模式(Subscribe/Publish)

    设计模式---订阅发布模式(Subscribe/Publish) 订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有订阅者对象,使 ...

  7. 经常使用Javascript CDN 对照

    [前言] 请参阅某种网上文章: http://c7sky.com/javascript-libraries-cdn.html 本文加入的各个cdn对一些库的更新情况.以及响应时间. [更新] 发表文章 ...

  8. CSS边框阴影效果

    ul { margin:5px 0 0 0; padding:0; list-style:none; width:300px; background:#f1f1f1; }li { border-lef ...

  9. 使用Windows2003创建DNS服务器 - 进阶者系列 - 学习者系列文章

    Windows 2003的DNS服务器的配置还是比较简单的.下面简要介绍下DNS服务器的配置. 1.    打开控制面板,选择 添加删除Windows组件,选择 网络服务 ,选择 详细信息,选择 域名 ...

  10. .NET Reflector 7.6.1.824安装及破解(刚试了,绝对能用)

    首先下载在这里http://download.csdn.net/detail/gattaca2011/4578752,不要到官网去了,由于官网已经是8.0了. 然后就是安装,执行注冊机(注意断网),详 ...