当前位置: 代码网 > 服务器>服务器>win服务器 > windows服务器Url重写竟然会引起IIS内核模式缓存不工作

windows服务器Url重写竟然会引起IIS内核模式缓存不工作

2024年05月12日 win服务器 我要评论
万万没有想到!当初为了解决使用负载均衡时记录客户端ip地址的问题,在iis url rewrite module中增加一条url重写规则。竟然造成http.sys的内核模式缓存(kernel mode

万万没有想到!当初为了解决使用负载均衡时记录客户端ip地址的问题,在iis url rewrite module中增加一条url重写规则。竟然造成http.sys的内核模式缓存(kernel mode caching)被iis url rewrite module禁用,禁用理由是重写规则中用到了影响缓存安全的服务器变量。

万万没有想到!当初为了解决使用负载均衡时记录客户端ip地址的问题,在iis url rewrite module中增加了一条url重写规则(详见迁入阿里云后遇到的request.userhostaddress记录ip地址问题):

<rewrite> <allowedservervariables> <add name="remote_addr" /> </allowedservervariables> <globalrules> <rule name="http_x_forwarded_for-to-remote_addr" enabled="true"> <match url=".*" /> <servervariables> <set name="remote_addr" value="{http_x_forwarded_for}" /> </servervariables> <action type="none" /> <conditions> <add input="{http_x_forwarded_for}" pattern="^$" negate="true" /> </conditions> </rule> </globalrules></rewrite>

这竟然造成http.sys的内核模式缓存(kernel mode caching)被iis url rewrite module禁用,禁用理由是重写规则中用到了影响缓存安全的服务器变量(cache unsafe server variable)——{http_x_forwarded_for}。

url重写竟然能影响到处于内核模式的http.sys,谁能想到?微软想到了,而且做到了!

当知道这个真相后,真的很恼火!平时谁会注意http.sys的缓存是否正常工作,如果不是因为最近在解决“黑色1秒”问题,估计再过十年也不会发现。

那我们是怎么发现的呢?借助于windows性能监视器(performance monitor)。

针对http.sys kernel mode cache的性能监视器

在添加了http service的三个监测项目——totaluriscached, uricachedhits, uricachemisses之后发现,totaluriscached与uricachedhits值一直是0,而uricachemisses的值巨大无比,一看就知道kernel mode caching出问题了。

后来发现一个命令可以更轻松地进行检测:

netsh http show cachestate

如果出现上图的画面,说明kernel mode caching没干活。

当我们禁用了让kernel mode caching罢工的url重写规则后,用浏览器访问一个网址,然后ctrl+f5刷新2次(10秒内被访问2次就会被http.sys缓存),然后运行命令netsh http show cachestate:

netsh http show cachestate

从上图中可以看出请求的内容被http.sys成功缓存了。

那内核模式缓存失效会带来什么影响呢?

谁都知道这会影响了网站的处理性能,而对我们来说还有一个重大影响——在“黑色1秒”问题的排查过程中,它让我们作出了错误的判断,以为“黑色1秒”期间http.sys进程卡住了(依据缓存没工作),详见“黑色30秒”走了,“黑色1秒”来了,真相也许大白了。现在看来,如果解决了http.sys缓存问题,“黑色1秒”期间iis日志中很可能有缓存输出的记录,如果真是这样,那引发“黑色1秒”的环节可能在was(windows process activation service),这将把我们带向不同的问题排查方向。

那如何解决这个问题呢?

目前只想到两个方式:

1. 弃用iis url rewrite module,但目前未找到更好的选择。

2. 让阿里云修改slb的转发规则,将http headers中的remote_addr修改为真实的客户端ip。

3. 修改代码,不通过request.userhostaddress获取ip。

【最终选择的解决方法】

写了两个扩展方法:

<rewrite>
    <allowedservervariables>
        <add name="remote_addr" />
    </allowedservervariables>
    <globalrules>
        <rule name="http_x_forwarded_for-to-remote_addr" enabled="true">
            <match url=".*" />
            <servervariables>
                <set name="remote_addr" value="{http_x_forwarded_for}" />
            </servervariables>
            <action type="none" />
            <conditions>
                <add input="{http_x_forwarded_for}" pattern="^$" negate="true" />
            </conditions>
        </rule>
    </globalrules>
</rewrite>

然后将代码中所有调用request.userhostaddress的地方改为调用扩展方法request.getuserip()。

【参考资料】

url rewrite module 1.1 for iis 7

working with http.sys or kernel mode caching in internet information services 6.0

url rewrite module configuration reference

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com