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

栏目: 后端 · 发布时间: 5年前

内容简介:背景我司的软件在一个客户处测试功能和性能,这个客户比较特殊:host header问题(此时先直连后端服务,不考虑代理)

背景

我司的软件在一个客户处测试功能和性能,这个客户比较特殊:

  • 他们客户端是很旧的 java 代码,且要求不能改动,客户端的主要业务简单说就是上传下载文件
  • 他们提供了客户端demo,http请求是用裸socket手动加http头,写死了http1.1,但又不带'host'这个http
    header
  • 客户要求中间必须经过一台windows server服务器代理
  • 后端的实际服务器是 linux 系统,用的是nginx

host header问题(此时先直连后端服务,不考虑代理)

最开始是请求直接返400,nginx access log可以看到400但是没有更多信息,error log则没有任何信息打印,一开始另一位同事负责定位,我跟着一起用wireshark抓包看了很久,没得出结论。后来我又看了一下,nginx error log默认的日志级别是crit,那么直接改到debug,看到这个信息:

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

那么问题就一目了然了,查了一下,这个header是http1.1要求必须带的

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

且nginx严格遵守该协议,没有提供可配置的方式忽略这个头,按理说其实服务端不应该强行处理这种问题,但客户要求最高,没办法

这时候好在,正好我们需要一层反向代理,那么,看看能不能找一个允许不带该header的反向代理服务器实现,接下来可以暂时忽略这个问题,我们使用压测 工具 测性能,压测工具在这个header上是没有问题的

代理布署及性能问题

windows server系统的服务器,一开始我们直接用Nginx,但简单测后就知道性能很差,搜了一下基本是说nginx和apache在windows上性能都没啥希望,首推的基本还是微软自家的IIS,于是我们配起了IIS,果然性能与直连后端相比基本没有损耗,但是经过很长时间查资料,找不到配置忽略host header的方法,而且IIS的确不好用,配置比较难看懂,大家都不熟悉windows平台,接下来只能另辟蹊径

python :老本行,用 twisted 写了个4行的反向代理,性能比nginx倒是好一点,但大概也只有直连的1/6,时间紧迫,没来得及分析,继续尝试其他语言

nodejs :在github找到个 redbird 库,代码也是只需要两行,但性能跟 python 半斤八两

java :捡了个 undertow 的框架,折腾挺久终于搞起来,倒是基本没有性能损耗,于是就要解决header问题,但是这个版本的400返回没带提示信息,java框架源码要反编译看,这个倒还好,但是没有错误信息,不好直接搜代码,只能看流程,比较难看

go :代码倒是长一些,要二三十行,性能不出意外也是等于直连,惊喜的来了,它的400带了个错误信息提示: missing required Host header ,当时那个幸福感。。。无法形容,直接对 go 产生了满分好感

于是直接打开源码目录全局搜,找到src/net/http/server.go,如下一段

`

// hosts, haveHost := req.Header["Host"]
isH2Upgrade := req.isH2Upgrade()
// if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) && !isH2Upgrade && req.Method != "CONNECT" {
//     return nil, badRequestError("missing required Host header")
// }
// if len(hosts) > 1 {
//     return nil, badRequestError("too many Host headers")
// }
// if len(hosts) == 1 && !httpguts.ValidHostHeader(hosts[0]) {
//     return nil, badRequestError("malformed Host header")
// }

`

果断注释掉了上面这些,跑起来没有问题。

但是到这还没结束,压测跑了一会儿发现请求全部失败,看了一下报错,socket爆了,在cmd里 netstat 查了一下,果然go进程接近2w的socket消耗,全部是 TIME_WAIT 状态

查一下就知道,本端主动关闭的socket,就会进入该状态,被对方关闭是 CLOSE_WAIT 。那么查一下,有说设置注册表的

[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesTcpipParameters]

"TcpTimedWaitDelay"=dword:0000001e

感觉并不是解决办法?实测也不能解决问题。想想就知道,关键应该是找到为什么go会频繁关闭socket,那么google的关键字就应该是这样了: go socket time_wait (而不是 windows socket time_wait

搜索结果第一条stackoverflow的就是答案: https://stackoverflow.com/que...

在main函数里加上配置:

http.DefaultTransport.(*http.Transport).MaxIdleConns = 8192
http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = 8192

这个值的含义见链接,简单说就是允许接收的最大并发数,我们压测工具跑的是100并发,实际只需要这个值是200就够了


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Visual C#从入门到精通(第8版)

Visual C#从入门到精通(第8版)

夏普 (John Sharp) / 周靖 / 清华大学出版社 / 2016-6-1

《Visual C#从入门到精通(第8版)》共27章,结构清晰,叙述清楚。所有练习均在Visual Studio 2015简体中文版上进行过全面演练。无论是刚开始接触面向对象编程的新手,还是打算迁移到C#的C、C++或Java程序员,都可以从《Visual C#从入门到精通(第8版)》汲取到新的知识。迅速掌握C#编程技术。一起来看看 《Visual C#从入门到精通(第8版)》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码