设为首页 收藏本站
查看: 632|回复: 0

[经验分享] nginx脚本引擎与变量设计(一)

[复制链接]
发表于 2016-12-26 11:47:04 | 显示全部楼层 |阅读模式
  前言:
  本来的想法是写一个针对经典配置的情景分析,写到一半的时候就力不从心了,感觉很难给出一个完整全面的展示,主要是这块内容牵扯到整个系统的很多方面,比较复杂。所以就打算从一个有代表性的rewrite配置出发,讲一下在这个情景下,nginx的脚本引擎是如何工作的。
  nginx的脚本解析系统,虽然不能跟专业的脚本解析器相比,但是它的设计却是非常巧妙,而且抽象性很高。先大体说一下它的大体思路。
  设计思路:
  我们知道nginx在解析配置时,每次根据读出的配置信息都会查找相应模块的特定处理函数,而rewrite的配置一般都是要针对具体的url来做特定的处理,如正则匹配等等,所以不能在解析的时候不能像其他配置那样得到一个相对静态的配置信息。nginx的做法是,为每个配置设置一个后续处理所需要的结构体,结构体中包含了与该配置相关的重要信息,并设置相应的处理handler,之后在处理请求的某个阶段(主要REWRITE_PHASE,这方面的介绍可以参考其他博客,这里就不重复了),会集中对这些在解析时设置的处理handler做一个集中处理。
  在这个脚本引擎中,rewrite的处理或者其他使用使用脚本引擎的地方,都是通过ngx_http_script_engine_t结构体来驱动执行和保存执行结果的。我们通过下面这段代码来看一下,它的核心处理是怎么样的。

// sp是一个ngx_http_variable_value_t的数组,里面保存了从配置中分离出的一些变量
// 和一些中间结果,在当前处理中可以可以方便的拿到之前或者之后的变量(通过sp—
// 或者sp++)
e->sp = ngx_pcalloc(r->pool, rlcf->stack_size * sizeof(ngx_http_variable_value_t));
// 包含了在配置解析过程中设置的一些处理结构体,下面的rlcf->codes是一个数组,
// 注意的是,这些结构体的第一个成员就是一个处理handler,这里处理时,都会将该
// 结构体类型强转,拿到其处理handler,然后按照顺序依次执行之
e->ip = rlcf->codes->elts;
// 需要处理的请求
e->request = r;
// 初始时认为uri需要特殊处理,如做escape,或者urldecode处理。
e->quote = 1;
e->log = rlcf->log;
// 保存处理过程时可能出现的一些http response code,以便进行特定的处理
e->status = NGX_DECLINED;
// 依次对e->ip 数组中的不同结构进行处理,在处理时通过将当前结构进行强转,就
// 可以得到具体的处理handler,因为每个结构的第一个变量就是一个handler。我们看
// 的出来这些结构成员的设计都是有它的意图的。
while (*(uintptr_t *) e->ip) {
code = *(ngx_http_script_code_pt *) e->ip;
code(e);
}

  

  说了这些抽象的理论之后,下面给出一个具体的例子来更加形象的分析一下。

情景分析:
  这里我们以下面这个例子来看一下,在一个特定的rewrite情景下,nginx的脚本引擎是如何工作的:
  location / {
  if ($uri ~* "(.*).html$" ) {
  set $file $1;
  rewrite ^(.*)$ http://$http_host$file.mp4 break;
  }
  }
  我想对于这个示例配置,大家应该都知道它的作用,主要是将一个对html请求,通过302跳转,让客户端重新取一个同名的mp4文件(是不是很无聊-_-!)。
  这里通过一个图来展现在整个解析过程得到的结构及其相应的处理handler,然后我们再对一些重点的地方加以分析,对于具体的逻辑,大家可以自己看。
DSC0000.gif

  说明:
  1. 图中蓝色的部分是if行,它的解析主要通过ngx_http_rewrite_if,set和rewirte类推。
  2. 图中带有小圆圈的标记,是脚本引擎中处理handler的执行顺序,即前面的e->ip数组。
  接下来我们针对这个情景下的处理流程中的一些重点进行探讨。

重点探讨:
  (一) if行的解析
  1. 在解析if时, nginx会把它当做一个location来对待的,并且它的location type为noname。通过ngx_http_add_location将该“location”添加到上层的locations中。这里将if看做location自然有它的合理性,因为if的配置也是需要进行url匹配的。
  2. if中具体的解析通过ngx_http_rewrite_if_condition来实施。
  3. 在(1)的处理时,对于$uri,ngx_http_rewrite_variable 函数会进行处理。主要的工作是将当前的这个变量(即$uri),放到全局的变量数组中,并得到其下标。还有一点就是ngx_http_script_var_code_t结构中的index,这个用来记录该下标,这样后面用到的时候就可以很快的取到该变量。
  4. 为什么(2)没用设置结构体和handler呢?那是因为根据(2)的配置,就可以确定后面这个配置的处理方式了。所以这里不是每个分句都有对应的结构和handler的设置,能简单处理的,就可以捎带处理掉了,同理的还有像“break”等。
  配置中凡是出现‘~’的,都是属于正则的处理。这里提醒一点是带有‘*’的,是不区分大小写的。
  5. 这里先提一点相关的背景。较新的PCRE库中实现了perl和python中叫做named subpattern的东西,我们通常在引用一个pattern中的()部分时,通常使用$1,$2…等,这里的named subpattern是指在一个pattern使用类似(?<name>...)的形式,这样我们在引用这个()的内容是,就可以通过这个name来指定了,使用更加灵活。这里在(3)的处理的时候,会通过ngx_http_regex_compile函数来进行正则的编译,里面封装了一些PCRE正则库的一些API,相关的细节可以到官网http://www.pcre.org/中的document上查看。这里提一点的是,由于我们的情景中都是比较常规的正则表达式,所以与像named
subpattern之类的处理就先跳过,如rc->named_captures的处理,我们这里只关注rc->captures这个值,它是正则表达式里,出现的()的个数,这个数目在对于处理后面出现的$1,$2…等非常有用。
  在(3)的处理中关键的的其实就是为模式匹配提供信息,所以通过regex->test = 1来标记实际处理时应该采取的处理方式。
  下一篇我们将分析set指令和rewrite执行。望关注!
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-319702-1-1.html 上篇帖子: nginx中的output chain的处理(一) 下篇帖子: Nginx Location和rewrite配置总结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表