Apache2 as a Reverse Proxy
這一陣子把自己的 Blog 搬回雲林的老家放置,
由於那裡 upload 的頻寬只有不到 2M,
因此如何有效的加速大家存取的速度,成了一個重要的課題。

我的狀況是,我背後的主機使用了 4 條中華電信的 10M/2M FTTB,
但是這四條線路平常也都有人在使用,
因此作為一個 Web Site 來說,上傳的頻寬常常不夠用,
尤其在很多圖文並茂的頁面下,偶而流量一大還會顯得吃力,
所以我開始考慮使用 Reverse Proxy,來降低負擔。
基本上你可以把 Reverse Proxy 當作一台可以自動幫你 cache 資料,
然後分散流量的一台快取伺服器。
假設今天 Jack 用 2M/512K 的 ADSL 固定 IP 架設一個 Web:
http://www.jack.idv.tw/
但是因為他的上傳只有 512K,所以大家連上來的時候很慢:
大家 -> ADSL(uploading) -> Jack’s Server
這時候 Jack 可以找到一個 Reverse Proxy,
願意幫他檔在前面 Cache,
那麼他可以將 http://www.jack.idv.tw/ 的 DNS IP 正解,
對應到 Reverse Proxy 的 IP,存取的流程變成:
大家 -> Reverse Proxy -> ADSL(uploading) -> Jack’s Server
好處就是 Reverse Proxy 的頻寬比較大,
而且相同的內容他去 Jack’s Server 拿到一份後,
就會 Cache 在自己身上,因此前端如果有人向 Server 要資料,
Reverse Proxy 就可以直接丟給大家,
不用再去 Jack’s Server 拿,可以大大節省 Jack’s Server 的頻寬。
同時這種機制也可以一個 domain,同時背後支援多台機器,
比如此例,Jack 可以裝個三台 Jack’s Server,分別三個不同的 IP,
Reverse Proxy 可以平均分散存取流量並 Cache,
這三台其中若有任何一台掛掉,還可以自動 Bypass。
一開始借到朋友在大水管上的機器,不過他只懂 Windows,
所以我必須找 Windows 上的 Solution,
我本來打算用 Squid for Windows Build,
而且也試驗性了幾個 one by one Site 對應的 Site,
我的作法如下:(squid.conf)
collapsed_forwarding on
http_port 80 vhost vport
cache_peer 127.0.0.1 parent 8081 0 originserver no-query name=test1
cache_peer 220.132.45.xxx parent 80 0 originserver no-query name=test2
cache_peer_domain test1 www.test1.idv.tw
cache_peer_domain test2 www.test2.idv.tw
parent 敘述前面接的是要 cache 的主機 IP,
後面接的是 Web Port,cache_peer_domain 設定網域對應,
網域對應也可以設立多組,都對應到同一個 name 的 cache_peer。
可惜的是網路上對於 squid 做 reverse proxy,
尤其是單一 domain 背後多台機器的設定,我找不太到相關資料,
雖然 squid 文件中提到相關 cache_peer 的 loading sharing 機制,
但是我功力薄弱,實在找不到 cache_peer_domain 該怎麼設定,
經過 sayya 網友 kenduest 的指點說,
Apache 的 mod_proxy似乎有相關 loadbalancer 模組可以用,
查了查資料,發覺果然還蠻好用的,順便搭配 mod_cache,
做快取的管理和控制,實際的 httpd.conf 設定如下:
(使用版本: Apache 2.2.8)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule cache_module modules/mod_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so
ProxyRequests Off
ProxyVia Off
KeepaLive On
ProxyPreserveHost On
NameVirtualHost *:80
<VirtualHost *:80>
DocumentRoot "d:/web"
<Directory "d:/web">
Options Indexes FollowSymLinks MultiViews ExecCGI
AllowOverride None
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName www.test1.idv.tw
ProxyPass / balancer://test1/
ProxyPreserveHost On
<proxy balancer://test1>
BalancerMember http://220.xxx.xxx.xxx
BalancerMember http://220.xxx.xxx.xxx
BalancerMember http://220.xxx.xxx.xxx
BalancerMember http://220.xxx.xxx.xxx
</proxy>
</VirtualHost>
<VirtualHost *:80>
ServerName www.test2.idv.tw
ProxyPass / balancer://test2/
ProxyPreserveHost On
<proxy balancer://test2>
BalancerMember http://220.xxx.xxx.xxx
BalancerMember http://220.xxx.xxx.xxx
BalancerMember http://220.xxx.xxx.xxx
BalancerMember http://220.xxx.xxx.xxx
</proxy>
</VirtualHost>
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<IfModule mod_cache.c>
<IfModule mod_disk_cache.c>
CacheRoot d:/cache
CacheEnable disk /
CacheDirLevels 5
CacheDirLength 3
</IfModule>
<IfModule mod_mem_cache.c>
CacheEnable mem /
MCacheSize 262144
MCacheMaxObjectCount 100
MCacheMinObjectSize 1
MCacheMaxObjectSize 2048
</IfModule>
#Don’t cache the list of security updates
#CacheDisable http://www.test1.idv.tw/update-list/
</IfModule>
ProxyPreserveHost 的設定,
是因為我的後端主機雖然看起來很多台,
但其實後端只有一台 Web,然後設定 Virtualhost 的狀況,
因此我把 ProxyPreserveHost 設定都打開。
設定完後,發現很順利的跑了起來,
然後我也沒有時間再去做什麼很細部的調整,就放給他跑,
順便寫下這篇文章當作技術筆記,
歡迎有看到這篇文章的高手,提供更多寶貴的意見喔!

三月 11th, 2008 at 1:05 上午
這篇文章出現後,我想大概一堆人會更清楚拿來幹一些壞事的應用方式 :p
三月 19th, 2008 at 11:54 上午
我馬上想到 Man in the middle,殘念…
七月 15th, 2008 at 8:46 下午
[...] Apache2 as a Reverse Proxy ruby-on-rails-伺服器架設原理 R-Proxy – 使用Apache架設 使用 Reverse Proxy代理服務 Lighttpd as reverse proxy [...]
十月 17th, 2009 at 5:30 下午
簡單的就可以啟用快取