本文参考自
Springboot3+微服务实战12306高性能售票系统 - 慕课网 (imooc.com)
本章将介绍仿12306售票系统实战开发的开发环境、项目核心技术和功能、项目模块和架构设计、开发所需前置知识,若想直接开始编写代码实现,请关注作者,看后面的第二章——项目实现
为什么使用最新版本?
学习要激进,实际项目要滞后(市场主流还是使用JDK1.8那套)
技术亮点主要就是高并发技术
售票系统需要实现持续高并发,不停的刷票,决不能超卖
12306是如何解决高并发问题?
提高处理能力: QPS和TPS
堆积硬件;引入第三方软件Gemfire;算法(模型、逻辑)
Gemfire:商业软件,分布式内存数据库,使得查询速度从15秒降到0.2秒
QPS(Queries Per Second)和 TPS(Transactions Per Second)是衡量系统性能的重要指标:
- QPS(Queries Per Second):指的是每秒钟所处理的查询数量,通常用来衡量系统对于短时、瞬时请求的处理能力,比如网络请求、数据库查询等。
- TPS(Transactions Per Second):指的是每秒钟所处理的事务数量,事务可以是一个或多个相关操作的集合,用来完成一个业务功能。TPS常用来衡量系统对于业务操作的处理能力,比如支付交易、订单处理等。
QPS更强调系统的查询处理能力,而TPS更侧重系统对业务操作的处理能力。在不同的场景下,可以根据具体需求选择监控并优化QPS或TPS来提升系统性能。
削峰
业务:验证码、分时段、排队
技术:限流、异步
选座逻辑
实现类似12306的选座逻辑
使用位运算算法,既快又准的得到符合要求的座位
12306:
本项目:
动态库存
当上海——北京,被买,则是1张票
当上海到南京,南京到上海被买,则是2张票
线上线下
即可线上买票,也可线下买票
最高并发:余票查询
业务逻辑最复杂:车票购买
网关模块
路由转发、登录校验
会员模块
会员、乘客、已购买的车票
业务模块
所有的车次数据、余票信息
跑批模块
管理定时任务,页面启停
web模块
会员相关界面
admin模块
管理员相关界面
针对静态资源做CDN
CDN(Content Delivery Network)技术是一种通过在全球各地部署服务器节点来加速网络内容传输的技术。通过在靠近用户的服务器节点上缓存内容,CDN技术能够减少网络延迟,提高网站的加载速度和性能。当用户请求访问网站时,CDN会自动将内容从最接近用户的服务器节点传输给用户,而不是从远程服务器传输,从而提高用户体验并减轻原始服务器的负载压力。
页面静态化
页面静态化是指将动态生成的网页内容转换为静态文件,并保存在服务器的本地存储空间或CDN节点上,从而加快网页加载速度和提高网站性能的技术。通过页面静态化,服务器无需每次请求时都重新生成页面内容,而是直接返回预先生成好的静态文件,减少了服务器的计算压力和数据库访问次数,提高了网站的并发访问能力和用户响应速度。页面静态化技术有助于改善网站的用户体验,减少加载时间,提高页面渲染速度。
倒计时&loading
防止用户不断刷新/点击秒杀,造成后端更大的压力
使用验证码削峰
微服务-服务拆分
热点接口做成单独的服务
负载均衡
限流降级
缓存
令牌
异步处理
Java8应用程序将包作为顶级组件,Java9应用程序将模块作为顶级组件。
使用module-info.java来声明一个模块,一个模块只能有一个文件,且在顶层包同目录下
使用exports来声明可以被外部引用的包,可以有多个exports语句
使用requires来声明依赖的外部的模块,可以有多个requires语句
原来:使用javac生成.class文件,然后在.class文件下用java命令将其打开
现在:直接命令运行:java xxx.java(必须带.java)
将java文件改成sh后缀,使用如下命令可运行
java --source 11 xxx.sh
什么是shebang
#!符号可以叫做shebang,翻译成释伴,即"解释伴随行"的简称,同时又是shebang的音译
以指令#!/bin/bash开头的文件,在执行时会实际调用/bin/bash程序来执行
// 传统字符串写法 String json = "{\n" + "\tname: \"TEST\"\n" + "}"; System.out.println(json); // 文本块写法 String json1 = """ { name: "TEST" } """; System.out.println(json1);
Object a = "123"; if (a instanceof String) { String b = (String) a; System.out.println(b); } if (a instanceof String b) { System.out.println(b); }
传统报错
Exception in thread "main" java.lang.NullPointerException at com.jiawa2.Jiawa2.main(Jiawa2.java:46)
新报错
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)
record是一个final类,初始化后就不能修改属性值
自动生成toString, hashCode, equals方法
public record TestRecord(String name, String password) { }
TestRecord testRecord = new TestRecord("test","111");
sealed类封装类或叫密封类
密封类的目的是为了限制子类的过度使用,父类的开发者必须声明哪些子类可以继承该父类,以确保不会出现未限定的子类继承父类,导致程序出现预料之外的问题
密封类及其允许的子类必须属于同一个模块。
每个允许的子类都必须直接继承密封类。
每个允许的子类都必须使用final、sealed或non-sealed修饰符中的一个来描述:
- 允许的子类声明为 final 表示它无法再扩展。
- 允许的子类声明为sealed表示它可以以一种受限制的方式进一步扩展。
- 允许的子类声明为non-sealed表示它可以任意的扩展。
显式声明Jiawa1只能被Jiawa2集成:
public sealed class Jiawa1 permits Jiawa2 { }
non-sealed:恢复隐式规则
旧版本:
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(""); }
JIT(Just-in-Time,实时编译)一直是Java语言的灵魂特性之一,与之相对的AOT(Ahead-of-Time,预编译或提前编译)方式
AOT的优点
AOT的缺点
现象:热点应用重启后,出现业务超时,几分钟后恢复正常
解决方法:
GraalVM下载:
https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.3.0
JAVA_HOME:给一些第三方用,例如Tomcat,会读取这里的路径
Path:在命令行可以获取JDK信息
安装native-image(用来打包exe(windows版本))
在线安装
gu install native-image(powershell报错,cmd正常)
有可能会超时报错,多试几次
手动安装
下载:https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.3.0
命令行:gu install -L 你的下载位置
查看安装结果
gu list
新建SpringBoot3项目
使用IDEA新建SpringBoot项目,版本号:3.0.0
安装Visual Studio 2022
下载社区版,安装时勾选C++桌面开发
GraalVM AOT打包
跳到项目所在目录,使用x64 Native Tools Command Prompt for VS 2022,执行:mvn -Pnative native:compile