Ubuntu下基於Nginx實現Tomcat集羣負載均衡

Nginx是一款HTTP和反向代理服務器,有關它的介紹可以到網上搜一下,很多很多,不再累述。這裏,我們記錄一下Nginx的安裝過程,以及如何配置Nginx來實現Tomcat集羣的負載均衡。

 

基本思路

 

假如現在我們有一個使用Java實現的Web搜索服務器,用戶可以通過Web頁面輸入關鍵詞,搜索服務器處理搜索請求並向用戶展示搜索結果。如果用戶訪問量很大的話,我們的這臺搜索服務器承受的壓力會很大,很可能由於搜索服務器的處理能力達到上限,在某一個時刻無法再處理用戶新到來的請求。所以,我們就考慮將用戶請求的壓力分散開,即在多臺服務器上部署同一套搜索服務器程序,然後通過一個負載均衡策略,將請求的壓力分攤在多臺搜索服務器上,這樣,在用戶請求量很大的情況下,很好解決單臺服務器的無法處理請求的問題。

我們的想法就是,通過一臺服務器做代理,使用負載均衡軟件實現請求的代理轉發,將用戶的請求轉發到多臺搜索服務器上去處理,就能實現多臺搜索服務器的負載均衡,而不致於單一服務器處理所有請求。

假設,我們現在有三臺機器,各臺服務器如下所示:

搜索服務器:192.168.0.174 RHEL 5
搜索服務器:192.168.0.181 Win 7
代理服務器:192.168.0.184 Ubuntu 11.04.1

通過使用Nginx做反向代理,安裝在192.168.0.184上。另外兩臺服務器均爲搜索服務器,並且都安裝了Tomcat Web服務器軟件,搜索服務器程序就部署在Tomcat中。服務器192.168.0.184接收搜索請求,並通過Nginx將請求轉發到兩臺搜索服務器上進行處理,然後返回結果,通過Nginx代理響應的搜索結果。

 

配置資源

 

這裏,說明一下我們各臺服務器的軟件配置,及其應用端口,如下所示:

服務器IP:端口

軟件配置

192.168.0.174:8080 OpenJDK 1.6.0_22, apache-tomcat-7.0.22.tar
192.168.0.181:8080 Sun JDK 1.6.0_17, apache-tomcat-6.0.20.exe
192.168.0.184:8888 nginx-1.0.8.targz, pcre-8.13.tar.gz

 

安裝配置過程

  • Nginx安裝

 下載nginx-1.0.8.targz, pcre-8.13.tar.gz這兩個安裝包,並解壓縮到目錄/home/shirdrn/tools下面,然後安裝過程如下所示:

cd /home/shirdrn/tools
tar -xvf pcre-8.13.tar.bz2
tar -xzvf nginx-1.0.8.tar.gz
cd /home/shirdrn/tools/nginx-1.0.8
./configure --with-http_stub_status_module --prefix=/home/shirdrn/servers/nginx --with-pcre=/home/shirdrn/tools/pcre-8.13
make
make install

執行上述命令,需要使用超級用戶權限,將我們的Nginx安裝到/home/shirdrn/servers/nginx-1.0.8下面,由於指定了--with-pcre=/home/shirdrn/tools/pcre-8.13,即pcre的源碼路徑,在安裝的過程首先編譯pcre並安裝,然後纔開始配置安裝Nginx。

驗證是否安裝成功,只需要在瀏覽器輸入http://192.168.0.184:8888/即可,默認Nginx使用80端口,這裏我的80端口被佔用了,所以修改爲8888(有關Nginx的基本配置在下面說明)。

  • Ngin負載均衡配置

 下面,我們看一下我們實現Nginx負載均衡的配置。配置文件爲conf/nginx.conf,由於我們進行的代理的配置,通過使用一個單獨的代理配置文件conf/proxy.conf,在conf/nginx.conf中引入該代理配置即可。

conf/proxy.conf的配置內容如下所示:

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;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   300;
proxy_send_timeout      300;
proxy_read_timeout      300;
proxy_buffer_size       4k;
proxy_buffers           4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

各配置項的含義,可以通過查閱相關文檔瞭解。下面看conf/nginx.conf的配置,我們根據實踐操作所做的修改,並對相關基本配來做適當的說明,如下所示:

user  root root; # Nginx所在的用戶和用戶組

worker_processes  3; # 啓動的工作進程數量

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

pid        logs/nginx.pid; # Nginx進程ID


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    upstream localhost { # 發到localhost上的請求,通過Nginx轉發到實際處理請求的服務器
           server 192.168.0.181:8080 weight=1;
           server 192.168.0.184:8080 weight=1;
    }

    server {
        listen       8888; # Nginx監聽的端口,默認爲80
        server_name  localhost; # Nginx所在主機的名稱

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html/solr; # 請求資源的路徑(代理:/home/shirdrn/servers/nginx/tml/solr/,該目錄下沒有任何數據)
            index  index.html index.htm;
            proxy_pass   http://localhost; # 代理:對發送到localhost上請求進行代理
            include proxy.conf; # 引入proxy.conf配置
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443;
    #    server_name  localhost;

    #    ssl                  on;
    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_timeout  5m;

    #    ssl_protocols  SSLv2 SSLv3 TLSv1;
    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers   on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}
  • 啓動Nginx

啓動Nginx比較簡單,有兩種方式:一種是直接使用默認安裝路徑下的nginx.conf,啓動命令如下所示:

/home/shirdrn/servers/nginx-1.0.8/sbin/nginx

另一種是,nginx.conf配置可以放到其他目錄下面,啓動時通過-c選項指定配置文件路徑即可,啓動命令如下所示:

/home/shirdrn/servers/nginx-1.0.8/sbin/nginx -c /home/shirdrn/servers/nginx-1.0.8/conf/nginx.conf

可以查看啓動進程:

root@dev2:~$ ps -ef | grep nginx
root     15952     1  0 18:56 ?        00:00:00 nginx: master process sbin/nginx
root     15953 15952  0 18:56 ?        00:00:00 nginx: worker process
root     15954 15952  0 18:56 ?        00:00:00 nginx: worker process
root     15955 15952  0 18:56 ?        00:00:00 nginx: worker process
ubuntu   22988 22887  0 22:19 pts/0    00:00:00 grep --color=auto nginx

查看Nginx監聽的端口號:

root@dev2:/home/ubuntu# netstat -nap | grep '8888'
tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      15952/nginx 
  • Tomcat配置

 無論在Windows下還是Linux下,Tomcat的配置無需做額外的配置,只要能夠發佈你的Web應用即可。但是,我們通過Nginx進行反向代理請求,必須保證多個Tomcat下的Web應用的請求路徑相一致,例如,我們配置的兩臺搜索服務器的單獨請求路徑,分別如下所示:

http://192.168.0.174:8080/solr/core0/search/?q=九寨溝&start=0&rows=10
http://192.168.0.181:8080/solr/core0/search/?q=馬爾代夫&start=0&rows=10

我們將我們的搜索服務器程序,分別發佈到這兩臺搜索服務器的Tomcat上,可以通過實際接口進行單獨接收請求並處理。

 

測試驗證

 

下面,來測試一下,驗證我們上述配置的內容,是否能夠按照開始設計的思路,實現負載均衡。由於在Nginx的配置中,我們設置了兩臺搜索服務器處理請求的權重爲1:1,所以在測試的過程中很容易就能看到。由於所有的請求都是先到達代理服務器,通過代理服務器進行轉發,所以對外部只有一個統一的接口:

http://192.168.0.184:8888/solr/core0/search/?q=普吉島&start=0&rows=10

根據代理配置,代理服務器只是轉發請求和相應,而不做請求的處理等工作,所以負荷會小一些。通過負載分攤,兩個搜索服務器的負荷也會比單臺的情況下有所好轉。上面代理的請求鏈接,實際會轉換爲如下兩者之一:

http://192.168.0.174:8080/solr/core0/search/?q=普吉島&start=0&rows=10
http://192.168.0.181:8080/solr/core0/search/?q=普吉島&start=0&rows=10

我們看一下,各臺服務器實際執行時的日誌記錄。如下4個請求:

http://192.168.0.184:8888/solr/core0/search/?q=九寨溝&start=0&rows=10
http://192.168.0.184:8888/solr/core0/search/?q=普吉島&start=0&rows=10
http://192.168.0.184:8888/solr/core0/search/?q=馬爾代夫&start=0&rows=10
http://192.168.0.184:8888/solr/core0/search/?q=西雙版納&start=0&rows=10

Nginx日誌,如下所示:

192.168.0.181 - - [05/Oct/2011:21:42:05 +0800] "GET /solr/core0/search/?q=九寨溝&start=0&rows=10 HTTP/1.1" 200 329495 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30"
192.168.0.181 - - [05/Oct/2011:21:42:12 +0800] "GET /solr/core0/search/?q=普吉島&start=0&rows=10 HTTP/1.1" 200 110349 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30"
192.168.0.181 - - [05/Oct/2011:21:42:25 +0800] "GET /solr/core0/search/?q=馬爾代夫&start=0&rows=10 HTTP/1.1" 200 85572 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30"
192.168.0.181 - - [05/Oct/2011:21:42:32 +0800] "GET /solr/core0/search/?q=西雙版納&start=0&rows=10 HTTP/1.1" 200 141030 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30"

我們看一下,各臺搜索服務器接收請求處理的日誌:
搜索服務器192.168.0.174請求處理日誌:

2011-10-5 21:42:12 org.apache.solr.core.SolrCore execute
信息: [core0] webapp=/solr path=/search/ params={bq=spiderName:baseSeSpider^1.5&start=0&q=普吉島&rows=10} hits=16 status=0 QTime=48 
2011-10-5 21:42:32 org.apache.solr.core.SolrCore execute
信息: [core0] webapp=/solr path=/search/ params={bq=spiderName:baseSeSpider^1.5&start=0&q=西雙版納&rows=10} hits=29 status=0 QTime=54

搜索服務器192.168.0.181請求處理日誌:

2011-10-5 21:42:06 com.chenlb.mmseg4j.solr.MMSegTokenizerFactory newSeg
信息: create new Seg ...
2011-10-5 21:42:06 com.chenlb.mmseg4j.solr.MMSegTokenizerFactory newSeg
信息: use complex mode
2011-10-5 21:42:08 com.chenlb.mmseg4j.solr.MMSegTokenizerFactory newSeg
信息: create new Seg ...
2011-10-5 21:42:08 com.chenlb.mmseg4j.solr.MMSegTokenizerFactory newSeg
信息: use complex mode
2011-10-5 21:42:08 org.apache.solr.core.SolrCore execute
信息: [core0] webapp=/solr path=/search/ params={bq=spiderName:baseSeSpider^1.5&start=0&q=九寨溝0&rows=10} hits=54 status=0 QTime=2116 
2011-10-5 21:42:27 com.chenlb.mmseg4j.solr.MMSegTokenizerFactory newSeg
信息: create new Seg ...
2011-10-5 21:42:27 com.chenlb.mmseg4j.solr.MMSegTokenizerFactory newSeg
信息: use complex mode
2011-10-5 21:42:28 com.chenlb.mmseg4j.solr.MMSegTokenizerFactory newSeg
信息: create new Seg ...
2011-10-5 21:42:28 com.chenlb.mmseg4j.solr.MMSegTokenizerFactory newSeg
信息: use complex mode
2011-10-5 21:42:29 org.apache.solr.core.SolrCore execute
信息: [core0] webapp=/solr path=/search/ params={bq=spiderName:baseSeSpider^1.5&start=0&q=馬爾代夫0&rows=10} hits=57 status=0 QTime=1721 

測試發現,雖然只有4個請求,但是在負載權重相等情況下,很好地分攤到兩臺搜索服務器上去進行請求的實際處理。通過上面日誌可以看出,我們基本實現了一開始設計的思路。

發佈了73 篇原創文章 · 獲贊 19 · 訪問量 110萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章