记一次线上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 事情回顾 在某次周五 ...
随机推荐
- SQL基础语法_周志城
一:建库建表语法,字段数据类型 1:建库建表语法 create (创建,关键字) database (数据库,关键字) IF NOT EXISTS 作用:如果需要创建的库已存在,将不会创建 DEF ...
- WPF中Enter 焦点转移方法
1.Set the TabIndex="16"2. private void detailGrid_Keydown(object sender, KeyEventArgs e) { ...
- Anaconda环境配置
镜像下载.域名解析.时间同步请点击 阿里巴巴开源镜像站 前言 Anaconda环境配置 Anaconda安装完后要进行环境配置,环境配置就是安装虚拟环境,让程序可以在这个环境中运行! 一.Anacon ...
- docker基础命令,常用操作
docker基础命令 使用docker镜像 获取镜像 从docker registry获取镜像的命令是docker pull.命令格式是: docker pull [选项][docker regist ...
- shellLab实验报告
一.预备知识 阅读课本CSAPP的第八章后完成本次实验,要求熟练掌握以下内容: 进程的概念.状态以及控制进程的几个函数(fork,waitpid,execve). 信号的概念,会编写正确安全的信号处理 ...
- WAF绕过的各种姿势
主要思路: 根据WAF部署位置,针对WAF.WEB服务器.WEB应用对协议解析.字符解析.文件名解析.编码解析以及SQL语法解析的差异,绕过WAF,将payload送至服务器执行. 常用绕过方法: 1 ...
- ElasticSearch7.3 学习之定制动态映射(dynamic mapping)
1.dynamic mapping ElasticSearch中有一个非常重要的特性--动态映射,即索引文档前不需要创建索引.类型等信息,在索引的同时会自动完成索引.类型.映射的创建. 当ES在文档中 ...
- 《前端运维》二、Nginx--4代理、负载均衡与其他
一.代理服务 比较容易理解吧,简单来说.客户端访问服务器并不是直接访问的,而是通过中间代理服务器,代理服务器再去访问服务器.就像一个中转站一样,无论什么,只要从客户端到服务器,你就要通过我. 一)正向 ...
- python3 爬虫6--requests的使用(1)
1用requests进行网页请求与urlopen差不多,这里省略不说 2抓取网页的学习 import requests import re headers={'User-Agent': 'Mozill ...
- docker容器登录,退出等操作命令
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口 ...