现象
昨天跟迭代新版告警平台,把告警数据发送到告警平台的API接口,但是数据发送器始终报如下错误:
代码语言:javascript复制11:59:22.819 [alertSystemTaskJobPool_169-thread-3] ERROR c.d.p.common.util.MetaDataUtil - Error in sending raw data, result is: {"errcode":10000,"errmsg":"The request does not contain a access-key."}
代码语言:javascript复制字面理解的意思就是这个请求不包含一个access-key.
分析原因
开发通过数据发送器的log,发现已经从config中读取到了access-key的值,但是发送到告警平台的API接口发送失败,然后查看告警平台API接口服务,发现传递过来的header中access-key为空。
整体平台工作架构如下:
如上图所示,可以知道SendData从配置中读取到access-key的配置信息,加入到header中的key键值是access_key
。
默认nginx是不能转发带_
的header信息的,为什么不能支持下划线呢,因为nginx的源码中默认判定就是不合法的:
rc = ngx_http_parse_header_line(r, r->header_in, cscf->underscores_in_headers);
if (r->invalid_header && cscf->ignore_invalid_headers)
在ngx_http_parse_header_line() 函数中
代码语言:javascript复制if (ch == ‘_’) {
if (allow_underscores) {
hash = ngx_hash(hash, ch);
r->lowcase_header[i ] = ch;
i &= (NGX_HTTP_LC_HEADER_LEN – 1);
} else {
r->invalid_header = 1;
}
从if (allow_underscores)
中你可以看出nginx对header name的字符做了限制,默认 underscores_in_headers 为off,表示如果header name中包含下划线,则忽略掉。
解决问题
好了现在问题已经很明显了,所以解决应该很easy了。这种问题解决方法都可以双向考虑,1是把传递的header name合法了,2是让nginx接收不合法的header name,所以解决方法如下:
- 让开发把传递的
access_key
改为access-key
, 一般header的name都是-
来拼接的,比如User-Agent
- 运维在nginx.conf配置文件中的
http {}
部分中 添加underscores_in_headers on;
配置项
总结
运维如何在日常工作中避免这种问题,这里给出如下几点建议:
- 运维要求开发传递的header中的键值不要带
_
- 统一环境,不要QA不用nginx代理,beta/onlien用nginx代理,让测试在QA环境规避了这种问题
- 图省事运维统一线上nginx开启
underscores_in_headers
配置项
关于第三条,最好不要这么做,还是去跟开发沟通,让他们形成良好的开发习惯,提升规范意识。
参考:HTTP Message: https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html