当前位置: 首页 > 后端技术 > Node.js

记录一次windows服务器上反向代理服务器的配置和使用

时间:2023-04-03 19:40:10 Node.js

背??景我们的软件正在测试客户端的功能和性能。这个client比较特殊:他们的client是很老的java代码,而且要求不能改,客户端的主要业务就是简单的上传和下载文件。他们提供了一个客户端演示。http请求使用baresocket手动添加http头,http1.1写死了,但是没有hosthttp头。windowsserverserver代理后端实际服务器是linux系统,使用nginxhost头问题(此时直接连接后端服务,不考虑代理)。一开始请求直接返回400,nginx访问日志可以看到400但没有更多信息,但是错误日志中没有打印任何信息。一开始是另一个同事负责定位,用wireshark抓包找了半天也没得出结论。后来又看了下,nginx错误日志默认的日志级别是crit,然后直接改成debug,看到这样的信息:那么问题一目了然,经查,http1.1和nginx都需要这个header严格遵守协议,没有可配置的方式来忽略此标头。如上图,按理说服务器不应该强行处理这种问题,但是客户的要求是最高的。没有办法做到这一点。幸运的是,我们只需要一层反向代理。然后,看看能不能找到一个不允许实现这个header的反向代理服务器。接下来,你可以暂时忽略这个问题。我们使用压力测试工具来测试性能。压测工具在这个header上代理部署没有问题。以及性能问题Windowsserver系统服务器,一开始我们直接使用了Nginx,但是经过简单的测试,发现性能很差。搜了一圈,基本都说nginx和apache在windows上性能没希望,第一推荐基本是微软。我们自己的IIS,所以我们配置了IIS。果然,性能和直连后端相比基本没有损失。但是查了半天资料也没找到配置忽略hostheader的方法,IIS确实不好用。Configuration比较难理解,大家对windows平台也不熟悉,只能另辟蹊径python:我用twisted写了一个4线的反向代理,性能不如nginx,只有1左右/6的直连,时间紧,没时间分析,继续尝试其他语言nodejs:在github上找了一个redbird库,代码只需要两行,但是性能和python差不多。,所以需要解决header的问题,但是这个版本400没有返回任何提示信息,需要反编译java框架的源码,可以,但是没有报错信息,不容易直接搜索代码,只能看到流程,丑陋,Java较少暴露go:代码较长,大概有30行,但只用了go的标准库,性能并不意外,并且相当于直连。惊喜来了,它的400带来了错误信息Tip:missingrequiredHostheader,当时的惊喜难以言喻,对go的印象很完美,直接打开源码目录全局搜索,找到src/net/http/server.go,下面这段`//hosts,haveHost:=req.Header["Host"]isH2Upgrade:=req.isH2Upgrade()//ifreq.ProtoAtLeast(1,1)&&(!haveHost||len(hosts)==0)&&!isH2Upgrade&&req.Method!="CONNECT"{//returnnil,badRequestError("缺少必需的主机标头")//}//iflen(hosts)>1{//returnnil,badRequestError("toomanyHostheaders")//}//iflen(hosts)==1&&!httpguts.ValidHostHeader(hosts[0]){//returnnil,badRequestError("malformedHostheader")//}`把上面注释掉了,跑起来没问题,所以hostheader的问题解决了使用golangsocket的问题,但是还没完,压力测试运行一段时间后,发现所有的请求都失败了。看完报错,socket炸了。我检查了cmd中的netstat。果然go进程的socket消耗接近2w。都是在TIME_WAIT状态被本端主动关闭的socket,会进入TIME_WAIT状态,被对方关闭是CLOSE_WAIT。然后查看windowssockettime_wait,据说在注册表中设置[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesTcpipParameters]"TcpTimedWaitDelay"=dword:0000001e不是解决办法吗?测试也不能解决问题。想想就知道关键应该是找出为什么go会频繁关闭socket,所以google的关键字应该是这样的:gosockettime_wait搜索结果中第一个stackoverflow就是答案:https://stackoverflow。com/que...在main函数中添加配置:http.DefaultTransport.(*http.Transport).MaxIdleConns=8192http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost=8192这个值的含义见链接。简单的说就是tcp允许维持的最大连接数,默认值为2(有待研究为什么是这个默认值),超过后socket会一直关闭然后重新打开,我们的压测工具是跑100个并发,其实只需要这个值是200就够了(因为真正的服务器方向还是需要同样的连接数,所以*2)想想,python应该也能做到不丢包。扭曲的库不知道那里有什么多余的操作。有空还是裸写一个反向代理吧。