一、前置知識:Web 技術演進
-
C/S vs B/S
– C/S:Socket 編程,QQ、迅雷等,通信層 TCP/UDP,協議私有。
– B/S:瀏覽器 + HTTP,文本協議跨網絡。 -
動態網頁誕生
早期靜態 HTML → 1990 年 HTTP + 瀏覽器 → 1995 年 JavaScript → CGI → ASP/PHP/JSP,邏輯搬到服務器,Browser/Server 模式形成。
二、前端三劍客:HTML / CSS / JavaScript
-
HTML:超文本標記語言,標簽 + 數據。
-
CSS:層疊樣式表,解決 HTML 臃腫,1996 CSS1、1998 CSS2、CSS3 模塊化。
-
JavaScript:
– 1995 LiveScript → JavaScript;1997 ECMAScript 標準。
– 2008 Chrome V8 引擎本地編譯,2009 Node.js 誕生 → JS 可以寫后端。
– Ajax(1999):XMLHttpRequest + JS 實現局部刷新,前后端徹底分離。
三、Web 框架與訪問模式
-
資源劃分
PC/手機瀏覽器:
– 靜態文件 → 靜態服務器
– 圖片 → 圖片服務器
– 動態內容 → 業務服務器(Tomcat 等)手機 App:
– 靜態資源內置包,必要時才訪問圖片/業務服務器。 -
典型調用鏈
瀏覽器 → Nginx(80) → (靜態)
→ (動態)Tomcat(8080) → DB
四、后臺架構演進
-
單體架構
– 所有功能打包成一個 war;橫向擴展復制多份 + 負載均衡。
– 缺點:一處修改全站重啟,耦合高。 -
微服務
– 把單體按業務拆成獨立服務;獨立數據庫;HTTP/REST 通信。
– 優點:小團隊、獨立部署、技術異構。
– 缺點:分布式事務、運維復雜度、監控鏈路。
– 框架:Dubbo(RPC + ZooKeeper)、Spring Cloud(HTTP REST + Eureka)。
五、Tomcat 全景速覽
? 1999 年起源于 Sun JWS → 貢獻 Apache → 合并 JServ → 頂級項目。
? 僅實現 Servlet/JSP 規范,不完整 JavaEE。
? 重要版本:3.0(Servlet2.2/JSP1.1) → 4.x(Catalina/Jasper) → 9.x。
? 官方:http://tomcat.apache.org
六、Tomcat 安裝
-
安裝 JDK
[root]# yum install java-1.8.0-openjdk.x86_64 -y -
解壓并做軟鏈
[root]# tar zxf apache-tomcat-9.0.91.tar.gz -C /usr/local/
[root]# ln -s /usr/local/apache-tomcat-9.0.91 /usr/local/tomcat -
啟動
[root]# /usr/local/tomcat/bin/startup.sh -
驗證端口
[root]# netstat -antlupe | grep java
tcp6 0 0 :::8080 :::* LISTEN 32887/java -
瀏覽器訪問
http://服務器IP:8080 → 出現 Tomcat 歡迎頁。
七、目錄結構逐目錄說明

bin 啟動/關閉腳本 (startup.sh shutdown.sh catalina.sh)
conf 配置文件 (server.xml context.xml web.xml tomcat-users.xml)
lib Tomcat 自身以及全局 jar
logs catalina.out、localhost.log、access_log 等
webapps 應用部署目錄,/webapps/ROOT 默認首頁
work JSP 編譯后生成的 servlet 類文件
temp 運行期臨時目錄
八、systemd 啟動腳本制作
-
新建環境變量文件
cat > /usr/local/tomcat/conf/tomcat.conf <<EOF
JAVA_HOME=/etc/alternatives/jre_openjdk
EOF -
新建 systemd unit
cat > /lib/systemd/system/tomcat.service <<'EOF'
[Unit]
Description=Tomcat
After=syslog.target network.target[Service]
Type=forking
EnvironmentFile=/usr/local/tomcat/conf/tomcat.conf
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/usr/local/tomcat/bin/shutdown.sh
PrivateTmp=true
User=tomcat
Group=tomcat[Install]
WantedBy=multi-user.target
EOF -
加載并開機自啟
systemctl daemon-reload
systemctl enable --now tomcat
九、結合反向代理部署(Nginx)
-
單機反向代理
location ~ .jsp$ {
proxy_pass http://127.0.0.1:8080;
} -
靜態 + 動態分離
server {
root /webdata/nginx/html;
location / { try_files uriuri/ =404; }
location ~ .jsp$ { proxy_pass http://tomcat; }
}
十、負載均衡與會話漂移
-
HTTP 特點
– 無狀態:服務器默認記不住兩次請求。
– 有連接:基于 TCP,三次握手。
– 短連接:HTTP/1.0 一次請求一次連接;HTTP/1.1 keep-alive 復用。 -
負載均衡配置(Nginx)
upstream tomcat {
ip_hash; # 或 hash $cookie_JSESSIONID;
server 192.168.65.131:8080;
server 192.168.65.132:8080;
} -
問題
ip_hash 會導致:
– 客戶端出口 IP 變化 → 漂移;
– 單節點故障 → 會話丟失。
因此需要集中式 Session 存儲。
十一、Memcached 緩存系統
-
特點
– 內存 Key-Value,最大 1 MB/對象;
– 支持多語言客戶端;
– 基于 libevent,高并發;
– 無持久化,可通過集群同步實現高可用。 -
安裝與啟動
yum install memcached -y
vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 0.0.0.0,::1"
systemctl enable --now memcached
-
常用命令示例(telnet localhost 11211)
add leekey 0 60 4
test
get leekey
set leekey 0 60 5
test1
delete leekey
flush_all
十二、msm(memcached-session-manager)實現 Session 共享
-
原理
– Tomcat 把 Session 序列化后寫入 Memcached;
– 多個 Tomcat 共用同一份 Session,故障無丟失;
– 支持 Tomcat 6/7/8/9,官方推薦 Kryo 序列化。 -
所需 jar(全部放到 $CATALINA_HOME/lib)
kryo-3.0.3.jar
asm-5.2.jar
objenesis-2.6.jar
reflectasm-1.11.9.jar
minlog-1.3.1.jar
kryo-serializers-0.45.jar
msm-kryo-serializer-2.3.2.jar
memcached-session-manager-tc9-2.3.2.jar
spymemcached-2.12.3.jar
memcached-session-manager-2.3.2.jar -
context.xml 修改
Tomcat-1:
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:172.25.254.10:11211,n2:172.25.254.20:11211" failoverNodes="n1" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" />Tomcat-2:
failoverNodes="n2" 其余同上。 -
Nginx 調度器
upstream tomcat {
hash $cookie_JSESSIONID;
server 172.25.254.10:8080;
server 172.25.254.20:8080;
} -
驗證步驟
a) 兩臺 Tomcat + 兩臺 Memcached 全啟動,瀏覽器登錄。
b) 關閉其中一臺 Tomcat 或 Memcached,刷新頁面 → 會話保持。
模擬132tomcat故障
正常情況下
? 192.168.65.131 上的 Tomcat-A 把 Session 主本 寫在對端 192.168.65.132 的 Memcached-n2;
? 192.168.65.132 上的 Tomcat-B 把 Session 主本 寫在 131 的 Memcached-n1。
兩臺 Memcached 各自只保存「對方 Tomcat 的主 Session」,本地 Memcached 并沒有這份數據。
關閉 132 的 Tomcat-B(不是 Memcached)
? 瀏覽器下次請求被 Nginx 調度到 仍在運行的 131 Tomcat-A;
? 131 Tomcat-A 發現本地 Memcached-n1 沒有 該 Session,于是根據 msm 機制,從 132 Memcached-n2 讀取到原來的主本 Session;
? 131 把這份 Session 重新寫回本地 Memcached-n1 作為新的備份,并繼續提供服務。
結論(正確表述)
“關閉 192.168.65.132 的 Tomcat 后,192.168.65.131 的 Tomcat 從 192.168.65.132 的 Memcached 成功拉回原 Session,并在本地 Memcached 重新備份,驗證會話未丟失。”
如果模擬132memcached故障
-
正常時
192.168.65.131 這臺 Tomcat 把 Session 主本保存在 192.168.65.132 的 Memcached(n2)中;
131 本地的 Memcached(n1)并不存放該 Session。 -
關閉 132 的 Memcached 后
131 的 Tomcat 檢測到 n2 不可寫,立即把同一 Session 改寫到本機 n1;
因此后續請求由 131 處理時,能夠從本地 n1 讀取到剛才新寫入的備份 Session,驗證數據未丟失。.
結論:
關閉 132 的 Memcached 后,131 的 Tomcat 將 Session 實時轉存到本地 Memcached,隨后從本地節點成功讀取,驗證無數據丟失。