環境背景:公司業務通過長期發展,有了很大突破,已經實現盈利,現公司要求增強技術架構應用功能和安全性以及開始向企業應用、移動APP等領域延伸,此時原來開發web服務的php語言已經不適應新的場景,須要上java技術架構,現要求你根據公司須要,實現基於java平臺的web應用服務選型、搭建、實現和應用,此時你如何選擇?css
項目實戰系列,總架構圖 http://www.cnblogs.com/along21/p/8000812.htmlhtml
本篇實戰所需的包,都存放在個人網盤中 http://pan.baidu.com/s/1c2B7BO0,須要的私聊我。java
JRE: Java Runtime Environmentlinux
JDK:Java Development Kit JREnginx
JRE顧名思義是java運行時環境,包含了java虛擬機,java基礎類庫。是使用java語言編寫的程序運行所須要的軟件環境,是提供給想運行java程序的用戶使用的。git
JDK顧名思義是java開發工具包,是程序員使用java語言編寫java程序所需的開發工具包,是提供給程序員使用的。JDK包含了JRE,同時還包含了編譯java源碼的編譯器javac,還包含了不少java程序調試和分析的工具:jconsole,jvisualvm等工具軟件,還包含了java程序編寫所需的文檔和demo例子程序。若是你須要運行java程序,只需安裝JRE就能夠了。若是你須要編寫java程序,須要安裝JDK。JRE根據不一樣操做系統(如:windows,linux等)和不一樣JRE提供商(IBM,ORACLE等)有不少版本,最經常使用的是Oracle公司收購SUN公司的JRE版本。程序員
(2)安裝相應版本的rpm包 jdk-VERSION-OS-ARCH.rpmgithub
yum -y localinstall jdk-8u144-linux-x64.rpm
centos7系統自帶:jdk-1.8.0_25-linux-x64.rpm
export JAVA_HOME=/usr/java/jdk1.8.0_144 export JRE_HOME=$JAVA_HOME/jre export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
(1)從官網下載tomcat二進制安裝包 http://tomcat.apache.org/
https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.23/bin/
tar xvf apache-tomcat-8.5.11.tar.gz -C /usr/local/
② 爲了方便管理,設置軟鏈接,若之後換版本了,能夠很容易切換
ln -s /usr/local/apache-tomcat-7.0.78/ /usr/local/tomcat
export CATALINA_BASE=/usr/local/tomcat export PATH=$CATALINA_BASE/bin:$PATH source /etc/profile.d/tomcat.sh 執行加載環境配置
yum install tomcat -y #安裝tomcat主程序 yum install -y tomcat-admin-webapps tomcat-docs-webapp tomcat-webapps #安裝tomcat對應的頁面 mkdir /var/lib/tomcat/webapps/{ROOT,test}/{WEB-INF,META-INF,classes,lib} -pv #建立頁面所須要的工做目錄
webapps存放位置:/var/lib/tomcat/webapps/
環境配置文件:/etc/sysconfig/tomcat #調整jdk內存使用大小等初始值
能夠去開源中國下載本身須要的https://www.oschina.net/
我已經下好一個,須要的私密我http://pan.baidu.com/s/1c2B7BO0
① unzip zchuanzhao-jeesns-master.zip
② mv /jeesns/war/jeesns.war .../webapps 把jeesns.war移到你的tomcat的webapps 下
若是你是自動佈署,會自動在/webapps 下生成jeesns目錄;若不是,能夠本身unzip 解包,佈署
MariaDB [(none)]> create database along;
cd /jeesns/jeesns-web/database/
mysql -uroot -p -D along < jeesns.sql
vim /webapps/jeesns/WEB-INF/classes/jeesns.properties
① 登陸首頁 http://192.168.30.107:8080/jeesns
② 進入後臺管理 http://192.168.30.107:8080/jeesns/manage/login
location / { proxy_pass http://192.168.30.107:8080; } location ~* \.(jsp|do)$ { proxy_pass http://192.168.30.107:8080; }
upstream tomcat_srv { server 192.168.30.107:8080 weight=1; server 192.168.30.7:8080 weight=2; }
location / { proxy_pass http://tomcat_srv; } location ~* \.(jsp|do)$ { proxy_pass http://tomcat_srv; }
<%@ page language="java" %> <%@ page import="java.util.*" %> <html> <head> <title>Test Page</title> </head> <body> <% out.println("hello world");%> </body> </html>
<%@ page language="java" %> <%@ page import="java.util.*" %> <html> <head> <title>Test Page</title> </head> <body> <% out.println("hello world2");%> </body> </html>
(1) session sticky(貼) 基於hash 和cookie 來實現會話保持,簡單的負載均衡算法
nginx: ip_hash 、 haproxy: source 、 lvs: sh
② 基於cookie nginx基於cookie實現,需加載cookie模塊,cookie 力度更新
(2) session cluster:delta session manager 基於tomcat集羣會話保持
分析:tomcat自身帶的機制 session cluster,基於組播的方式,一個tomcat 被用戶登陸訪問,記錄session;經過組播給集羣中的其餘機器複製一份;那麼當用戶再次訪問時,每一個機器都有session 會話記錄;從而實現了會話保持
(3) session server:redis(store), memcached(cache) 共享存儲
分析:新創建一個存放各個tomcat session記錄的server,每臺tomcat服務器都將本身的session記錄在這個服務器中,用戶再次訪問,每臺tomcat 都從這個server中獲取;實現會話保持
vim /etc/nginx/nginx.conf 只需加一條ip_hash便可
upstream tomcat_srv { ip_hash; server 192.168.30.107:8080 weight=1; server 192.168.30.7:8080 weight=2; }
訪問頁面,一直匹配到107的server 上,沒有輪詢;會話保持成功
原理:Tomcat集羣的會話管理器,它經過將改變了會話數據同步給集羣中的其它節點實現會話複製。這種實現會將全部會話的改變同步給集羣中的每個節點
機器名稱 |
IP配置 |
服務角色 |
備註 |
nginx |
192.168.30.107 |
代理服務器 |
開啓代理功能 |
tomcat-srv1 |
192.168.30.106 |
web服務 |
配置集羣會話 |
tomcat-srv2 |
192.168.30.7 |
web服務 |
配置集羣會話 |
upstream tomcat_srv { #在http 段配置 server 192.168.30.106:8080 weight=1; server 192.168.30.7:8080 weight=2; } location / { #在server 段配置 proxy_pass http://tomcat_srv; } location ~* \.(jsp|do)$ { proxy_pass http://tomcat_srv; }
注意:兩臺tomcat-srv的配置是如出一轍的,除了測試的頁面設置不一樣
cd /usr/local/tomcat/ 進入本身的tomcat 的目錄下
vim conf/server.xml 在Engine 引擎段中,添加下面代碼,注意:註釋千萬別加去
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> 定義集羣節點,「8」表示異步 <Manager className="org.apache.catalina.ha.session.DeltaManager" 定義Manger採用DeltaManager 會話管理器 expireSessionsOnShutdown="false" 一個節點關閉,不影響集羣其餘session notifyListenersOnReplication="true"/> 複製、刪除操做通知session listener <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter="/"/> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>
(1)Cluster配置:
Cluster(集羣,族) 節點,若是你要配置tomcat集羣,則須要使用此節點.
className 表示tomcat集羣時,之間相互傳遞信息使用那個類來實現信息之間的傳遞.
channelSendOptions能夠設置爲二、四、八、10,每一個數字表明一種方式
2 = Channel.SEND_OPTIONS_USE_ACK(確認發送)
4 = Channel.SEND_OPTIONS_SYNCHRONIZED_ACK(同步發送)
8 = Channel.SEND_OPTIONS_ASYNCHRONOUS(異步發送)
在異步模式下,能夠經過加上確認發送(Acknowledge)來提升可靠性,此時channelSendOptions設爲10,半同步
例:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
(2)Manager
Manger對象用於實現HTTP會話管理的功能,Tomcat中有4種Manger的實現:
Tomcat6的默認會話管理器,用於非集羣環境中對單個處於運行狀態的Tomcat實例會話進行管理。當Tomcat關閉時,這些會話相關的數據會被寫入磁盤上的一個名叫SESSION.ser的文件,並在Tomcat下次啓動時讀取此文件。
當一個會話長時間處於空閒狀態時會被寫入到swap會話對象,這對於內存資源比較吃緊的應用環境來講比較有用。
用於Tomcat集羣的會話管理器,它經過將改變了會話數據同步給集羣中的其它節點實現會話複製。這種實現會將全部會話的改變同步給集羣中的每個節點,也是在集羣環境中用得最多的一種實現方式。
用於Tomcat集羣的會話管理器,與DeltaManager不一樣的是,某節點會話的改變只會同步給集羣中的另外一個而非全部節點
className-指定實現org.apache.catalina.ha.ClusterManager接口的類,信息之間的管理
expireSessionsOnShutdown-設置爲true時,一個節點關閉,將致使集羣下的全部Session失效
notifyListenersOnReplication-集羣下節點間的Session複製、刪除操做,是否通知session listeners
(3)Channel 頻道的介紹和配置
Channel是Tomcat節點之間進行通信的工具。Channel包括4個組件:
① Membership:維護集羣的可用節點列表,它能夠檢查到新增的節點,也能夠檢查到沒有心跳的節點
⑤ frequency-發送心跳(向組播地址發送UDP數據包)的時間間隔(單位:ms)。默認值爲500
⑥ dropTime-Membership在dropTime(單位:ms)內未收到某一節點的心跳,則將該節點從可用節點列表刪除。默認值爲3000
注:組播(Multicast):一個發送者和多個接收者之間實現一對多的網絡鏈接。
一個發送者同時給多個接收者傳輸相同的數據,只需複製一份相同的數據包。
相同組播地址、端口的Tomcat節點,能夠組成集羣下的子集羣
<Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/>
接收器分爲兩種:BioReceiver(阻塞式)、NioReceiver(非阻塞式)
className-指定Receiver使用的類
address-接收消息的地址
port-接收消息的端口
autoBind-端口的變化區間
若是port爲4000,autoBind爲100,接收器將在4000-4099間取一個端口,進行監聽
selectorTimeout-NioReceiver內輪詢的超時時間
maxThreads-線程池的最大線程數
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/>
Sender內嵌了Transport組件,Transport真正負責發送消息
Transport分爲兩種:bio.PooledMultiSender(阻塞式)、nio.PooledParallelSender(非阻塞式)
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender>
① TcpFailureDetector-網絡、系統比較繁忙時,Membership可能沒法及時更新可用節點列表,此時TcpFailureDetector能夠攔截到某個節點關閉的信息,並嘗試經過TCP鏈接到此節點,以確保此節點真正關閉,從而更新集羣能夠用節點列表
② MessageDispatch15Interceptor-查看Cluster組件發送消息的方式是否設置爲Channel.SEND_OPTIONS_ASYNCHRONOUS(Cluster標籤下的channelSendOptions爲8時)。 設置爲Channel.SEND_OPTIONS_ASYNCHRONOUS時,MessageDispatch15Interceptor先將等待發送的消息進行排隊,而後將排好隊的消息轉給Sender
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
(4)ClusterListener 配置
ClusterListener : 監聽器,監聽Cluster組件接收的消息
使用DeltaManager時,Cluster接收的信息經過ClusterSessionListener傳遞給DeltaManager
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
cp /usr/local/tomcat/conf/web.xml WEB-INF/
vim WEB-INF/web.xml 在</web-app>上加一行
② vim session.jsp 建立測試頁面,在tomcat-srv1上是TomcatA;在tomcat-srv1上是TomcatB
<%@ page language="java" %> <html> <head><title>TomcatA</title></head> //TomcatA的標題 <body> <h1><font color="blue">TomcatA </h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("abc","abc"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>
頁面訪問http://192.168.30.107/test/session.jsp;輪詢,可是session ID是同樣的,會話保持成功
原理:新創建一個存放各個tomcat session記錄的server,每臺tomcat服務器都將本身的session記錄在這個服務器中,用戶再次訪問,每臺tomcat 都從這個server中獲取;實現會話保持
機器名稱 |
IP配置 |
服務角色 |
備註 |
nginx |
192.168.30.107 |
代理服務器 |
開啓代理功能 |
tomcat-srv1 |
192.168.30.106 |
web服務 |
指向共享存儲 |
tomcat-srv2 |
192.168.30.7 |
web服務 |
指向共享存儲 |
memcached |
192.168.30.6 |
共享存儲 |
|
memcached-session-manager項目地址,http://code.google.com/p/memcached-session-manager/, https://github.com/magro/memcached-session-manager
① 下載以下jar文件至各tomcat節點的tomcat安裝目錄下的lib目錄中,尋找本身須要的版本號,tc的版本號要與tomcat版本相同。
memcached-session-manager-1.8.3.jar
memcached-session-manager-tc7-1.8.3.jar
spymemcached-2.11.1.jar
msm-javolution-serializer-1.8.3.jar
javolution-5.4.3.1.jar
我已經下到了個人網盤,有須要的私聊 http://pan.baidu.com/s/1nvGFgKD
upstream tomcat_srv { #在http 段配置 server 192.168.30.106:8080 weight=1; server 192.168.30.7:8080 weight=2; } location / { #在server 段配置 proxy_pass http://tomcat_srv; } location ~* \.(jsp|do)$ { proxy_pass http://tomcat_srv; }
vim /usr/local/tomcat/conf/server.xml
<Context path="/test" docBase="test" reloadable="true"> <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="192.168.30.106:11211" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"/> </Context>
頁面訪問http://192.168.30.107/test/session.jsp;輪詢,可是session ID是同樣的,會話保持成功