秒杀

目录

第一章:项目框架搭建

1、Springboot环境搭建

2、集成Thymeleaf、Result结果封装

3、集成Mybatis+Druid

4、集成Jedis+Redis安装+通用缓存key封装

第二章 实现登录动能

1、数据库设计

2、明文密码俩次MD5处理  

3、JSR303参数校验+全局异常处理器

4、分布式Session 

三、实现秒杀功能

1、数据库设计

2、商品列表页

3、商品详情页

4、订单详情页

四、JMeter压测

1、JMeter入门

2、自定一变量模拟多个用户

3、JMeter命令行使用

4、SpringBoot打war包

第五章:页面优化技术

1、页面缓存+URL缓存+对象缓存

2、页面静态化,前后端分离3、静态资源优化4、CDA优化

第六章:接口优化

1、Redis预减库存减少数据库访问

2、内存标记减少Redis访问

3、RabbitMQ队列缓存,异步下单,增强用户体验

4、RabbitMQ安装与Springboot集成

5、访问Nginx水平扩展

6、压测

第七章:安全优化

1、秒杀接口地址隐藏

2、数学公式验证码

3、接口防刷


秒杀

前端、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


  	4.0.0
  	com.topxin.miaosha
  	springboot-miaosha
  	0.0.1-SNAPSHOT
  
  	
		UTF-8
		1.8
	
	
	
		org.springframework.boot
		spring-boot-starter-parent
		1.5.20.RELEASE
	
	
	
		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			1.3.1
		
	


2、集成Thymeleaf、Result结果封装

pom.xml


    org.springframework.boot
    spring-boot-starter-thymeleaf

Result.java

package com.topxin.miaosha.result;

public class Result {
	
	private int code;
	private String msg;
	private T data;
	
	//成功时调用
	public static Result success(T data){
		return new Result(data);
	}
	
	//失败时调用
	public static Result error(CodeMsg cm){
		return new Result(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


    mysql
    mysql-connector-java
    runtime


    com.alibaba
    druid
    1.0.5

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


    redis.clients
    jedis


    com.alibaba
    fastjson
    1.2.38

 

模板模式(设计模式)、通用缓存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


    commons-codec
    commons-codec


    org.apache.commons
    commons-lang3
    3.6

3、JSR303参数校验+全局异常处理器

pom.xml


    org.springframework.boot
    spring-boot-starter-validation

4、分布式Session 

三、实现秒杀功能

1、数据库设计

2、商品列表页

3、商品详情页

4、订单详情页

四、JMeter压测

1、JMeter入门

下载地址

http://jmeter.apache.org/download_jmeter.cgi

主要工具

1)设置一个线程组

秒杀_第1张图片

2)设置 http默认请求配置秒杀_第2张图片

 3)设置一个具体任务

秒杀_第3张图片

2、自定一变量模拟多个用户

(C SV Data Set Config  设置配置问卷)

秒杀_第4张图片

5)Aggregate Report(聚合报告)   Throughput(吞吐量) 

并发在多少的qps(tps)

秒杀_第5张图片

 6)对线程并发出现数据库连接异常

秒杀_第6张图片

3、JMeter命令行使用

redis压测工具redis-benchmark

1)top命令查看cpu 

秒杀_第7张图片

2)Redis压测工具redis-benchmark
redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 100000    (100个并发连接,100000个请求)

秒杀_第8张图片

3) redis-benchmark -h 127.0.0.1 -p 6379 -q -d 100    (存取大小为100字节的数据包)

秒杀_第9张图片

4)redis-benchmark -t set,lpush -q -n 100000    (只输出set和lpush)

4、SpringBoot打war包

1)添加spring-boot-starter-tomcat的provided


    org.springframework.boot
    spring-boot-starter-tomcat
    provided

2)添加maven-war-plugin


	${project.artifactId}
	
		
			org.apache.maven.plugins
			maven-war-plugin
			
				false
			
		
	

3)改成war

war

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


    org.springframework.boot
    spring-boot-starter-amqp

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

 

你可能感兴趣的:(springboot)