Apache與Nginx在同一服務器反向代理共存端口衝突怎麼辦

Apache與Nginx在同一服務器反向代理共存端口衝突怎麼辦

很久以前,老王去飯店吃飯,需要先到飯店,七葷八素點好菜,坐等飯菜上桌,然後大快朵頤,不亦樂乎。有了第三方訂餐外賣平臺(代理),老王懶得動身前往飯店,老王打個電話或用APP,先選好某個飯店,再點好菜,外賣小哥會送上門來。由於某個品牌的飯店口碑特別好,食客絡繹不絕涌入,第三方訂餐電話也不絕於耳,但是限於飯店接待能力有限,無法提供及時服務,很多食客等得不耐煩了,紛紛鎩羽而歸,飯店老總看着煮熟的鴨子飛走了,心疼不已。痛定思痛,老總又成立了幾個連鎖飯店,形成一個集羣,對外提供統一標準的菜品服務,電話訂餐電話400-xxx-7777,當食客涌入飯店總檯,總檯將食客用大巴運到各個連鎖店,這樣食客既不需要排隊,各連鎖店都能高速運轉起來,一舉兩得,老總樂開了花,併爲此種運作模式起名爲“反向代理”(Reverse Proxy)。反向代理在計算機世界裏,由於單個服務器的處理客戶端(用戶)請求能力有一個極限,當用戶的接入請求蜂擁而入時,會造成服務器忙不過來的局面,可以使用多個服務器來共同分擔成千上萬的用戶請求,這些服務器提供相同的服務,對於用戶來說,根本感覺不到任何差別。
一個典型的 Nginx + Apache 應用方案可以是Nginx 佔用 80 端口,過濾靜態請求,然後動態請求即 Proxy 到 Apache 的 8080 端口。Proxy 反向代理的好處是訪問的時候,始終就是 80 端口,來訪者不會覺察到有任何的區別。


但有的應用確非常“聰明”,識別到 Apache 所位於的端口是 8080 ,就會把相關的超鏈接都一併加上 :8080 的後續。這麼就死定了,還能有正常訪問麼?!


有個方法可以解決這事,就是把 apache 也運行在80端口上。同一臺服務器,有Nginx 也有 Apache,2個httpd服務,都是80,不會衝突麼?


下邊就是舉例方法。
Nginx.conf 的配置中


server {
 listen 80;
 server_name www.xmc9.com;
}
修改一下。


server {
 listen 192.168.3.3:80;  #指定Nginx只佔用某個IP的80端口。
 listen 192.168.10.3:80;  #如果你服務器中有多個IP,還可以指定多個。
 server_name www.xmc9.com;
}
如果你在Nginx有多個虛擬主機,每一個都需要這麼修改。


然後輪到 apache 的 httpd.conf
把原來的


Listen 80
改爲


Listen 127.0.0.1:80
跟Nginx一樣,指定apache所佔用的IP及端口。
保存退出,重啓apache即可生效。
如果你 apache 上也有多個虛擬主機。無需好像Nginx那樣逐一修改,只要都是 80 端口既可。


如:


NameVirtualHost *:80
<VirtualHost *:80>
 ServerAdmin [email protected]
 DocumentRoot /data/web_server/admin
 ServerName www.xmc9.com
</VirtualHost>
這樣你是不是以爲,就已經萬事大吉了?非也。


這樣的apache只能通過http://127.0.0.1:80才能訪問,那麼他還佔用80端口就沒有意義了。還不如apache用8080,nginx用80算了。
所以此時如果你的服務器有多ip,除了把apache綁定在 127.0.0.1 還能綁定另外一張網卡的IP,那麼問題就解決。


可是一般人都是隻有一個獨立ip的,所以這種方法對很多人來講就是海市蜃樓。
修改一種思路,apache還是8080端口,修改其中的一個nginx的域名的conf文件


location / {
 try_files $uri @apache;
}
  
location @apache {
 internal;
 proxy_pass http://127.0.0.1:8080;
}
  
location ~ .*.(php|php5)?$ {
 proxy_pass http://127.0.0.1:8080;
}
此時,該域名全部動作都走Apache了,包括靜態文件。


也有很多人下面這種寫法:


upstream zend {
 server 127.0.0.1:8080;
}
  
location / {
 proxy_pass  http://zend;
 proxy_redirect   off;
 proxy_set_header  Host $host;
 proxy_set_header  X-Real-IP $remote_addr;
 proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header   X-Scheme $scheme;
}
  
location ~ .*.(php|php5)?$ {
 proxy_pass  http://zend;
 proxy_redirect   off;
 proxy_set_header  Host $host;
 proxy_set_header  X-Real-IP $remote_addr;
 proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header   X-Scheme $scheme;
}
大體類似。


Nginx的端口修改
修改 nginx.conf 文件實現。在 Linux 上該文件的路徑爲 /usr/local/nginx/conf/nginx.conf,Windows 下 安裝目錄\conf\nginx.conf。


server {
 listen  80;
 server_name localhost;
  
 ……
}
改成


server {
 listen  81;
 server_name localhost;
  
 location / {
 root html;
 index index.html index.htm;
 }
 ……
}
當然改成 8080,8081 什麼的都可以,不一定要 81,但是確保 iptable 要放開對該端口的訪問。


注意到 location 的配置:


root html; #根目錄,相對於安裝目錄 
index index.html index.htm; #默認主頁
默認,你把文件放在安裝目錄下的 html 文件夾,即可通過 Nginx 訪問。


Apache與Nginx的優缺點比較 
1、nginx相對於apache的優點: 
輕量級,同樣起web 服務,比apache 佔用更少的內存及資源 
抗併發,nginx 處理請求是異步非阻塞的,而apache 則是阻塞型的,在高併發下nginx 能保持低資源低消耗高性能 
高度模塊化的設計,編寫模塊相對簡單 
社區活躍,各種高性能模塊出品迅速啊 
apache 相對於nginx 的優點: 
rewrite ,比nginx 的rewrite 強大 
模塊超多,基本想到的都可以找到 
少bug ,nginx 的bug 相對較多 
超穩定 
存在就是理由,一般來說,需要性能的web 服務,用nginx 。如果不需要性能只求穩定,那就apache 吧。後者的各種功能模塊實現得比前者,例如ssl 的模塊就比前者好,可配置項多。這裏要注意一點,epoll(freebsd 上是 kqueue )網絡IO 模型是nginx 處理性能高的根本理由,但並不是所有的情況下都是epoll 大獲全勝的,如果本身提供靜態服務的就只有寥寥幾個文件,apache 的select 模型或許比epoll 更高性能。當然,這只是根據網絡IO 模型的原理作的一個假設,真正的應用還是需要實測了再說的。 


2、作爲 Web 服務器:相比 Apache,Nginx 使用更少的資源,支持更多的併發連接,體現更高的效率,這點使 Nginx 尤其受到虛擬主機提供商的歡迎。在高連接併發的情況下,Nginx是Apache服務器不錯的替代品: Nginx在美國是做虛擬主機生意的老闆們經常選擇的軟件平臺之一. 能夠支持高達 50,000 個併發連接數的響應, 感謝Nginx爲我們選擇了 epoll and kqueue 作爲開發模型. 
Nginx作爲負載均衡服務器: Nginx 既可以在內部直接支持 Rails 和 PHP 程序對外進行服務, 也可以支持作爲 HTTP代理 服務器對外進行服務. Nginx採用C進行編寫, 不論是系統資源開銷還是CPU使用效率都比 Perlbal 要好很多. 
作爲郵件代理服務器: Nginx 同時也是一個非常優秀的郵件代理服務器(最早開發這個產品的目的之一也是作爲郵件代理服務器), Last.fm 描述了成功並且美妙的使用經驗. 
Nginx 是一個安裝非常的簡單 , 配置文件非常簡潔(還能夠支持perl語法), Bugs 非常少的服務器: Nginx 啓動特別容易, 並且幾乎可以做到7*24不間斷運行,即使運行數個月也不需要重新啓動. 你還能夠不間斷服務的情況下進行軟件版本的升級 . 


3、Nginx 配置簡潔, Apache 複雜 
Nginx 靜態處理性能比 Apache 高 3倍以上 
Apache 對 PHP 支持比較簡單,Nginx 需要配合其他後端用 
Apache 的組件比 Nginx 多 
現在 Nginx 纔是 Web 服務器的首選 


4、最核心的區別在於apache是同步多進程模型,一個連接對應一個進程;nginx是異步的,多個連接(萬級別)可以對應一個進程 


5、nginx處理靜態文件好,耗費內存少.但無疑apache仍然是目前的主流,有很多豐富的特性.所以還需要搭配着來.當然如果能確定nginx就適合需求,那麼使用nginx會是更經濟的方式. 


6、從個人過往的使用情況來看,nginx的負載能力比apache高很多。最新的服務器也改用nginx了。而且nginx改完配置能-t測試一下配置有沒有問題,apache重啓的時候發現配置出錯了,會很崩潰,改的時候都會非常小心翼翼現在看有好多集羣站,前端nginx抗併發,後端apache集羣,配合的也不錯。 


7、nginx處理動態請求是雞肋,一般動態請求要apache去做,nginx只適合靜態和反向。 


8、從我個人的經驗來看,nginx是很不錯的前端服務器,負載性能很好,在老奔上開nginx,用webbench模擬10000個靜態文件請求毫不吃力。apache對php等語言的支持很好,此外apache有強大的支持網路,發展時間相對nginx更久,bug少但是apache有先天不支持多核心處理負載雞肋的缺點,建議使用nginx做前端,後端用apache。大型網站建議用nginx自代的集羣功能 


9、Nginx優於apache的主要兩點:1.Nginx本身就是一個反向代理服務器 2.Nginx支持7層負載均衡;其他的當然,Nginx可能會比apache支持更高的併發,但是根據NetCraft的統計,2011年4月的統計數據,Apache依然佔有62.71%,而Nginx是7.35%,因此總得來說,Aapche依然是大部分公司的首先,因爲其成熟的技術和開發社區已經也是非常不錯的性能。 


10、你對web server的需求決定你的選擇。大部分情況下nginx都優於APACHE,比如說靜態文件處理、PHP-CGI的支持、反向代理功能、前端Cache、維持連接等等。在Apache+PHP(prefork)模式下,如果PHP處理慢或者前端壓力很大的情況下,很容易出現Apache進程數飆升,從而拒絕服務的現象。 


11、可以看一下nginx lua模塊:https://github.com/chaoslaw...apache比nginx多的模塊,可直接用lua實現apache是最流行的,why?大多數人懶得更新到nginx或者學新事物 


12、對於nginx,我喜歡它配置文件寫的很簡潔,正則配置讓很多事情變得簡單運行效率高,佔用資源少,代理功能強大,很適合做前端響應服務器 


13、Apache在處理動態有優勢,Nginx併發性比較好,CPU內存佔用低,如果rewrite頻繁,那還是Apache吧
1.nginx負載均衡
  網站的訪問量越來越大,服務器的服務模式也得進行相應的升級,比如分離出數據庫服務器、分離出圖片作爲單獨服務,這些是簡單的數據的負載均衡,將壓力分散到不同的機器上。有時候來自web前端的壓力,也能讓人十分頭痛。怎樣將同一個域名的訪問分散到兩臺或更多的機器上呢?這其實就是另一種負載均衡了,nginx自身就可以做到,只需要做個簡單的配置就行。
  nginx不單可以作爲強大的web服務器,也可以作爲一個反向代理服務器,而且nginx還可以按照調度規則實現動態、靜態頁面的分離,可以按照輪詢、ip哈希、URL哈希、權重等多種方式對後端服務器做負載均衡,同時還支持後端服務器的健康檢查。
Nginx負載均衡一些基礎知識:
nginx 的 upstream目前支持 4 種方式的分配 
1)、輪詢(默認) 
  每個請求按時間順序逐一分配到不同的後端服務器,如果後端服務器down掉,能自動剔除。 
2)、weight 
  指定輪詢機率,weight和訪問比率成正比,用於後端服務器性能不均的情況。 
2)、ip_hash 
  每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。  
3)、fair(第三方) 
  按後端服務器的響應時間來分配請求,響應時間短的優先分配。  
4)、url_hash(第三方)
 
2.nginx負載均衡配置,主要是proxy_pass,upstream的使用
在http段做如下配置,即可實現兩個域名
 


upstream  www.xmc9.com  
{
    server   10.0.1.50:8080;
    server   10.0.1.51:8080;
}
 
upstream  xmc9.com   
{
    server   10.0.1.50:8080;
    server   10.0.1.51:8080;
}
 
server
{
    listen  80;
    server_name  www.xmc9.com;
 
    location / {
        proxy_pass        http://www.xmc9.com;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
}
 
server
{
    listen  80;
    server_name  xmc9.com;
 
    location / {
        proxy_pass        http://www.xmc9.com;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
}
 
3.注意的幾個小問題
3.1 多臺機器間session的共享問題
配置負載均衡比較簡單,但是最關鍵的一個問題是怎麼實現多臺服務器之間session的共享
下面有幾種方法(以下內容來源於網絡,第四種方法沒有實踐.)
1). 不使用session,換作cookie
  能把session改成cookie,就能避開session的一些弊端,在從前看的一本J2EE的書上,也指明在集羣系統中不能用session,否則惹出禍端來就不好辦。如果系統不復雜,就優先考慮能否將session去掉,改動起來非常麻煩的話,再用下面的辦法。
2). 應用服務器自行實現共享
  php可以用數據庫或memcached來保存session,從而在php本身建立了一個session集羣,用這樣的方式可以令 session保證穩定,即使某個節點有故障,session也不會丟失,適用於較爲嚴格但請求量不高的場合。但是它的效率是不會很高的,不適用於對效率要求高的場合。
以上兩個辦法都跟nginx沒什麼關係,下面來說說用nginx該如何處理:
3).  ip_hash
  nginx中的ip_hash技術能夠將某個ip的請求定向到同一臺後端,這樣一來這個ip下的某個客戶端和某個後端就能建立起穩固的session,ip_hash是在upstream配置中定義的:
 


upstream backend {
    server 127.0.0.1:8080 ;
    server 127.0.0.1:9090 ;
    ip_hash;
}
  ip_hash是容易理解的,但是因爲僅僅能用ip這個因子來分配後端,因此ip_hash是有缺陷的,不能在一些情況下使用:
  nginx不是最前端的服務器。ip_hash要求nginx一定是最前端的服務器,否則nginx得不到正確ip,就不能根據ip作hash。譬如使用的是squid爲最前端,那麼nginx取ip時只能得到squid的服務器ip地址,用這個地址來作分流是肯定錯亂的。
  nginx的後端還有其它方式的負載均衡。假如nginx後端又有其它負載均衡,將請求又通過另外的方式分流了,那麼某個客戶端的請求肯定不能定位到同一臺session應用服務器上。這麼算起來,nginx後端只能直接指向應用服務器,或者再搭一個squid,然後指向應用服務器。最好的辦法是用location作一次分流,將需要session的部分請求通過ip_hash分流,剩下的走其它後端去。
4). upstream_hash
  爲了解決ip_hash的一些問題,可以使用upstream_hash這個第三方模塊,這個模塊多數情況下是用作url_hash的,但是並不妨礙將它用來做session共享。假如前端是squid,他會將ip加入x_forwarded_for這個http_header裏,用upstream_hash可以用這個頭做因子,將請求定向到指定的後端:可見這篇文檔:http://www.sudone.com/nginx/nginx_url_hash.html
在文檔中是使用$request_uri做因子,稍微改一下:
hash   $http_x_forwarded_for;


這樣就改成了利用x_forwarded_for這個頭作因子,在nginx新版本中可支持讀取cookie值,所以也可以改成:
hash   $cookie_jsessionid;


  假如在php中配置的session爲無cookie方式,配合nginx自己的一個userid_module模塊就可以用nginx自發一個cookie,可參見userid模塊的英文文檔:http://wiki.nginx.org/NginxHttpUserIdModule
  另可用姚偉斌編寫的模塊upstream_jvm_route:http://code.google.com/p/nginx-upstream-jvm-route/
3.2 後端服務器自動加上端口的問題

  一個典型的 Nginx + Apache 應用方案可以是Nginx 佔用 80 端口,過濾靜態請求,然後動態請求即 Proxy 到 Apache 的 8080 端口。Proxy 反向代理的好處是訪問的時候,始終就是 80端口,來訪者不會覺察到有任何的區別。但有的應用確非常“聰明”,識別到 Apache 所位於的端口是 8080 ,就會把相關的超鏈接都一併加上 :8080 的後續。這麼就死定了,還能有正常訪問麼?!有個方法可以解決這事,就是把 apache 也運行在80端口上。同一臺服務器,有Nginx 也有 Apache,2個httpd服務,都是80,不會衝突麼?


nginx.conf 的配置中
 


server {
    listen 80;
    server_name www.xmc9.com;
    ....
}
修改爲:
 


server {
    listen 123.123.123.123:80; #指定Nginx只佔用某個公網IP的80端口。
    #listen 123.123.123.124:80; #如果你服務器中有多個IP,還可以指定多個。
    server_name www.xmc9.com;
....
}
把 apache 的配置文件 httpd.conf 中的
Listen 80


改爲
Listen 127.0.0.1:80


跟Nginx一樣,指定apache所佔用的IP及端口。

保存退出,重啓apache即可生效。

小麥藏閣

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章