本文參考自
Springboot3+微服務(wù)實(shí)戰(zhàn)12306高性能售票系統(tǒng) - 慕課網(wǎng) (imooc.com)
本章將介紹仿12306售票系統(tǒng)實(shí)戰(zhàn)開發(fā)的開發(fā)環(huán)境、項(xiàng)目核心技術(shù)和功能、項(xiàng)目模塊和架構(gòu)設(shè)計(jì)、開發(fā)所需前置知識(shí),若想直接開始編寫代碼實(shí)現(xiàn),請(qǐng)關(guān)注作者,看后面的第二章——項(xiàng)目實(shí)現(xiàn)
一、開發(fā)環(huán)境
- 后端:
- JDK 17
- Springboot 3.0.0
- SpringCloud Alibaba 2022.0.0.0
- 第三方依賴,如Mybatis等,使用升級(jí)后適配Springboot3的版本
- 前端:
- Vue3
二、項(xiàng)目技術(shù)亮點(diǎn)概括
為什么使用最新版本?
學(xué)習(xí)要激進(jìn),實(shí)際項(xiàng)目要滯后(市場主流還是使用JDK1.8那套)
技術(shù)亮點(diǎn)主要就是高并發(fā)技術(shù)
售票系統(tǒng)需要實(shí)現(xiàn)持續(xù)高并發(fā),不停的刷票,決不能超賣
12306是如何解決高并發(fā)問題?
-
提高處理能力: QPS和TPS
堆積硬件;引入第三方軟件Gemfire;算法(模型、邏輯)
Gemfire:商業(yè)軟件,分布式內(nèi)存數(shù)據(jù)庫,使得查詢速度從15秒降到0.2秒
QPS(Queries Per Second)和 TPS(Transactions Per Second)是衡量系統(tǒng)性能的重要指標(biāo):
- QPS(Queries Per Second):指的是每秒鐘所處理的查詢數(shù)量,通常用來衡量系統(tǒng)對(duì)于短時(shí)、瞬時(shí)請(qǐng)求的處理能力,比如網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫查詢等。
- TPS(Transactions Per Second):指的是每秒鐘所處理的事務(wù)數(shù)量,事務(wù)可以是一個(gè)或多個(gè)相關(guān)操作的集合,用來完成一個(gè)業(yè)務(wù)功能。TPS常用來衡量系統(tǒng)對(duì)于業(yè)務(wù)操作的處理能力,比如支付交易、訂單處理等。
QPS更強(qiáng)調(diào)系統(tǒng)的查詢處理能力,而TPS更側(cè)重系統(tǒng)對(duì)業(yè)務(wù)操作的處理能力。在不同的場景下,可以根據(jù)具體需求選擇監(jiān)控并優(yōu)化QPS或TPS來提升系統(tǒng)性能。
-
削峰
業(yè)務(wù):驗(yàn)證碼、分時(shí)段、排隊(duì)
技術(shù):限流、異步
三、項(xiàng)目業(yè)務(wù)邏輯難點(diǎn)概括
-
選座邏輯
實(shí)現(xiàn)類似12306的選座邏輯
使用位運(yùn)算算法,既快又準(zhǔn)的得到符合要求的座位
-
12306:
-
本項(xiàng)目:
-
-
動(dòng)態(tài)庫存
當(dāng)上海——北京,被買,則是1張票
當(dāng)上海到南京,南京到上海被買,則是2張票
-
線上線下
即可線上買票,也可線下買票
四、核心功能
最高并發(fā):余票查詢
業(yè)務(wù)邏輯最復(fù)雜:車票購買
五、功能模塊劃分
-
網(wǎng)關(guān)模塊
路由轉(zhuǎn)發(fā)、登錄校驗(yàn)
-
會(huì)員模塊
會(huì)員、乘客、已購買的車票
-
業(yè)務(wù)模塊
所有的車次數(shù)據(jù)、余票信息
-
跑批模塊
管理定時(shí)任務(wù),頁面啟停
-
web模塊
會(huì)員相關(guān)界面
-
admin模塊
管理員相關(guān)界面
六、整體架構(gòu)設(shè)計(jì)
- 業(yè)務(wù)、會(huì)員、跑批分別為不同的服務(wù),且數(shù)據(jù)庫相互隔離(做一定的數(shù)據(jù)冗余)
- common主要是公共的工具類,generator為代碼生成器
- springcloud alibaba組件:nacos是注冊中心,seata是分布式事務(wù),sentinel是限流
七、數(shù)據(jù)庫表
1. 會(huì)員模塊
- 會(huì)員表:手機(jī)號(hào)
- 乘客表:會(huì)員ID,姓名,身份證,旅客類型
- 車票表:會(huì)員ID,乘客ID,乘客姓名,日期,車次信息,座位信息
2.業(yè)務(wù)模塊
- 車站表:站名,站名拼音
- 車次表:車次編號(hào),車次類型,始發(fā)站,出發(fā)時(shí)間,終點(diǎn)站,到站時(shí)間
- 到站表:車次編號(hào),站名,進(jìn)站時(shí)間,出站時(shí)間,停站時(shí)長,里程
- 車箱表:車次編號(hào),箱號(hào),座位類型,座位數(shù),排數(shù),列數(shù)
- 座位表:車次編號(hào),箱號(hào),排號(hào),列號(hào)
- 每日車次表:日期,基礎(chǔ)車次信息
- 每日到站表:日期,基礎(chǔ)到站信息
- 每日車箱表:日期,基礎(chǔ)車箱信息
- 每日座位表:日期,基礎(chǔ)座位信息,銷售詳情
- 每日余票表:日期,車次編號(hào),出發(fā)站,出發(fā)時(shí)間,到達(dá)站,到站時(shí)間,各種座位的余票信息
3.其他
- quartz相關(guān)表
- seata相關(guān)表
八、持續(xù)秒殺高并發(fā)技術(shù)
1.前端
-
針對(duì)靜態(tài)資源做CDN
CDN(Content Delivery Network)技術(shù)是一種通過在全球各地部署服務(wù)器節(jié)點(diǎn)來加速網(wǎng)絡(luò)內(nèi)容傳輸?shù)募夹g(shù)。通過在靠近用戶的服務(wù)器節(jié)點(diǎn)上緩存內(nèi)容,CDN技術(shù)能夠減少網(wǎng)絡(luò)延遲,提高網(wǎng)站的加載速度和性能。當(dāng)用戶請(qǐng)求訪問網(wǎng)站時(shí),CDN會(huì)自動(dòng)將內(nèi)容從最接近用戶的服務(wù)器節(jié)點(diǎn)傳輸給用戶,而不是從遠(yuǎn)程服務(wù)器傳輸,從而提高用戶體驗(yàn)并減輕原始服務(wù)器的負(fù)載壓力。
-
頁面靜態(tài)化
頁面靜態(tài)化是指將動(dòng)態(tài)生成的網(wǎng)頁內(nèi)容轉(zhuǎn)換為靜態(tài)文件,并保存在服務(wù)器的本地存儲(chǔ)空間或CDN節(jié)點(diǎn)上,從而加快網(wǎng)頁加載速度和提高網(wǎng)站性能的技術(shù)。通過頁面靜態(tài)化,服務(wù)器無需每次請(qǐng)求時(shí)都重新生成頁面內(nèi)容,而是直接返回預(yù)先生成好的靜態(tài)文件,減少了服務(wù)器的計(jì)算壓力和數(shù)據(jù)庫訪問次數(shù),提高了網(wǎng)站的并發(fā)訪問能力和用戶響應(yīng)速度。頁面靜態(tài)化技術(shù)有助于改善網(wǎng)站的用戶體驗(yàn),減少加載時(shí)間,提高頁面渲染速度。
-
倒計(jì)時(shí)&loading
防止用戶不斷刷新/點(diǎn)擊秒殺,造成后端更大的壓力
-
使用驗(yàn)證碼削峰
2.后端
-
微服務(wù)-服務(wù)拆分
熱點(diǎn)接口做成單獨(dú)的服務(wù)
-
負(fù)載均衡
-
限流降級(jí)
-
緩存
-
令牌
-
異步處理
3.數(shù)據(jù)庫
- 分庫:業(yè)務(wù)分庫、讀寫分離
- 分表:橫向分表(按地區(qū)/時(shí)間分)、縱向分表(把一張完整的表,縱向切成兩張表)
- 冗余設(shè)計(jì)(反范式,空間換時(shí)間)
- 分布式數(shù)據(jù)庫
4.其他
- 分時(shí)段秒殺
- 彈性擴(kuò)容(自動(dòng)擴(kuò)容有時(shí)候反應(yīng)比較慢,不適合突發(fā)的大流量請(qǐng)求,所以秒殺之前需要提前擴(kuò)容好;但是在秒殺后,他可以自動(dòng)回收,降低成本
- 候補(bǔ)+排隊(duì)
九、SpringBoot3&JDK9~17新特性詳情
1.JDK9新特性——模塊化開發(fā)(用的較少)
Java8應(yīng)用程序?qū)?strong>包作為頂級(jí)組件,Java9應(yīng)用程序?qū)?strong>模塊作為頂級(jí)組件。
使用module-info.java來聲明一個(gè)模塊,一個(gè)模塊只能有一個(gè)文件,且在頂層包同目錄下
使用exports來聲明可以被外部引用的包,可以有多個(gè)exports語句
使用requires來聲明依賴的外部的模塊,可以有多個(gè)requires語句
2.JDK10新特性——var局部變量推導(dǎo)
- 必須能推導(dǎo)出實(shí)際類型
- 只能用于局部變量
3.JDK11新特性——單文件程序
原來:使用javac生成.class文件,然后在.class文件下用java命令將其打開
現(xiàn)在:直接命令運(yùn)行:java xxx.java(必須帶.java)
4.JDK11新特性——shebang腳本
將java文件改成sh后綴,使用如下命令可運(yùn)行
java --source 11 xxx.sh
什么是shebang
#!符號(hào)可以叫做shebang,翻譯成釋伴,即"解釋伴隨行"的簡稱,同時(shí)又是shebang的音譯
以指令#!/bin/bash開頭的文件,在執(zhí)行時(shí)會(huì)實(shí)際調(diào)用/bin/bash程序來執(zhí)行
5.JDK14新特性——文本塊
// 傳統(tǒng)字符串寫法
String json = "{\n" +
"\tname: \"TEST\"\n" +
"}";
System.out.println(json);
// 文本塊寫法
String json1 = """
{
name: "TEST"
}
""";
System.out.println(json1);
6.JDK14新特性——instanceof增強(qiáng)
Object a = "123";
if (a instanceof String) {
String b = (String) a;
System.out.println(b);
}
if (a instanceof String b) {
System.out.println(b);
}
7.JDK14新特性——空指針提示
-
傳統(tǒng)報(bào)錯(cuò)
Exception in thread "main" java.lang.NullPointerException at com.jiawa2.Jiawa2.main(Jiawa2.java:46)
-
新報(bào)錯(cuò)
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.List.size()" because "a" is null at com.jiawa2.Jiawa2.main(Jiawa2.java:46)
8.JDK16新特性——record類
record是一個(gè)final類,初始化后就不能修改屬性值
自動(dòng)生成toString, hashCode, equals方法
public record TestRecord(String name, String password) {
}
TestRecord testRecord = new TestRecord("test","111");
9.JDK17新特性——sealed類
- 痛點(diǎn):一個(gè)類被哪些子類繼承了,很難查,隨時(shí)有可能繼續(xù)被繼承
- sealed可以對(duì)類的繼承做顯式的管理,一個(gè)類被哪些類繼承,一眼就能看得清。
- 父類如果是sealed類,則必須至少有一個(gè)子類
- sealed類的子類,必須是final,sealed,non-sealed之一
sealed類封裝類或叫密封類
密封類的目的是為了限制子類的過度使用,父類的開發(fā)者必須聲明哪些子類可以繼承該父類,以確保不會(huì)出現(xiàn)未限定的子類繼承父類,導(dǎo)致程序出現(xiàn)預(yù)料之外的問題密封類及其允許的子類必須屬于同一個(gè)模塊。
每個(gè)允許的子類都必須直接繼承密封類。
每個(gè)允許的子類都必須使用final、sealed或non-sealed修飾符中的一個(gè)來描述:
- 允許的子類聲明為 final 表示它無法再擴(kuò)展。
- 允許的子類聲明為sealed表示它可以以一種受限制的方式進(jìn)一步擴(kuò)展。
- 允許的子類聲明為non-sealed表示它可以任意的擴(kuò)展。
顯式聲明Jiawa1只能被Jiawa2集成:
public sealed class Jiawa1 permits Jiawa2 {
}
non-sealed:恢復(fù)隱式規(guī)則
10.JDK17新特性——switch增強(qiáng)
-
舊版本:
if (data.get("key") instanceof String s) { log.info(s); } else if (data.get("key") instanceof Double s) { log.info(s); } else if (data.get("key") instanceof Integer s) { log.info(s); }
-
新版本:
switch (data.get("key1")) { case String s -> log.info(s); case Double d -> log.info(d.toString()); case Integer i -> log.info(i.toString()); default -> log.info(""); }
11.SpringBoot3——AOT與JIT介紹
JIT(Just-in-Time,實(shí)時(shí)編譯)一直是Java語言的靈魂特性之一,與之相對(duì)的AOT(Ahead-of-Time,預(yù)編譯或提前編譯)方式
AOT的優(yōu)點(diǎn)
- 在程序運(yùn)行前編譯,可以避免在運(yùn)行時(shí)的編譯性能消耗和內(nèi)存消耗
- 可以在程序運(yùn)行初期就達(dá)到最高性能,程序啟動(dòng)速度快
- 運(yùn)行產(chǎn)物只有機(jī)器碼,打包體積小
AOT的缺點(diǎn)
- 由于是靜態(tài)提前編譯,不能根據(jù)硬件情況或程序運(yùn)行情況擇優(yōu)選擇機(jī)器指令序列,理論峰值性能不如JIT
- 沒有動(dòng)態(tài)能力(如AOP)
- 同一份產(chǎn)物不能跨平臺(tái)運(yùn)行
12.JIT在高并發(fā)場景中的生產(chǎn)問題
現(xiàn)象:熱點(diǎn)應(yīng)用重啟后,出現(xiàn)業(yè)務(wù)超時(shí),幾分鐘后恢復(fù)正常
解決方法:
- 預(yù)熱:初始讓程序自動(dòng)運(yùn)行熱點(diǎn)代碼幾百次
- 流量控制:啟動(dòng)時(shí)小流量,運(yùn)行幾分鐘后再放到正常流量
13.SpringBoot3——GraalVM代替JDK實(shí)現(xiàn)AOT
-
GraalVM下載:
https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.3.0
JAVA_HOME:給一些第三方用,例如Tomcat,會(huì)讀取這里的路徑
Path:在命令行可以獲取JDK信息
-
安裝native-image(用來打包exe(windows版本))
-
在線安裝
gu install native-image(powershell報(bào)錯(cuò),cmd正常)
有可能會(huì)超時(shí)報(bào)錯(cuò),多試幾次 -
手動(dòng)安裝
下載:https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.3.0
命令行:gu install -L 你的下載位置 -
查看安裝結(jié)果
gu list
-
-
新建SpringBoot3項(xiàng)目
使用IDEA新建SpringBoot項(xiàng)目,版本號(hào):3.0.0 -
安裝Visual Studio 2022
下載社區(qū)版,安裝時(shí)勾選C++桌面開發(fā)
-
GraalVM AOT打包
跳到項(xiàng)目所在目錄,使用x64 Native Tools Command Prompt for VS 2022,執(zhí)行:mvn -Pnative native:compile文章來源:http://www.zghlxwxcb.cn/news/detail-848866.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-848866.html
到了這里,關(guān)于Java項(xiàng)目實(shí)戰(zhàn)--基于SpringBoot3.0開發(fā)仿12306高并發(fā)售票系統(tǒng)--(一)前置知識(shí)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!