1. 程式人生 > >IIS中應用Application Request Route 配置反向代理

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。

負載均衡和反向代理有什麼區別?有反向代理,那有正向代理嗎?

答:正向代理代理客戶端,反向代理代理伺服器,負載均衡將請求分發到多個伺服器。