zoukankan      html  css  js  c++  java
  • Nginx http filter异常排查

    问题:

    • 访问异常
    root@cloud:/usr/local/nginx# curl -i http://localhost/test.html
    curl: (52) Empty reply from server
    
    • 错误日志
    2016/09/11 13:17:03 [alert] 63560#0: worker process 63663 exited on signal 11 (core dumped)
    
    • dmesg信息
    [265950.220943] nginx[63663]: segfault at 128 ip 000000000048259d sp 00007ffde898eab0 error 4 in nginx[400000+a5000]
    
    • core dump设置
      默认Worker进程用户nobody:nogroup,无法写coredump. 需在nginx.conf配置:
    worker_rlimit_core 1024m; #1G
    working_directory /tmp/core #保证nobody:nogroup有W权限
    

    执行"sbin/nginx -s reload"重新加载配置。

    • core dump分析
    • 使用readelf工具
      core dump是ELF格式文件,你可以用readelf -a 查看core dump文件,但哪只是一堆数据。
    • 使用gdb工具
    gdb <command> <core>
    

    一般会直接显示出错的代码位置

    • 位置1
      conf = ngx_http_conf_get_module_loc_conf(r,ngx_http_myfilter_module); #应该是ngx_http_get_module_loc_conf(...)
      
    • 位置2
      myfilter_ctx_t *ctx;
      ctx = ngx_http_get_module_ctx(r, ngx_http_myfilter_module);
      if (ctx->add_prefix != 1) { 应该先判断ctx == NULL
      	return next_body_filter(r, in);
      }
      

    Nginx http filter示例源码

    ngx_addon_name=ngx_http_myfilter_module
    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_myfilter_module"
    NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_myfilter_module.c"
    
    #include <ngx_config.h>
    #include <ngx_core.h>
    #include <ngx_http.h>
    
    static ngx_str_t filter_prefix = ngx_string("[my filter prefix]");
    static ngx_http_output_header_filter_pt next_header_filter;
    static ngx_http_output_body_filter_pt next_body_filter;
    
    typedef struct {
    	ngx_flag_t enable;
    } myfilter_conf_t;
    
    typedef struct {
    	ngx_int_t add_prefix;
    } myfilter_ctx_t;
    
    static ngx_int_t myfilter_header_filter(ngx_http_request_t *r);
    static ngx_int_t myfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in);
    static ngx_int_t myfilter_init(ngx_conf_t *cf);
    
    static void *myfilter_create_loc_conf(ngx_conf_t *cf);
    static char *myfilter_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
    
    static ngx_http_module_t myfilter_conf = {
    	NULL,
    	myfilter_init,
    	NULL,
    	NULL,
    	NULL,
    	NULL,
    	myfilter_create_loc_conf,
    	myfilter_merge_loc_conf
    };
    
    static ngx_command_t myfilter_commands[] = {
    	{
    		ngx_string("add_prefix"),
    		NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
    		ngx_conf_set_flag_slot,
    		NGX_HTTP_LOC_CONF_OFFSET,
    		offsetof(myfilter_conf_t, enable),
    		NULL
    	},
    	ngx_null_command
    };
    
    ngx_module_t ngx_http_myfilter_module = {
    	NGX_MODULE_V1,
    	&myfilter_conf,
    	myfilter_commands,
    	NGX_HTTP_MODULE,
    	NULL,
    	NULL,
    	NULL,
    	NULL,
    	NULL,
    	NULL,
    	NULL,
    	NGX_MODULE_V1_PADDING
    };
    
    static ngx_int_t myfilter_init(ngx_conf_t *cf){
    	next_header_filter = ngx_http_top_header_filter;
    	next_body_filter = ngx_http_top_body_filter;
    
    	ngx_http_top_header_filter = myfilter_header_filter;
    	ngx_http_top_body_filter = myfilter_body_filter;
    
    	return NGX_OK;
    }
    
    static ngx_int_t myfilter_header_filter(ngx_http_request_t *r){
    	myfilter_conf_t *conf;
    	myfilter_ctx_t *ctx;
    
    	if(r->headers_out.status != NGX_HTTP_OK){
    		return next_header_filter(r);
    	}
    
    	ctx = ngx_http_get_module_ctx(r, ngx_http_myfilter_module);
    	if(ctx){
    		return next_header_filter(r);
    	}
    
    	conf = ngx_http_get_module_loc_conf(r,ngx_http_myfilter_module);
    	if(conf == NULL || conf->enable == 0){
    		return next_header_filter(r);
    	}
    
    	ctx = ngx_pcalloc(r->pool, sizeof(myfilter_ctx_t));
    	if(ctx == NULL){
    		return NGX_ERROR;
    	}
    	ctx->add_prefix = 0;
    	ngx_http_set_ctx(r, ctx, ngx_http_myfilter_module);
    
    	r->headers_out.status = NGX_HTTP_MOVED_TEMPORARILY;
    	ngx_str_t keys = ngx_string("Location");
    	ngx_str_t vals = ngx_string("http://www.163.com");
    	ngx_table_elt_t *headers = ngx_list_push(&r->headers_out.headers);
    	if(headers){
    		headers->key.data = keys.data;
    		headers->key.len = keys.len;
    		headers->value.data = vals.data;
    		headers->value.len = vals.len;
    		headers->hash = 1;
    	}
    
    //	if (r->headers_out.content_type.len >= sizeof("text/plain") - 1
    //			&& ngx_strncasecmp(r->headers_out.content_type.data,
    //					(u_char *) "text/plain", sizeof("text/plain") - 1) == 0) {
    		ctx->add_prefix = 1;
    		if(r->headers_out.content_length_n > 0){
    			r->headers_out.content_length_n += filter_prefix.len;
    		}
    //	}
    
    	return next_header_filter(r);
    }
    
    static ngx_int_t myfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in) {
    	myfilter_ctx_t *ctx;
    	ctx = ngx_http_get_module_ctx(r, ngx_http_myfilter_module);
    	if (ctx == NULL || ctx->add_prefix != 1) {
    		return next_body_filter(r, in);
    	}
    
    	ctx->add_prefix = 2;
    	ngx_buf_t *b = ngx_create_temp_buf(r->pool, filter_prefix.len);
    	b->start = b->pos = filter_prefix.data;
    	b->last = b->pos + filter_prefix.len;
    
    	ngx_chain_t *cl = ngx_alloc_chain_link(r->pool);
    	cl->buf = b;
    	cl->next = in;
    	return next_body_filter(r, cl);
    }
    
    static void *myfilter_create_loc_conf(ngx_conf_t *cf) {
    	myfilter_conf_t *mycf;
    	mycf = (myfilter_conf_t *)ngx_pcalloc(cf->pool, sizeof(myfilter_conf_t));
    	if(mycf == NULL) return NULL;
    	mycf->enable = NGX_CONF_UNSET;
    	return mycf;
    }
    
    static char *myfilter_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child){
    	myfilter_conf_t *prev = (myfilter_conf_t *)parent;
    	myfilter_conf_t *conf = (myfilter_conf_t *)child;
    
    	ngx_conf_merge_value(conf->enable, prev->enable, 0);
    	return NGX_CONF_OK;
    }
    
    
  • 相关阅读:
    CSS Class 选择器
    CSS ID 选择器
    一个可以兼容各种数据库事务的使用范例
    参数化构造的通用查询方法
    QUI操作超时弹出登录窗口登录的处理方式
    一款代码生成器的妙用
    mongoDB操作命令及mongoDB的helper
    记录asp.net网站停止运行原因的代码
    一个JS版本的MD5
    获取地理位置的html5代码
  • 原文地址:https://www.cnblogs.com/zolo/p/5861716.html
Copyright © 2011-2022 走看看