目录
秒杀
前端、jquery、Thymeleaf、Result结果、bootstrap
后台、springboot、jsr303 监控(参数校验)、mybatis
中间件:rabbitmq、jeids+redis、druid
分布式session
JMeter入门压测
第一章:项目框架搭建
1、Springboot环境搭建
启动类
package com.topxin.miaosha;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 秒杀启动类
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.topxin.miaosha</groupId>
<artifactId>springboot-miaosha</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.20.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
</project>
2、集成Thymeleaf、Result结果封装
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Result.java
package com.topxin.miaosha.result;
public class Result<T> {
private int code;
private String msg;
private T data;
//成功时调用
public static<T> Result<T> success(T data){
return new Result<T>(data);
}
//失败时调用
public static<T> Result<T> error(CodeMsg cm){
return new Result<T>(cm);
}
private Result(T data) {
this.code = 0;
this.msg = "success";
this.data = data;
}
private Result(CodeMsg cm) {
if(cm == null) {
return;
}
this.code = cm.getCode();
this.msg = cm.getMsg();
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public T getData() {
return data;
}
}
application.properties
#thymeleaf
spring.thymeleaf.cache=true
spring.thymeleaf.content-type=text/html
spring.thymeleaf.enable=true
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML5
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
3、集成Mybatis+Druid
pom.xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.5</version>
</dependency>
application.properties
#mybatis
mybatis.type-alises-package=com.topxin.miaosha.domain
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default.statement-timeout=30
mybatis.mapperLocation=classpath:com/topxin/miaosha/dao/*.xml
#druid
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/miaosha?characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
4、集成Jedis+Redis安装+通用缓存key封装
Linux安装redis和测试
https://redis.io/
tar -zxvf redis-5.0.5.tar.gz
mv redis-5.0.5 /usr/local/redis
cd /usr/local/redis/
make -j 2
make install
vi redis.conf
bind 0.0.0.0
daemonize yes
requirepass 123456
redis-server ./redis.conf
shutdown save
auth 123456
cd utils/
./install_server.sh
/usr/local/redis/redis.conf
/usr/local/redis/redis.log
/usr/local/redis/data
chkconfig --list | grep redis
systemctl status redis_6379
systemctl stop redis_6379
systemctl start redis_6379
applaction.properties
#redis
redis.host=192.168.10.222
redis.port=6379
redis.timeout=3
redis.password=123456
redis.poolMaxTotal=10
redis.poolMaxIdle=10
redis.poolMaxWait=3
pom.xml
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
模板模式(设计模式)、通用缓存key封装、接口KeyPrefix--->抽象类BasePrefix--->实现类UserKey
KeyPrefix接口
package com.topxin.miaosha.redis;
/**
* key生成接口
*/
public interface KeyPrefix {
public int expireSeconds();
public String getPrefix();
}
BasePrefix抽象类
package com.topxin.miaosha.redis;
/**
* 模板模式
* 通用缓存key封装
* 接口--->抽象类--->实现类
*/
public abstract class BasePrefix implements KeyPrefix{
private int expireSeconds;//过期时间
private String prefix;
public BasePrefix(int expireSeconds,String prefix) {
this.expireSeconds = expireSeconds;
this.prefix = prefix;
}
public BasePrefix(String prefix) {//0代表永不过期
this(0, prefix);
}
public int expireSeconds() {//默认0代表永不过期
return expireSeconds;
}
public String getPrefix() {
String className = getClass().getSimpleName();
return className + ":" + prefix;
}
}
UserKey实现类
package com.topxin.miaosha.redis;
/**
* 实现了抽象类BasePrefix
*/
public class UserKey extends BasePrefix{
public UserKey(String prefix) {
super(prefix);
}
public static UserKey getById = new UserKey("id");
public static UserKey getByName = new UserKey("name");
}
第二章 实现登录动能
1、数据库设计
2、明文密码俩次MD5处理
用户端:PASS=MD5(明文+固定Salt)
服务端:PASS=MD5(用户输入+随机Salt)
pom.xml
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
3、JSR303参数校验+全局异常处理器
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
4、分布式Session
三、实现秒杀功能
1、数据库设计
2、商品列表页
3、商品详情页
4、订单详情页
四、JMeter压测
1、JMeter入门
下载地址
http://jmeter.apache.org/download_jmeter.cgi
主要工具
1)设置一个线程组
2)设置 http默认请求配置
3)设置一个具体任务
2、自定一变量模拟多个用户
(C SV Data Set Config 设置配置问卷)
5)Aggregate Report(聚合报告) Throughput(吞吐量)
并发在多少的qps(tps)
6)对线程并发出现数据库连接异常
3、JMeter命令行使用
redis压测工具redis-benchmark
1)top命令查看cpu
2)Redis压测工具redis-benchmark
redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 100000 (100个并发连接,100000个请求)
3) redis-benchmark -h 127.0.0.1 -p 6379 -q -d 100 (存取大小为100字节的数据包)
4)redis-benchmark -t set,lpush -q -n 100000 (只输出set和lpush)
4、SpringBoot打war包
1)添加spring-boot-starter-tomcat的provided
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
2)添加maven-war-plugin
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
3)改成war
<packaging>war</packaging>
4、启动类
package com.topxin.miaosha;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
/**
* 秒杀启动类
*/
@SpringBootApplication
public class MainApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MainApplication.class);
}
}
第五章:页面优化技术
1、页面缓存+URL缓存+对象缓存
2、页面静态化,前后端分离
3、静态资源优化
4、CDA优化
第六章:接口优化
1)系统初始化,把商品库的数量加载到Redis
2)收到请求,Redis预见库存,库存不足,直接返回,否则进入3
3)请求入队,立即返回排队中
4)请求出队,生成订单,减少库存
5)客户端轮询,是否秒杀成功
1、Redis预减库存减少数据库访问
2、内存标记减少Redis访问
3、RabbitMQ队列缓存,异步下单,增强用户体验
4、RabbitMQ安装与Springboot集成
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
application.properties
#rabbitmq
spring.rabbitmq.host=192.168.10.222
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
#
spring.rabbitmq.listener.simple.concurrency=10
spring.rabbitmq.listener.simple.max-concurrency=10
#
spring.rabbitmq.listener.simple.prefetch=1
spring.rabbitmq.listener.simple.auto-startup=true
spring.rabbitmq.listener.simple.default-requeue-rejected=true
#
spring.rabbitmq.template.retry.enabled=true
spring.rabbitmq.template.retry.initial-interval=1000
spring.rabbitmq.template.retry.max-attempts=3
spring.rabbitmq.template.retry.max-interval=10000
spring.rabbitmq.template.retry.multiplier=10
rabbitmqConfig
@Configuration //是一个类级别注释
public class MQConfig {
public static final String QUEUE = "queue";
@Bean //依赖注入rabbitmq的Queue队列
public Queue queue() {
return new Queue(QUEUE,true);
}
/**
* 通过Binding对象可以绑定相应的交换机(Exchange),rabbitmq常用的有4种
* Direct模式
* Topic模式(可以支持通配符)
* Fanout模式(广播模式)
* Header模式(需要match匹配相应的条件map)
*/
@Bean
public Binding topicBinding() {
return BindingBuilder.bind(topicQueue1()).to(topicExchange()).with("topic.key1");
}
}
Sender发送消息
private static Logger logger = LoggerFactory.getLogger(MQSender.class);
@Autowired
AmqpTemplate amqpTemplate;
public void send(Object message) {
String msg = RedisService.beanToString(message); logger.info("send message"+ msg);
amqpTemplate.convertAndSend(MQConfig.QUEUE,msg);
}
Receive接收消息
@RabbitListener(queues=MQConfig.QUEUE)
public void receive(String message) {
logger.info("receive message" +message);
}
5、访问Nginx水平扩展
LVS(linux内核)
6、压测
第七章:安全优化
1、秒杀接口地址隐藏
思路,秒杀开始之前,先去请求接口获取秒杀地址
1)接口改造,带上PathVariable参数
2)添加生成地址的接口
3)秒杀收到请求,先验证PthVaribale
2、数学公式验证码
思路,秒杀开始之前,先输入验证码,分散用户的请求
1)添加生成验证码接口
2)在获取秒杀路径的时候,验证验证码
2)ScriptEngine使用
3、接口防刷
架构
1、高防IP(防止DDOS攻击)
2、接入SLB,对对台云服务器进行流量并发,可以通过流量并发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性
3、Nginx做限流分发
4、基于Redis或者zookeeper分布式锁,Kafka或者Redis做消息队列,DRDS数据库中间件实现数据的读写分离
优化思路
分流、分流、分流。再牛逼的机器也挡不住高级别的并发
限流、限流、限流,毕竟秒杀商品有限,防刷的前提下没有绝对公平,根据每个服务的负载能力,设定流量极限。
缓存、缓存、缓存,尽量不要让大量请求穿透到DB层,活动开始前商品信息可以推送至分布式缓存。
异步、异步、异步,分析并识别出可以异步处理的逻辑,比如日志,缩短系统响应时间。
主备、主备、主备,如果有条件做好主备容灾方案也是非常有必要的(参考某年锤子的活动被攻击)。
最后,为了支撑更高的并发,追求更好的性能,可以对服务器的部署模型进行优化,部分请求走正常的秒杀流程,部分请求直接返回秒杀失败,缺点是开发部署时需要维护两套逻辑。
分层优化
前端优化:活动开始前生成静态商品页面推送缓存和CDN,静态文件(JS/CSS)请求推送至文件服务器和CDN。
网络优化:如果是全国用户,最好是BGP多线机房,减少网络延迟。
应用服务优化:Nginx最佳配置、Tomcat连接池优化、数据库配置优化、数据库连接池优化。
全链路测压
分析需压测业务场景涉及系统
协调各个压测系统资源并搭建压测环境
压测数据隔离以及监控(响应时间、吞吐量、错误率等数据以图表形式实时显示)
压测结果统计(平均响应时间、平均吞吐量等数据以图表形式在测试结束后显示)
优化单个系统性能、关联流程以及整个业务流程
整个压测优化过程就是一个不断优化不断改进的过程,事先通过测试不断发现问题,优化系统,避免问题,指定应急方案,才能让系统的稳定性和性能都得到质的提升。
学习计划
接口防刷
JMeter压测
JMeter命令行使用
1、在windows上录好jmx
2、命令行./apache-jmeter-5.1.1/bin/jmeter.sh -n -t goods_list.jmx -l result.jtl
3\把result.jtl导入到jmeter中
cat /etc/motd
cat /proc/cpuinfo | grep processor
top
load average
第五章
1、页面缓存+URL缓存+对象缓存(更细粒度),减少数据访问
2、页面静态化、前后端分离(AngularJS、Vue.js),优点:利用浏览器的缓存
Cache Aside Patten 缓存模式
Pragma
Expire
Cache-Control 300秒
3、静态资源优化
JS/CSS压缩,减少流量
多个JS/CSS组合,减少连接数
Tengine.taobao.org(Nginx)
组合多个CSS,JavaScript文件的访问请求变成一个请求
自动去除空白字符和注释从而减少页面的体积(webpcak打包)
4、CDN(Content Delivery Network内容分发网络)优化
第六章 、接口优化(减少数据库访问)
1)系统初始化,把商品库的数量加载到Redis
2)收到请求,Redis预见库存,库存不足,直接返回,否则进入3
3)请求入队,立即返回排队中
4)请求出队,生成订单,减少库存
5)客户端轮询,是否秒杀成功
1)Redis预减库存减少数据库访问
2)内存标记减少Redis访问
3)请求先入队缓存,异步下单,增强用户体验
4)RabbitMQ安装与SpringBoot集成
安装erlang
5672
http://www.erlang.org/downloads
http://www.cnerlang.com/
https://www.rabbitmq.com/download.html
yum -y install gcc gcc-c++ autoconf automake
yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel
1、下载erlang和rabbitmq上传到服务器上
2、yum install ncurses-devel
3、tar xf otp_src_21.0.tar.gz
4、mkdir /usr/local/erlang21
4、./configure --prefix=/usr/local/erlang21 --without-javac
5、make -j 4(make && make install)
6、cd /bin ./erl
7、tar xf rabbitmq-server-generic-unix-3.7.15.tar
cp -r rabbitmq_server-3.7.15/ /usr/local/rabbitmq
8、yum install python -y
9、yum install xmlto -y
10、yum install python-simplejson -y
11、cd sbin ./rabbitmq-server
12、配置环境
13、tail -f /home/rabbitmq/var/log/rabbitmq/rabbit\@localhost.log
netstat -nap | grep 5672
[{kernel,[{inet_dist_use_interface,{127,0,0,1}}]}].
#set erlang environment
export PATH=$PATH:/home/erlang21/bin
#set rabbitmq enviroment
export PATH=$PAHT:/home/rabbitmq/sbin