从源码角度理解nginx配置中last与break的区别

nginx 配置文件中经常会用到last与break指令。那么两者之间的区别如何呢?

以nginx-1.0.14的源码为例:
/src/http/modules/ngx_http_rewrite_module.c (366-389行)

    
    
    
    
if  (cf ->args ->nelts  ==  4 )  {
if  (ngx_strcmp (value [ 3 ]. data ,  "last" )  ==  0 )  {
last  =  1 ;

}  else  if  (ngx_strcmp (value [ 3 ]. data ,  "break" )  ==  0 )  {
regex->break_cycle = 1;
last  =  1 ;

}  else  if  (ngx_strcmp (value [ 3 ]. data ,  "redirect" )  ==  0 )  {
regex ->status  = NGX_HTTP_MOVED_TEMPORARILY ;
regex ->redirect  =  1 ;
last  =  1 ;

}  else  if  (ngx_strcmp (value [ 3 ]. data ,  "permanent" )  ==  0 )  {
regex ->status  = NGX_HTTP_MOVED_PERMANENTLY ;
regex ->redirect  =  1 ;
last  =  1 ;

}  else  {
ngx_conf_log_error (NGX_LOG_EMERG , cf ,  0 ,
"invalid parameter \"%V\"" ,  &value [ 3 ] ) ;
return NGX_CONF_ERROR ;
}
}

break 与last的区别在于多了一行,regex->break_cycle = 1; 那么我们来看看这行语句具体有何含义。
break_cycle赋值后会被ngx_http_script_regex_code_t *code 调用。

具体在/src/http/ngx_http_script.c (1007行),代码段如下:

    
    
    
    
if  (code ->break_cycle )  {
r->valid_location = 0;
r->uri_changed = 0; 

}  else  {
r ->uri_changed  =  1 ;
}

r->valid_location = 0; 表示break指令不会继续作用于之后的location域。
r->uri_changed = 0;表示break指令停止继续匹配。而last指令会继续匹配下去。
继续看如下代码
/src/http/ngx_http_core_module.c(1038行)

    
    
    
    
ngx_http_core_post_rewrite_phase (ngx_http_request_t  *r ,
ngx_http_phase_handler_t  *ph )
{
ngx_http_core_srv_conf_t  *cscf ;

ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r ->connection -> log ,  0 ,
"post rewrite phase: %ui" , r ->phase_handler ) ;

if  ( !r ->uri_changed )  {
r ->phase_handler ++;
return NGX_AGAIN ;
}

r->uri_changed = 0; 内核会跳出处理下一个请求。
last指令 r->uri_changed = 1; 会继续不停的匹配。

总结:使用break指令后,不会继续作用于随后的location域,不会循环继续匹配。last指令恰恰相反。

从效率上来说尽量使用break指令。

你可能感兴趣的:(nginx,LNMP)