![ARR 在客户端用户之间混合 HTTP 服务器变量](https://linux22.com/image/712190/ARR%20%E5%9C%A8%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%94%A8%E6%88%B7%E4%B9%8B%E9%97%B4%E6%B7%B7%E5%90%88%20HTTP%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8F%98%E9%87%8F.png)
我正在尝试做什么?
我正在设置蓝绿部署以实现零停机部署。
执行情况如何?
- 我有一台服务器。
- 我创建了一个网络农场。
- 我在不同的端口设置了 3 个网站,分别为蓝色、绿色和主网站。主网站处理来自客户端的所有请求,并将请求重写到 Web Farm。
- Web 场通过 ARR(应用程序请求路由)将请求路由到活动网站(蓝色或绿色)
- 由于蓝/绿网站接收来自 Web Farm/ARR 的请求,REMOTE_ADDR(客户端 IP 地址)显示 127.0.0.1。
- 尽管这是预期的,但我并不想要它,我已经创建了一个 URL 重写规则,该规则在主网站上使用 REMOTE_ADDR 设置 HTTP_X_FORWARDED_FOR_INTERNAL 服务器变量。
- 我在蓝/绿网站上创建了另一条规则,该规则使用来自主网站的 HTTP_X_FORWARDED_FOR_INTERNAL 设置 REMOTE_ADDR 服务器变量。
- 结果,我得到了 REMOTE_ADDR 作为真实客户端 IP 地址。太棒了!
- 对于单个客户端用户来说,一切都运行良好。
什么没有按预期进行?
当我从不同的 IP 地址连接到网站时(尤其是静态内容),蓝/绿应用程序会接收其他客户端拥有的错误 IP 地址(REMOTE_ADDR)。
例子:
- A和B是不同的IP地址。
- A 连接到 foo.com/somestaticfile.css。
- B 连接到 foo.com/somestaticfile.css。
当我检查 IIS 应用程序日志时,来自 B 的请求日志显示 IP 地址为“A”,尽管它应该是 B!
我还可以根据 cookie 确认请求来自 B,我们在 cookie 中保存了 ip 地址,并且根据 IIS 应用程序日志,cookie 中的 ip 地址不等于 REMOTE_ADDR。
编辑:我发现了另一个问题,“有时”一些 javascript 响应的 mime 类型在响应中变成“text/html”,因为我们实现了 X-Content-Type-Options=nosniff,所以这些脚本不会被浏览器加载。
Refused to execute script from 'https://foo.com/bundles/scripts/common?v=Pc3UWD-GF8GEIazC15mnIr_UYtcH3cQPlDPwAf2cXtU1' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
编辑2:我发现了一些有用的东西。当我访问一些返回 40x 状态代码的链接时。错误与每次重现的 IP 地址有关。这是我未经身份验证后被重定向的 URL。
returnUrl解码后的值为:“/error/notfound/?404;https://foo.com:10003/error/notfound“
诡异的?
我已尝试过什么方法来解决此情况?
我以为这是某种缓存问题,然后我禁用了我知道的所有缓存机制;
- 从全局设置禁用 IIS 缓存。
- 通过创建缓存控制规则禁用 ARR 缓存。
- 已禁用 Web Farm 缓存。
但它没有起作用。
我已经清除了所有配置并使用ARR 助手它是为在此类配置中将 IP 地址转发到最后面的 Web 应用程序而开发的,我遇到了相同的问题。
您可能需要的配置文件
在主 Web 应用程序中设置 HTTP_X_FORWARDED_FOR_INTERNAL 的规则。
<rule name="Set HTTP_X_FORWARDED_FOR_INTERNAL">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<serverVariables>
<set name="HTTP_X_FORWARDED_FOR_INTERNAL" value="{REMOTE_ADDR}" />
</serverVariables>
<action type="None" />
</rule>
在蓝/绿应用程序中设置 REMOTE_ADDR 的规则。
<rule name="Set REMOTE_ADDR">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_X_FORWARDED_FOR_INTERNAL}" pattern="^$" negate="true" />
</conditions>
<serverVariables>
<set name="REMOTE_ADDR" value="{HTTP_X_FORWARDED_FOR_INTERNAL}" />
<set name="REMOTE_HOST" value="{HTTP_X_FORWARDED_FOR_INTERNAL}" />
</serverVariables>
<action type="None" />
</rule>
在全局级别禁用 ARR 缓存的规则。
<rewrite>
<globalRules>
<rule name="ARR_CacheControl_9dc69ea7-26f6-4654-af58-2e289d681463" enabled="true" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<serverVariables>
<set name="ARR_CACHE_CONTROL_OVERRIDE" value="1,no-cache" />
</serverVariables>
<action type="None" />
</rule>
</globalRules>
</rewrite>
整个 Web 场配置
<webFarms>
<webFarm name="iissucks" enabled="true">
<server address="bluecloud" enabled="true">
<applicationRequestRouting httpPort="880" httpsPort="8443" />
</server>
<server address="greencloud" enabled="true">
<applicationRequestRouting httpPort="980" httpsPort="9443" />
</server>
<applicationRequestRouting>
<healthCheck url="https://iissucks/account/signin" interval="00:00:01" statusCodeMatch="200-599" responseMatch="I_am_healthy." />
<protocol xForwardedForHeaderName="X-Forwarded-For-Farm" includePortInXForwardedFor="false">
<cache enabled="false" queryStringHandling="NoCaching" validationInterval="00:00:00" />
</protocol>
</applicationRequestRouting>
</webFarm>
<applicationRequestRouting>
<hostAffinityProviderList>
<add name="Microsoft.Web.Arr.HostNameRoundRobin" />
</hostAffinityProviderList>
</applicationRequestRouting>
</webFarms>
答案1
我远非 IIS 专家,但我发现您的问题很有趣。我看到您的全局缓存禁用规则stopProcessing="true"
中有一个参数设置。也许在缓存禁用规则停止处理任何其他规则后,您的变量设置规则没有被执行。