IIS中应用Application Request Route 配置反向代理

简介

在配置web服务器的时候,我们经常遇到这样的问题,由于某些原因,该服务器只能拥有一个公网IP,但是可能需要提供其他机器或者本机上其他webserver的服务器给访问者,同时又不希望使用其他端口,如果在linux下,常见的解决方案是使用nginx作为前端server,通过反向代理间接访问其他webserver,在IIS上,通过Application Request Routing模块,我们可以轻松实现反向代理。

Demo

 此Demo完成内容是:在服务器上创建三个网站,分别对应80,8081,8082三个端口,但在生产环境中,这些非80或443端口通常不会暴露给外部访问,采用ARR反向代理的访问,外部通过http://myexample.com/first来实际访问localhost:8081,通过http://myexample.com/second来实际访问localhost:8082。

网址 IIS上的网站 实际站点
http://myexample.com t localhost
http://myexample.com/first/ first localhost:8081
http://myexample.com/second/ second localhost:8082

在上节中,我们开启了server farm,加了重写规则,完成了load balance的功能,所有的请求会直接分发到server farm下任意一台服务器,但在本节中,我们不再使用load balance,在下面的窗口中,不选中下面的URL重写规则,相当于禁用了load balance,我们接下来试一下反向代理。

修改C:\Windows\System32\drivers\etc\hosts文件,以便通过域名myexample.com能访问本地, 然后新建两文件夹first 和second,在这两文件夹里分别创建index.html文件,在IIS中创建first和second这两网站并物理路径指向相应的文件夹。创建后的IIS网站如下:

下面是相应的文件夹和文件

PS C:\apps\test> ls
    Directory: C:\apps\test
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       12/10/2018   2:24 PM                first
d-----       12/10/2018   2:26 PM                second
-a----        12/9/2018   5:23 PM             42 index.html

PS C:\apps\test> cat index.html
this is the data from localhost----server0

PS C:\apps\test> cat first/index.html
this is the first page  <a href="/index.html">here</a>

PS C:\apps\test> cat second/index.html
this is the second page  <a href="/index.html">here</a>

PS C:\apps\test> invoke-webrequest -uri myexample.com
StatusCode        : 200
StatusDescription : OK
Content           : this is the data from localhost----server0
RawContent        : HTTP/1.1 200 OK

PS C:\apps\test> invoke-webrequest -uri http://localhost:8081
StatusCode        : 200
StatusDescription : OK
Content           : this is the first page  <a href="/index.html">here</a>

PS C:\apps\test> invoke-webrequest -uri http://localhost:8082
StatusCode        : 200
StatusDescription : OK
Content           : this is the second page  <a href="/index.html">here</a>

点击上图中的Application Request Routing,选中启用代理,再点击Apply。

入站规则

接下来,配置路由重写规则,在t网站上,点击Url Rewrite——Add Rules——Blank rule——Ok。

 重写规则增加后的界面如下:

重写规则增加后在此网站对应的文件夹下,多出来了一个web.config文件,其中{R:1} 代表MatchUrl中的第一个匹配括号。

PS C:\apps\test> cat web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
                        <rules>
                                <rule name="Reverse Proxy to first" stopProcessing="true">
                                        <match url="^first/(.*)" />
                                        <action type="Rewrite" url="http://localhost:8081/{R:1}" />
                                </rule>
                                <rule name="Reverse Proxy to second" stopProcessing="true">
                                        <match url="^second/(.*)" />
                                        <action type="Rewrite" url="http://localhost:8082/{R:1}" />
                                </rule>
                        </rules>
</rewrite>
    </system.webServer>
</configuration>

到这里就配置完成了,我们来验证一下。当访问 myexample.com/first时,实际上请求转发到localhost:8081,访问myexample.com/second时,请求转发到localhost:8082。

PS C:\apps\test> invoke-webrequest -uri myexample.com/first

StatusCode        : 200
StatusDescription : OK
Content           : this is the first page  <a href="/index.html">here</a>
RawContent        : HTTP/1.1 200 OK
                    Accept-Ranges: bytes
                    Content-Type: text/html
                    ETag: "bcd86c505190d41:0"
                    Last-Modified: Mon, 10 Dec 2018 06:26:41 GMT
                    Server: Microsoft-IIS/10.0
                    X-Powered-By: ASP.NET,ARR/3.0,ASP.N...
Forms             : {}
Headers           : {[Accept-Ranges, bytes], [Content-Type, text/html], [ETag, "bcd86c505190d41:0"], [Last-Modified,
                    Mon, 10 Dec 2018 06:26:41 GMT]...}
Images            : {}
InputFields       : {}
Links             : {@{innerHTML=here; innerText=here; outerHTML=<A href="/index.html">here</A>; outerText=here;
                    tagName=A; href=/index.html}}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 55



PS C:\apps\test> invoke-webrequest -uri myexample.com/second

StatusCode        : 200
StatusDescription : OK
Content           : this is the second page  <a href="/index.html">here</a>
RawContent        : HTTP/1.1 200 OK
                    Accept-Ranges: bytes
                    Content-Type: text/html
                    ETag: "7cca275c5190d41:0"
                    Last-Modified: Mon, 10 Dec 2018 06:27:01 GMT
                    Server: Microsoft-IIS/10.0
                    X-Powered-By: ASP.NET,ARR/3.0,ASP.N...
Forms             : {}
Headers           : {[Accept-Ranges, bytes], [Content-Type, text/html], [ETag, "7cca275c5190d41:0"], [Last-Modified,
                    Mon, 10 Dec 2018 06:27:01 GMT]...}
Images            : {}
InputFields       : {}
Links             : {@{innerHTML=here; innerText=here; outerHTML=<A href="/index.html">here</A>; outerText=here;
                    tagName=A; href=/index.html}}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 56

出站规则

细心的你一定发现网页有一个链接,这个链接当从http://myexample.com/second来实际访问localhost:8082时,这网址的链接始终是<a href="/index.html">here</a>,直接点击这个链接,得不到预期的结果,因为它直接跳转到http://myexample.com/index.html,明显不对,如下图:

接下我们改一下它的出站规则,更改后的web.config内容如下,其中{C:1} 代表condition中的第一个匹配括号

PS C:\apps\test> cat web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
                        <rules>
                                <rule name="Reverse Proxy to first" stopProcessing="true">
                                        <match url="^first/(.*)" />
                                        <action type="Rewrite" url="http://localhost:8081/{R:1}" />
                                </rule>
                                <rule name="Reverse Proxy to second" stopProcessing="true">
                                        <match url="^second/(.*)" />
                                        <action type="Rewrite" url="http://localhost:8082/{R:1}" />
                                </rule>
                        </rules>
                        <outboundRules>
                                <rule name="Add application prefix" preCondition="IsHTML">
                                        <match filterByTags="A" pattern="^/(.*)" />
                                        <conditions>
                                                <add input="{URL}" pattern="^/(first|second)/.*" />
                                        </conditions>
                                        <action type="Rewrite" value="/{C:1}/{R:1}" />
                                </rule>
                                <preConditions>
                                        <preCondition name="IsHTML">
                                                <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                                        </preCondition>
                                </preConditions>
                        </outboundRules>
</rewrite>
    </system.webServer>
</configuration>

 最终我们来看看,点击一下,它会跳转到http://myexample.com/second/index.html,这样就对啦。

 实际上大多数情况下我们都不需要配置出站规则,我们在原网页中写得内容是:this is the second page  <a href="/index.html">here</a>,这样在index.html加一个斜杠写法就不太好,一般我们这样写:this is the second page  <a href="index.html">here</a> 或者 this is the second page  <a href="./index.html">here</a>,如果是这种写法的话,出规规则就可以不用设置了,浏览器会直接找相对路径。

参考链接

https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/reverse-proxy-with-url-rewrite-v2-and-application-request-routing

总结

写到这里,发现在使用ARR来配置负载均衡或反向代理,最核心的模块是使用了URL Rewrite。

负载均衡和反向代理有什么区别?有反向代理,那有正向代理吗?

答:正向代理代理客户端,反向代理代理服务器,负载均衡将请求分发到多个服务器。

猜你喜欢

转载自blog.csdn.net/wucong60/article/details/84938936