tengine整合tomcat加上memcached實現高併發、負載均衡、可擴展架構接

1、高可用、負載均衡、可擴展架構的需要背景

2、系統架構

3、系統規劃及說明

4、系統部署及測試

5、總結


1、高可用、負載均衡、可擴展架構的需要背景

    從互聯網誕生以來,網站架構隨着互聯網的快速發展發生着巨大的變化,現今,數據每天都在以爆炸式的增長,大數據、雲計算等概念被業內炒得沸沸揚揚,這些前沿技術也在各行各業落地開花。每一種新技術的提出幾乎都會或多或少影響着IT的基礎架構,面對數據的快速增長、我們急需一套高可用、負載均衡、可擴展的架構來作爲支撐。

2、系統架構

    此次博文介紹一套高可用、負載均衡、可擴展的系統架構方案,此方案能滿足多數企業需要,並能隨着業務的變化進行系統擴展,並儘量避免單點故障,發架設在此係統上的應用能實現365*7*24服務不中斷。架構上對應用進行了拆分,如下的架構圖:

技術分享

第一層:負載均衡層,此層是用戶的入口,此處的服務器擔任director的角色,它把用戶的請求根據其調度算法調度到後端的服務器上,能勝任調度器的開源軟件有LVS、Haproxy、Nginx、Tengine等,爲了避免單點故障,director需要做高可用,在開源軟件有Hertbeat、keepalived等;

第二層:web應用層,這一層是部署具體web應用的,一般常見的web應用有httpd、php、tomcat、nginxt等,這個層次把具有各種不同的運用劃分成一個組,這個組能提供相同的web服務,配合第一層就能實現負載均衡和故障隔離的效果;

第三層:數據庫層,這裏是在提供動態站點時程序與數據庫交互數據的地方,在這個層次上一般所用的開源軟件有mysql、mariadb、redis、nosql類的數據庫等,數據庫的設計上也應該考慮到高可用性,負載均衡功能,比如mysql的主從架構,MMM架構,或爲了實現讀寫分離,引入中間件淘寶的amoeba、奇虎360的Atlas;

第四層:分佈式文件系統層,這個系統主要是爲解決web應用數據共享的,當然數據庫層中需要持久化的數據也可以放在分分佈式文件系統中,開源軟件有MooseFs、MgileFS、GlusterFS、FastDFS、GFS、TFS等。

如果網站隨着用戶的增多,web應用服務器和數據庫服務器的壓力越來越大,那就需要考慮加入緩存層,在web應用程序前端可加入緩存web靜態數據的緩存層,開源解決方案有squid、varnish、ats等,ats是yahoo向ASF貢獻的一個項目;在數據庫層的前端也可加入緩存層,用來緩存web應用程序從數據庫中查詢的數據,可以把查詢的sql語句和結果存放在一個緩存中,一般所用的服務是memcached。

3、系統規劃及說明

    此次博文不會把涉及系統部署的全部過程都描述,只是把重要的部分進行記錄與講解。

此次測試中所使用的服務器信息整理如下表:

技術分享

說明:此次用兩主機配置成tomcat容器提供jsp程序的運行環境,並且在主機上安裝httpd,用反向代理的方式向前端的tengine反向代理提供服務,測試環境中mysql服務器只有規劃了一臺,在實際生產環境下請用主從架構或MMM等有架構,nod1和nod2主機上還部署了memcached服務,它主要是在爲了給tomcat中的session信息作高可用的,此次採用是MSM(Memcached Session Manager)方案實現tomcat中對session的高可用;nod3與nod4利用tengine提供反向代理的功能,keepalived實現tengine的高可用,以避免單點故障。

4、系統部署及測試

    雖說在系統部署上沒有嚴格要求有什麼先後順序,但按照一定的順序來部署會讓工作變得簡單有序,這讓你對整個項目有了全局觀,對項目管理人員來說能更好的協調人員,能更好的掌握控制項目的進度。一般按照以下順序來部署:

a)、部署分佈式文件系統,此次博文不討論這部分;

b)、數據庫系統部署;

c)、應用服務器部署;

d)、director部署;

當然有些是有交集的,但基本要遵循“先後端再前端”的大原則,即先部署後端的服務應用,再去部署前端面的服務和應用。

4.1、分佈式文件部署

    這個可以根據自己熟悉的開源系統來部署。MooseFS是一個不錯的選擇。部署過程此博文不討論,略。。。。

4.2、數據庫及memcached部署

請參照前邊的博文進行mysql主從架構的部署,此次使用單一的mysql進行測試。mysql主從架構搭建博文地址:http://zhaochj.blog.51cto.com/368705/1635982

數據庫搭建好後,創建一個供測試的數據庫,並建立一個用戶供測試站點的使用。

memcached直接用yum源中進行安裝(nod1與nod2安裝方式相同):

[root@nod1 ~]# yum -y install memcached
[root@nod1 ~]# service memcached start
[root@nod1 ~]# netstat -tnl | grep 11211
tcp        0      0 0.0.0.0:11211               0.0.0.0:*                   LISTEN      
tcp        0      0 :::11211                    :::*                        LISTEN

4.3、apache+tomcat部署

nod0與nod2上tomcat與httpd的部署相同,只是在配置參數上有點不同。

jdk安裝配置:

[root@nod0 msm]# pwd
/root/software/msm
[root@nod0 msm]# rpm -ivh jdk-8u45-linux-x64.rpm
[root@nod0 msm]# vim /etc/profile.d/java.sh
JAVA_HOME=/usr/java/jdk1.8.0_45
export PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME
[root@nod0 msm]# source /etc/profile.d/java.sh
[root@nod0 msm]# java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

tomcat安裝配置:

[root@nod0 msm]# tar -xf apache-tomcat-7.0.62.tar.gz -C /usr/local/
[root@nod0 local]# ln -sv apache-tomcat-7.0.62 tomcat
[root@nod0 local]# vim /etc/profile.d/tomcat.sh
CATALINA_HOME=/usr/local/tomcat
export PATH=$CATALINA_HOME/bin:$PATH
export CATALINA_HOME
[root@nod0 local]# source /etc/profile.d/tomcat.sh
[root@nod0 local]# catalina.sh version
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/java/jdk1.8.0_45
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Server version: Apache Tomcat/7.0.62
Server built:   May 7 2015 17:14:55 UTC
Server number:  7.0.62.0
OS Name:        Linux
OS Version:     2.6.32-358.el6.x86_64
Architecture:   amd64
JVM Version:    1.8.0_45-b14
JVM Vendor:     Oracle Corporation
[root@nod0 msm]# vim /etc/rc.d/init.d/tomcat   #服務腳本
#!/bin/sh
#Description: This shell script manage apache tomcat.
#Author: zhaochj
#Time: 2015-4-21
#Version: 1.0
case $1 in
    ‘start‘)
        /usr/local/tomcat/bin/catalina.sh start
        ;;
    ‘stop‘)
        /usr/local/tomcat/bin/catalina.sh stop
        ;;
    ‘restart‘)
        /usr/local/tomcat/bin/catalina.sh stop
        sleep 3
        /usr/local/tomcat/bin/catalina.sh start
        ;;
    *)
        echo "Usage:`basename $0` {start|stop|restart}"
        exit 1
        ;;
esac
[root@nod0 msm]# chmod +x /etc/rc.d/init.d/tomcat

至此,jdk與tomcat安裝完畢。

配置server.xml文件,使其再提供一個<Service>元素,這個不是必須,我只是爲了保留原始server.conf的配置,通過增加一個<Service>元素可以讓tomcat以一種協議監聽在不同的端口,而tomcat實例又只有一個,在配置文件夾的</Service>後增加如下代碼:

<Service name="Catalina2">
    <Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8444" />
        <Engine name="Catalina2" defaultHost="192.168.0.200" jvmRoute="jvm200">
            <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                   resourceName="UserDatabase"/>
            </Realm>
              <Host name="192.168.0.200"  appBase="/tomcat/app"
                    unpackWARs="true" autoDeploy="true">
                  <Context path="" docBase="mysite"/>
                  <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                         prefix="nod0_access_log." suffix=".txt"
                         pattern="%h %l %u %t &quot;%r&quot; %s %b" />
              </Host>
        </Engine>
  </Service>

這個<Service>中擁有自己的http連接器,自己的虛擬主機,爲了安全可以把默認的連接器註釋掉,也可用mod_jk的方式通過ajp13協議與tomcat結合,但我在嘗試這樣做時,用mod_jk模塊能夠正常加載,但就是無法發現後端tomcat中的“jvmRoute=jvm200”引擎,所以才用proxy_module中的proxy_http_module的方式與tomcat整合。

配置tomcat,使其成爲MSM環境:

根據tomcat的版本去http://code.google.com/p/memcached-session-manager/wiki/SetupAndConfiguration下載相應的jar包,就是下邊的這些包

[root@nod0 msm]# ls msm_kryo_serializers/
asm-3.2.jar                memcached-session-manager-1.8.3.jar      msm-kryo-serializer-1.8.3.jar
kryo-1.04.jar              memcached-session-manager-tc7-1.8.3.jar  reflectasm-1.01.jar
kryo-serializers-0.11.jar  minlog-1.2.jar                           spymemcached-2.11.1.jar

把這些jar包全部拷貝到$CATALINA_HOME/lib目錄下

[root@nod0 msm]# scp msm_kryo_serializers/* /usr/local/tomcat/lib/

再去編輯$CATALINA_HOME/conf/context.xml文件,使其配置memcached的相應功能(這裏是以粘性的session的方式配置)

[root@nod0 msm]# vim /usr/local/tomcat/conf/context.xml
<Context>
......
<!-- sticky session.-->
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
             memcachedNodes="memcached1:192.168.0.201:11211,memcached2:192.168.0.202:11211"
             failoverNodes="memcached1"
             requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
             transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"/>
....
</Context>

最後把jsp測試程序拷貝到server.xml配置文件中虛擬主機的網站目錄“/tomcat/app/mysite”下,這次測試我用的是shopxx這個jsp程序。

一切準備好後就可以記動tomcat進行測試站點的安裝了。這裏我是把tomcat中該配置的都配置完後再啓用的tomcat,其實在真正的實施過程中,你應該每修改一次配置文件你都要一邊監控着日誌輸出,再去啓用tomcat服務,看啓動的過程中是否有警告、錯誤的信息,不要等你把配置文件修改得過多,一啓動服務報錯,而報的錯又不是很好定位時,那你就只能慢慢排查了,然而,當我更改了一部份配置文件,只要此修改會改變tomcat的運行屬性,那我就去啓動一下tomcat,看日誌是否有問題,沒有問題再去做別的修改,這樣即使有問題也比較好排查。

httpd反向代理tomcat部分:

先註釋掉中心主機,即在http.conf配置文件中註釋掉“DocumentRoot /var/www/html”這一行,再啓用一箇中心主機配置文件

[root@nod0 msm]# vim /etc/httpd/conf.d/virtual.conf 
<VirtualHost *:80>
    DocumentRoot /tomcat/app/mysite
    ServerName www.test.com
    ProxyVia Off
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8081/
    ProxyPa***everse / http://127.0.0.1:8081/
</VirtualHost>

經過上邊對tomcat與httpd的配置後,打開瀏覽器直接訪問"http://nod0ipaddress"就可以訪問我們部署的網站。

在另外的nod2節點上也按照上邊的操作進行配置,只是有幾點值得注意,如果是以mod_jk的方式反向代理tomcat,那server.xml中的"jvmRoute="jvm200""這裏的值可不能與nod0上配置一樣,還有這是nod2上jsp網站程序的安裝問題,直接把nod0上的已安裝過的站點程序拷貝過來就行了,不要再試着去連接數據進行安裝(這樣是錯誤的操作)。

4.4、Tengine+Keepalived部署

    taobao對nginx做了衆多的改進,在nginx中有些需要打第三方補丁才能實現的功能,而Tengine自身就自帶了,還有在nginx的wiki中明明看到能使用的指令,但你配置後,語法檢測是無法通過的,如果檢查語法無誤後,那這個指令只供商業訂閱才支持的,只是在官方wiki中沒有說明,老版本的文檔中有此說明,不過好在都可以通過一些第三方模塊實現相應的功能。而Tengine就不樣,沒有商業訂閱這一說,而且Tengine還引進了更好的內存管理機制,即jemalloc,所以你完全可以選擇Tengine來代替nginx。

    要想Tengine支持jemalloc,那先要下載此程序,再編譯Tengine時把此程序編譯進來即可,下載地址:http://www.canonware.com/download/jemalloc/

[root@nod3 tengine]# pwd
/root/software/tengine
[root@nod3 tengine]# tar -xf jemalloc-3.6.0.tar.bz2 -C /usr/local/   #jemalloc只需要解壓出來,不需要安裝
[root@nod3 tengine]# yum -y install pcre-devel gd-devel  #先處理依賴關係
[root@nod3 tengine]# tar xf tengine-2.1.0.tar.gz
[root@nod3 tengine]# cd tengine-2.1.0
[root@nod3 tengine-2.1.0]# ./configure --prefix=/usr/local/tengine \ 
--sbin-path=/usr/local/tengine/sbin/nginx --conf-path=/etc/tengine/nginx.conf --error-log-path=/var/log/tengine/error.log --http-log-path=/var/log/tengine/access.log --pid-path=/var/run/tengine.pid --lock-path=/var/lock/subsys/tengine --user=nginx --group=nginx --with-file-aio --with-http_ssl_module --with-http_spdy_module --with-http_image_filter_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_image_filter_module=shared --with-http_sub_module=shared --with-http_flv_module=shared --with-http_mp4_module=shared --with-http_rewrite_module=shared --with-http_fastcgi_module=shared --http-client-body-temp-path=/var/tmp/tengine/client --http-proxy-temp-path=/var/tmp/tengine/proxy --http-fastcgi-temp-path=/var/tmp/tengine/fastcgi --http-uwsgi-temp-path=/var/tmp/tengine/uwsgi --with-pcre --dso-path=/usr/local/tengine/dsomodule/dso --dso-tool-path=/usr/local/tengine/dsomodule/dsotool --with-jemalloc --with-jemalloc=/usr/local/jemalloc-3.6.0
[root@nod3 tengine-2.1.0]# make
[root@nod3 tengine-2.1.0]# make dso_install
[root@nod3 tengine-2.1.0]# make install
[root@nod3 tengine-2.1.0]# mkdir -pv /var/tmp/tengine/{proxy,fastcgi,uwsgi}
[root@nod3 tengine-2.1.0]# /usr/local/tengine/sbin/nginx -v
Tengine version: Tengine/2.1.0 (nginx/1.6.2)

編譯配置文件,例其成爲反向代理服務器:

[root@nod3 tengine-2.1.0]# vim /etc/tengine/nginx.conf  #配置文件中確保有以下代碼
......
http {
.......
    upstream be_server1 { 
        consistent_hash $request_uri; 
        server 192.168.0.200:80 id=1000 weight=1;
        server 192.168.0.202:80 id=1001 weight=1;
        check interval=3000 rise=2 fall=5 timeout=1000 type=http;
        check_http_send "HEAD / HTTP/1.0\r\n\r\n";
        check_keepalive_requests 100;
        check_http_expect_alive http_2xx http_3xx;
        }
    server {
        listen 80;
        servern_ame www.test.com;
        location / {
            proxypass / http://be_server1;
            }
        location /status {
            check_status;
            access_log off;
            allow 192.168.0.0/24;
            deny all;
        }
    }
........
}

註釋:tengine在upstream模塊中引進了一致性hash算法來實現對上游服務器的負載均衡,nginx好像只有ip hash,least_conn、sticky cookie三種方式。

配置好後就可以啓動tengine

[root@nod3 tengine-2.1.0]# /usr/local/tengine/sbin/nginx   #啓動tengine
[root@nod3 tengine-2.1.0]# /usr/local/tengine/sbin/nginx -t  #測試配置文件
[root@nod3 tengine-2.1.0]# /usr/local/tengine/sbin/nginx  -s {stop|quit||reopen|reload|}

測試通過訪問tengine的IP看能否訪問到我們在tomcat上部署的網站,還可以打來tengine的狀態頁面查看上游服務器的狀態,如下:

技術分享

以同樣的方法在nod4上完成部署。

最後來部署keepalived讓tengine具有高可用性:

[root@nod3 ~]# yum -y install keepalived  #以yum方式安裝
[root@nod3 ~]# rpm -qa keepalived
keepalived-1.2.13-5.el6_6.x86_64
[root@nod3 ~]# vim /etc/keepalived/keepalived.conf

保配置文件中有以下代碼,主要是vrrp_instance實例的代碼段

! Configuration File for keepalived
global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id TENGINE_203
}
 
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 123
    priority 180
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.0.111
    }
}

而nod4中的代碼段如下:

[root@nod4 keepalived]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id TENGINE_204
}
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 123
    priority 179
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.0.111
    }
}

關於keepalived更詳細的配置說明請查看http://zhaochj.blog.51cto.com/368705/1655449

兩個節點的keepalived配置好後就啓動keepalived服務,虛擬Ip應該是配置在MASTER節點上的,測試時把MASTER節點的keepalived服務關閉,再觀察虛擬ip是否會被BACKUP節點搶佔。

5、總結

    此套系統部署完後,有以下優點:

a)、用戶的接入端面實現了高可用,一個負載均衡器出現故障不會影響業務;

b)、web應用層可根據訪問壓力伸縮服務器;

c)、數據庫層如果壓力大了,只要jsp程序支持,可以加memcached緩存緩解mysql的壓力,如果多讀壓力還大時,如果後端服務器的讀壓力還是大,那就加讀寫分離的中間件;

d)、分佈文件系統也可隨着業務的變化而進行擴容、減容。

最後此套系統還差一套報警監控系統,時時監控各服務器的運行狀態,一旦有服務器負載過高或發生宕機,可以直接通知管理人員,以便處理故障。

監控可以從以下幾個維度來描述:

第一、上班時間可以打開一個監控頁面時時查看;

第二、打開郵件客戶端,定時刷新以收取報警郵件;

第三、下班後手機24小開機,可以通過短信貓的形式接收報警短信。


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