• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

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

    发布者: 嘉6148 | 发布时间: 2025-8-15 06:03| 查看数: 44| 评论数: 0|帖子模式

    万万没有想到!当初为了解决使用负载均衡时记录客户端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 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:

    从上图中可以看出请求的内容被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。
    【最终选择的解决方法】
    写了两个扩展方法:
    1. <rewrite>
    2.     <allowedServerVariables>
    3.         <add name="REMOTE_ADDR" />
    4.     </allowedServerVariables>
    5.     <globalRules>
    6.         <rule name="HTTP_X_Forwarded_For-to-REMOTE_ADDR" enabled="true">
    7.             <match url=".*" />
    8.             <serverVariables>
    9.                 <set name="REMOTE_ADDR" value="{HTTP_X_Forwarded_For}" />
    10.             </serverVariables>
    11.             <action type="None" />
    12.             <conditions>
    13.                 <add input="{HTTP_X_Forwarded_For}" pattern="^$" negate="true" />
    14.             </conditions>
    15.         </rule>
    16.     </globalRules>
    17. </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

    来源:互联网
    免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作!

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    ×

    最新评论

    浏览过的版块

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表