记录一次"失败"的Windows Server优化案例
分类: Windows Server ◆ 标签: #Azure #Virtual Host #Windows #.Net ◆ 发布于: 2023-06-15 19:52:01
近期将自己的博客移动基于Windows Server 2019 Datacenter的Azure虚拟机上,这个虚拟机使用了标准的Azure B2s的机型,从参数上看是2个vCore, 4G的内存,IOPS是1280,之前采用的是基于Ubuntu Server 20.04 LTS版本的机器,虚拟机的大小是一样的。但是我发现将博客迁移到Windows Server上之后,发现性能提升巨大,这确实颠覆了我的认知,一直以来我都认为是Linux的性能是要好于Windows的。
因此我自己做了一个技术上的总结,对比了一下,在相同硬件的情况下,为什么Windows会速度有这么大的提升。抛开操作系统的设计不谈,毕竟这不是我的强项,从架构上,以及Web应用我是可以归纳一些原因的:
在Linux上我采用的架构是开源社区及其推崇的架构:nginx + .Net Core的
Kestrel, 依据官方的推荐配置了相应的配置,主要有:- 使用
Systemd来管理.Net应用 nginx的反向代理不监听loopback转为监控unix socket, 同时启用了/dev/shm 来放置unix socket, 减少反向代理时请求loopback设备的损耗。- 优化了
nginx的参数。
- 使用
在
Windows Server 2019 Datacenter上我主要是使用了IIS 10.0+Asp.net Core Module, 从而使用Asp.net Core的IIS实现,不使用Kestrel, 同时在部署网站的时候选择了in-process的模式,也即.Net的代码和IIS的w3wp在同一个进程里,免去了额外的通讯, 其他没有做什么额外的优化。同时做了一些Window Server上的目录分布以及权限的配置。首先最重要的一个原因,我认为是因为
IIS和Asp.net Core Module的集成方式,IIS和.Net的代码直接在同一进程中通讯,我认为这会比在Linux上通过nginx反向代理要快上很多个数量级。通过查看
Windows Server的优化文档,文档中提及针对HTTP.sys默认的优化,也即Windows的内核缓存上。IIS本身提供的用户缓存。
由于我的博客仅仅是一个很小的几乎是静态的页面,同时我启用了IIS的动态压缩,因此最开始我认为是由于:in-process模式部署,HTTP.sys的内核缓存,以及IIS的用户缓存,以及IIS的动态压缩,这些原因导致了Windows的性能更好,当然也少不了HTTP.sys的连接管理功能。
本来还挺心安理得,觉得是一个很明智的选择,结果有一天晚上,突发奇想,我既然适用了这么多的缓存,那么我怎么这些缓存的命中率咋样呢?起了多大的作用呢?
赶紧找了一下技术文档,发现有几个方法可以进行查看。
方法一:直接使用netsh http show cachestate查看内核缓存的状态,然后我兴致勃勃的,开始写了一个小脚本,使劲的刷一个页面,结果发现:

啊?!! 尴尬了,咋回事?难道是我用错了命令?一点都没有输出啊。。。。赶紧去查了windows的官方文档,仔细看了一下这个命令,以及帮助。没错就是这么用的。这。。。。咋回事?我的缓存呢?
不信邪的我,继续用第二招:
启动性能监视器, 然后查看指标:

嗯?几个指标UriCacheHits, TotalUriCached, CurrentUrisCache都是0啊!!!!
奔溃了,咋办?
别急,还有一招。放大招。使用IIS的Freb Trace。
按照如下的步骤临时启用Freb Trace:
启动
IIS管理器,选择自己的站点,然后右侧选择Failed Request Tracking Rule, 双击进入,然后选择右边菜单上的Edit Site Tracking:
如下图:

然后启用trace:
然后再添加规则,添加上图中的`Add...', 出现对话框之后:
然后一路'Next`, 配置好了之后,继续刷页面。然后到保存
freb的目录里查看,看到日志文件如下图:

从图上可以看到一般的路径以及文件名。
用浏览器打开一个,按如下图确认是你访问的文件地址:

看图标处,第一个是文件地址,第二个是我们要关注的地方。点击
Request Detail之后,搜索cache:
然后就看到这个:

嗯,咋回事?说是没有启用?
使用
netsh http确认一下:

说明是启用了的。
就觉得很郁闷,感觉很奇怪,后来在大佬的指点下,屏蔽了Asp.net Core module的Handler 仅仅使用静态文件发现居然可以了~~~~~
由此怀疑是不是Asp.net Core Module完全不使用HTTP.sys以及IIS的缓存啊。。。
最后终于发现文档:
https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/iis/modules?view=aspnetcore-6.0
HttpCache模块压根就不会被Asp.net Core使用,如下图:

也就是说基于IIS + Asp.net Core module的in-process模式是完全没有使用内核缓存和IIS的用户缓存的,完全是由Asp.net Core的Response Cache middler来接管的。
这样就更有意思了。同样是在同一套代码和同一套runtime下,in-process的模式可以有如此大的提升?
虽然这次优化不是我想的那样,但是我对于Windows更感兴趣了,是时候好好的研究一下了。