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>,如果是這種寫法的話,出規規則就可以不用設定了,瀏覽器會直接找相對路徑。
參考連結
總結
寫到這裡,發現在使用ARR來配置負載均衡或反向代理,最核心的模組是使用了URL Rewrite。
負載均衡和反向代理有什麼區別?有反向代理,那有正向代理嗎?
答:正向代理代理客戶端,反向代理代理伺服器,負載均衡將請求分發到多個伺服器。