记一次线上websocket返回400问题排查
现象
生产环境websocket无法正常连接,服务端返回400 bad request,开发及测试环境均正常。

抓包排查
src:nginx服务器 172.16.177.193
dst:imp应用服务器 172.16.177.218

问题定位
观察到header中的host值带有下划线,在一些中间件(如kafka、hadoop)中,对host中的特殊字符也有限制。由此猜测是header问题。
经排查,此header来自nginx的upstream

解决方案1
修改nginx的upstream配置,去除下划线
解决方案2
既然upstream中用了下划线,为何普通的http请求正常,而websocket则返回400呢?
再看正常的http请求的抓包
src: nginx服务器 172.31.47.151
dst: imp应用服务器 172.31.47.153

可见,header中的host,被转发到了目标服务器,而此host并没有下划线,正常请求。
所以,如果不修改nginx中的upstream下划线的配置,其实还可以在server中的websocket 对应的location中,添加参数,以便转发原始请求的host
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|

配置后的抓包如下

请求正常
原因探讨
带有下划线的host,为何会被服务端返回400?从上述排查过程可知,应是tomcat返回的。
这一切要从一个RFC协议规范说起
RFC-1034 是一个关于DNS及域名基础的标准。在「3.5 Preferred name syntax」中,有提及主机名的格式规范:由字母开头,字母或数字结尾,中间包含字母、数字或横杆

可见,RFC-1034标准中下划线并不被允许。
而Tomcat在一次8.x的升级中遵循该标准对host做了此校验,详见链接
org.apache.coyote.AbstractProcessor#parseHost
org.apache.tomcat.util.http.parser.Host#parse(java.io.Reader)

总结
在我们日常配置host参数时,都尽量避免使用下划线。包括在/etc/hosts下进行的配置,有时在集群环境中为了方便管理,会配置host,此时也应注意避免使用下划线。因为中间件可能也遵循了RTC规范。
延伸阅读
如果大家阅读了上述规范,可能会有疑问:为何网易163可以是数字开头?大家可以先去了解下域名的解析过程。
此处科普几个基本概念。
- domain name is the identifier of a resource in a DNS database
- label is the part of a domain name in between dots
- hostname is a special type of domain name which identifies Internet hosts
域名是在dns库中的唯一标识,label是域名中以「.」分隔的单元,hostname是对于一个地址的特殊域名映射。
在1989年的RFC-1101中的「3.1 Network name syntax」定义了网络名词的DNS编码规范。允许数字开头,只要不与十进制八位字节形式的ip地址冲突。
在1997年的RFC-2181中「11 Name syntax」对域名语法作了澄清,下划线不应被DNS服务所拒绝。
而在近年的一次CA/B论坛里,众多大厂发起投票,禁止在域名中使用下划线,否则SSL证书将不能正常申请使用。
有兴趣的朋友可以尝试搭建一个网站并作域名映射。可以确定的是,做域名映射时,因为是hostname,A和MX记录是不能带下划线的。CNAME记录由于针对的是域名,是否支持则取决于你的DNS服务商了。
记一次线上websocket返回400问题排查的更多相关文章
- 记一次线上bug排查-quartz线程调度相关
记一次线上bug排查,与各位共同探讨. 概述:使用quartz做的定时任务,正式生产环境有个任务延迟了1小时之久才触发.在这一小时里各种排查找不出问题,直到延迟时间结束了,该任务才珊珊触发.原因主要就 ...
- 解Bug之路-记一次线上请求偶尔变慢的排查
解Bug之路-记一次线上请求偶尔变慢的排查 前言 最近解决了个比较棘手的问题,由于排查过程挺有意思,于是就以此为素材写出了本篇文章. Bug现场 这是一个偶发的性能问题.在每天几百万比交易请求中,平均 ...
- Linux(2)---记录一次线上服务 CPU 100%的排查过程
Linux(2)---记录一次线上服务 CPU 100%的排查过程 当时产生CPU飙升接近100%的原因是因为项目中的websocket时时断开又重连导致CPU飙升接近100% .如何排查的呢 是通过 ...
- 线上CPU飙升100%问题排查
本文转载自线上CPU飙升100%问题排查 引子 对于互联网公司,线上CPU飙升的问题很常见(例如某个活动开始,流量突然飙升时),按照本文的步骤排查,基本1分钟即可搞定!特此整理排查方法一篇,供大家参考 ...
- 一次线上CPU高的问题排查实践
一次线上CPU高的问题排查实践 前言 近期某一天上班一开电脑,就收到了运维警报,有两台服务CPU负载很高,同时收到一线同事反馈 系统访问速度非常慢,几乎无响应. 一个美好的早晨,最怕什么就来什么.只好 ...
- 线上Redis偶发性链接失败排查记
问题过程 输入法业务于12月12日上线了词库接受业务,对部分用户根据用户uuid判断进行回传,在12月17日早上8点多开始出现大量的php报错(Redis went away),报错导致了大量的链接积 ...
- 记一次线上Kafka消息堆积踩坑总结
2018年05月31日 13:26:59 xiaoguozi0218 阅读数:2018更多 个人分类: 大数据 年后上线的系统,与其他业务系统的通信方式采用了第三代消息系统中间件Kafka.由于是 ...
- 记一次线上由nginx upstream keepalive与http协议"协作"引起的接口报错率飙高事件
年前接到个任务,说要解决线上一些手机客户端接口报错率很高的问题.拿到了监控邮件,粗略一看,各种50%+的错误率,简直触目惊心.这种疑难杂症解决起来还是挺好玩的,于是撸起袖子action. 最终的结果虽 ...
- 记一次线上 OOM 和性能优化
大家好,我是鸭血粉丝(大家会亲切的喊我 「阿粉」),是一位喜欢吃鸭血粉丝的程序员,回想起之前线上出现 OOM 的场景,毕竟当时是第一次遇到这么 紧脏 的大事,要好好记录下来. 1 事情回顾 在某次周五 ...
随机推荐
- TypeScript方法的定义
在 JavaScript 中,有两种方式定义方法. 1.命名的方法 function add(x,y){ return x+y;}2.匿名方法 var myAdd = function(x,y) { ...
- Web调试工具之调试方法
转载于: http://toutiao.com/news/6242781162012410370/ 一.Firefox 插件之 Firebug, 火狐调试利器[初学必备] 为什么要第一个提到火狐呢?因 ...
- 分享一些阅读Java相关框架源码的经验
昨天和部分网友进行了线上的交流,交流中有不少网友提到阅读源码比较难,不知道怎么上手.胖哥分享了一些个人经验,这里总结一下. 阅读源码实际上是Debug源码 其实所谓的阅读源码并不是单纯的阅读,而是调试 ...
- kafka 第一次小整理(草稿篇)————分发的基本思路[三]
前言 简单整理一下分发的基本思路. 正文 kafka 原本是做日志管理系统,主要是分发这块的. 那么如何做分发呢? 分发的是什么呢? 分发的其实是日志,日志是事件状态,kafka 内部就叫做Recor ...
- 串和KMP算法
一.串 串是由零个或多个字符串组成的有限序列 (一).串的定义 定长顺序存储 特点:每个串变量分配一个固定长度的存储区,即定长数组 定义: #define MAXLEN 255 typedef str ...
- Python之VSCode
在学习Python的过程中,一直没有找到比较趁手的第三方编辑器,用的最多的还是Python自带的编辑器.由于本人用惯了宇宙第一IDE(Visual Studio),所以当Visual Studio C ...
- 七天接手react项目 系列 —— react 路由
其他章节请看: 七天接手react项目 系列 react 路由 本篇首先讲解路由原理,接着以一个基础路由示例为起点讲述路由最基础的知识,然后讲解嵌套路由.路由传参,最后讲解路由组件和一般组件的区别,以 ...
- python3 使用mongo数据库
0让服务器端开启服务 sudo mongod --port 27017 --dbpath /data/db --logpath /data/log --logappend --fork --auth ...
- mac phpStrom 卸载
cd ~/Library/Logs/cd ~/Library/Application\ Supportcd ~/Library/Preferences/cd ~/Library/Caches/
- 在java web工程中jsp页面中使用kindeditor
在这之前我们用Notepad++写过kindeditor 在Java web工程里也差不多 首先我们复制之前的thml代码粘贴到工程里 然后把样式也复制进去 然后就可以运行了