目錄php
一、高可用、負載均衡、可擴展架構的須要背景css
二、系統架構html
三、系統規劃及說明前端
四、系統部署及測試java
五、總結mysql
一、高可用、負載均衡、可擴展架構的須要背景linux
從互聯網誕生以來,網站架構隨着互聯網的快速發展發生着巨大的變化,現今,數據天天都在以爆炸式的增加,大數據、雲計算等概念被業內炒得沸沸揚揚,這些前沿技術也在各行各業落地開花。每一種新技術的提出幾乎都會或多或少影響着IT的基礎架構,面對數據的快速增加、咱們急需一套高可用、負載均衡、可擴展的架構來做爲支撐。nginx
二、系統架構web
這次博文介紹一套高可用、負載均衡、可擴展的系統架構方案,此方案能知足多數企業須要,並能隨着業務的變化進行系統擴展,並儘可能避免單點故障,發架設在此係統上的應用能實現365*7*24服務不中斷。架構上對應用進行了拆分,以下的架構圖:redis
第一層:負載均衡層,此層是用戶的入口,此處的服務器擔任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。
三、系統規劃及說明
這次博文不會把涉及系統部署的所有過程都描述,只是把重要的部分進行記錄與講解。
這次測試中所使用的服務器信息整理以下表:
說明:這次用兩主機配置成tomcat容器提供jsp程序的運行環境,而且在主機上安裝httpd,用反向代理的方式向前端的tengine反向代理提供服務,測試環境中mysql服務器只有規劃了一臺,在實際生產環境下請用主從架構或MMM等有架構,nod1和nod2主機上還部署了memcached服務,它主要是在爲了給tomcat中的session信息做高可用的,這次採用是MSM(Memcached Session Manager)方案實現tomcat中對session的高可用;nod3與nod4利用tengine提供反向代理的功能,keepalived實現tengine的高可用,以免單點故障。
四、系統部署及測試
雖然說在系統部署上沒有嚴格要求有什麼前後順序,但按照必定的順序來部署會讓工做變得簡單有序,這讓你對整個項目有了全局觀,對項目管理人員來講能更好的協調人員,能更好的掌握控制項目的進度。通常按照如下順序來部署:
a)、部署分佈式文件系統,這次博文不討論這部分;
b)、數據庫系統部署;
c)、應用服務器部署;
d)、director部署;
固然有些是有交集的,但基本要遵循「前後端再前端」的大原則,即先部署後端的服務應用,再去部署前端面的服務和應用。
4.一、分佈式文件部署
這個能夠根據本身熟悉的開源系統來部署。MooseFS是一個不錯的選擇。部署過程此博文不討論,略。。。。
4.二、數據庫及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.三、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 "%r" %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.四、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_p_w_picpath_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_p_w_picpath_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 { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc 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 { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc 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節點搶佔。
五、總結
此套系統部署完後,有如下優勢:
a)、用戶的接入端面實現了高可用,一個負載均衡器出現故障不會影響業務;
b)、web應用層可根據訪問壓力伸縮服務器;
c)、數據庫層若是壓力大了,只要jsp程序支持,能夠加memcached緩存緩解mysql的壓力,若是多讀壓力還大時,若是後端服務器的讀壓力仍是大,那就加讀寫分離的中間件;
d)、分佈文件系統也可隨着業務的變化而進行擴容、減容。
最後此套系統還差一套報警監控系統,時時監控各服務器的運行狀態,一旦有服務器負載太高或發生宕機,能夠直接通知管理人員,以便處理故障。
監控能夠從如下幾個維度來描述:
第1、上班時間能夠打開一個監控頁面時時查看;
第2、打開郵件客戶端,定時刷新以收取報警郵件;
第3、下班後手機24小開機,能夠經過短信貓的形式接收報警短信。