Skip to main content

记录一次"失败"的Windows Server优化案例

分类:  Windows Server 标签:  #Azure #Virtual Host #Windows #.Net 发布于: 2023-06-15 19:52:01

近期将自己的博客移动基于Windows Server 2019 DatacenterAzure虚拟机上,这个虚拟机使用了标准的Azure B2s的机型,从参数上看是2个vCore, 4G的内存,IOPS是1280,之前采用的是基于Ubuntu Server 20.04 LTS版本的机器,虚拟机的大小是一样的。但是我发现将博客迁移到Windows Server上之后,发现性能提升巨大,这确实颠覆了我的认知,一直以来我都认为是Linux的性能是要好于Windows的。

因此我自己做了一个技术上的总结,对比了一下,在相同硬件的情况下,为什么Windows会速度有这么大的提升。抛开操作系统的设计不谈,毕竟这不是我的强项,从架构上,以及Web应用我是可以归纳一些原因的:

  1. 在Linux上我采用的架构是开源社区及其推崇的架构:nginx + .Net Core的Kestrel, 依据官方的推荐配置了相应的配置,主要有:

    • 使用Systemd来管理.Net应用
    • nginx的反向代理不监听loopback转为监控unix socket, 同时启用了/dev/shm 来放置unix socket, 减少反向代理时请求loopback设备的损耗。
    • 优化了nginx的参数。
  2. Windows Server 2019 Datacenter上我主要是使用了IIS 10.0 + Asp.net Core Module, 从而使用Asp.net CoreIIS实现,不使用Kestrel, 同时在部署网站的时候选择了in-process的模式,也即.Net的代码和IISw3wp在同一个进程里,免去了额外的通讯, 其他没有做什么额外的优化。同时做了一些Window Server上的目录分布以及权限的配置。

  3. 首先最重要的一个原因,我认为是因为IISAsp.net Core Module的集成方式,IIS.Net的代码直接在同一进程中通讯,我认为这会比在Linux上通过nginx反向代理要快上很多个数量级。

  4. 通过查看Windows Server的优化文档,文档中提及针对HTTP.sys默认的优化,也即Windows的内核缓存上。

  5. IIS本身提供的用户缓存。

由于我的博客仅仅是一个很小的几乎是静态的页面,同时我启用了IIS的动态压缩,因此最开始我认为是由于:in-process模式部署,HTTP.sys的内核缓存,以及IIS的用户缓存,以及IIS的动态压缩,这些原因导致了Windows的性能更好,当然也少不了HTTP.sys的连接管理功能。

本来还挺心安理得,觉得是一个很明智的选择,结果有一天晚上,突发奇想,我既然适用了这么多的缓存,那么我怎么这些缓存的命中率咋样呢?起了多大的作用呢?

赶紧找了一下技术文档,发现有几个方法可以进行查看。

方法一:直接使用netsh http show cachestate查看内核缓存的状态,然后我兴致勃勃的,开始写了一个小脚本,使劲的刷一个页面,结果发现:


啊?!! 尴尬了,咋回事?难道是我用错了命令?一点都没有输出啊。。。。赶紧去查了windows的官方文档,仔细看了一下这个命令,以及帮助。没错就是这么用的。这。。。。咋回事?我的缓存呢?

不信邪的我,继续用第二招:

启动性能监视器, 然后查看指标:


嗯?几个指标UriCacheHitsTotalUriCachedCurrentUrisCache都是0啊!!!!

奔溃了,咋办?

别急,还有一招。放大招。使用IISFreb Trace

按照如下的步骤临时启用Freb Trace:

  1. 启动IIS管理器,选择自己的站点,然后右侧选择Failed Request Tracking Rule, 双击进入,然后选择右边菜单上的Edit Site Tracking:
    如下图:


    然后启用trace:



    然后再添加规则,添加上图中的`Add...', 出现对话框之后:



    然后一路'Next`, 配置好了之后,继续刷页面。

  2. 然后到保存freb的目录里查看,看到日志文件如下图:


    从图上可以看到一般的路径以及文件名。

    用浏览器打开一个,按如下图确认是你访问的文件地址:


    看图标处,第一个是文件地址,第二个是我们要关注的地方。


  3. 点击Request Detail之后,搜索cache:
    然后就看到这个:


    嗯,咋回事?说是没有启用?

    使用netsh http确认一下:

    说明是启用了的。

就觉得很郁闷,感觉很奇怪,后来在大佬的指点下,屏蔽了Asp.net Core moduleHandler 仅仅使用静态文件发现居然可以了~~~~~

由此怀疑是不是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 modulein-process模式是完全没有使用内核缓存和IIS的用户缓存的,完全是由Asp.net CoreResponse Cache middler来接管的。

这样就更有意思了。同样是在同一套代码和同一套runtime下,in-process的模式可以有如此大的提升?

虽然这次优化不是我想的那样,但是我对于Windows更感兴趣了,是时候好好的研究一下了。