工具

  • Redis 缓存
  • RabbitMQ 消息队列
  • JSR303 数据校验
  • JMeter 压力测试
  • Redis 压测工具 redis-benchmark

RabbitMQ

安装

Windows 平台
  1. RabbitMQ 官网下载安装包
  2. 进入命令行,进入安装文件下的 sbin ,
    输入 rabbitmqctl status 检验是否安装成功
  3. rabbitmq-plugins enable rabbitmq-management 启动管理插件
  4. 访问 http://localhost:15672/ 进入登录界面 默认账户密码 guest guest
  5. 添加账户 rabbitmqctl.bat add_users username password
  6. 授予管理员权限 rabbitmqctl.bat set_user_tags username administrator
  7. rabbitmq的用户角色:
    超级管理员:administrator
    监控着:monitoring
    策略制定者:policymaker
    普通管理者:management
  8. 修改密码 rabbitmqctl.bat change_password username new_password

分布式 session

  • 目的:保证多台服务器之间登录信息一致
  • 功能:验证登录信息,维持登录状态

1. 验证登录信息

前台传入账号(phone number, password),JSR303校验;

使用手机号依次访问 redis, mysql DB ,获取用户信息(phone number, dbPassword, salt);

访问数据库时(缓存中没有该用户),如果 user 存在,存入缓存;

将登录密码和 salt 通过 MD5 加密后,将结果和 dbPassword 比较;

比较结果为 true ,通过校验。

补充:使用 用户id + 系统当前时间 作为每个用户的 salt。

2. 维持登录状态

登录成功后,使用 MD5 (uId + Y/M/D) 生成作为 token,返回 token 给客户端,客户端将 token 存储到 cookie 中,并设置 cookie 过期时间(与 redis 过期时间保持一致)以后的访问都会携带 token;使用前缀( “token” )+ token 作为 key ,用户信息作为 value,存储到 redis ,并添加过期时间;添加 filter ,获取 cookie 中的 token ,如果 token 不存在,向客户端返回错误状态码和信息;token 存在,使用 token 向 redis 中获取对应 value,获取不到,向客户端返回错误状态码和信息;获取到 value ,更新过期时间。

秒杀

秒杀实现

  • 检验库存是否充足
  • 判断是否参与过秒杀
  • 将 减库存 + 写订单 + 下订单 作为一个事务操作
  • 减库存成功后才能进行下面动作

秒杀优化一

对象缓存
  • 访问接口时,首先从 redis 中获取对象
  • 如果获取到直接返回;否则,访问数据库,写入 redis (设置过期时间)后返回

秒杀优化二

1. 内存标记,减少 redis 访问

使用 HashMap ,标识是否秒杀是否结束。系统启动初始化,
将参与秒杀的商品加入内存,如果后续有商品加入。读取内存时,获取值为
null ,表示商品没有参加秒杀。

2. 缓存商品库存

将秒杀商品的库存缓存到 redis,用户参与秒杀,缓存库存量减一,如果库存量小于零,
将内存标记中的商品标识为结束(true)。系统初始化,将参与秒杀的商品加入内存,如
果后续有商品加入。在判断库存减一后是否小于零之前,首先判断商品是否存在(不需要
了,内存标记已经判断过了)。

3. 添加消息队列

将满足参与秒杀的信息(用户 + 商品)加入队列,接收端处理队列信息。消息队列在秒杀主要作用是为了削峰限流,当流量过大,直接涌入业务处理层时,会导致系统承载量过大。消息队列将大量的流量放入队列中,业务处理层根据自身处理能力,处理队列中的信息,无法及时处理的信息则滞留在队列中,所以不会出现业务处理层短时间接受大量信息的情况,保证了业务处理的稳定性。

JMeter 接口压力测试

秒杀接口测试

  • 线程数:10000
  • 线程启动时间: 0 (同时启动)
  • 用户量: 10000 (每个线程持有一个用户)
  • 吞吐量:260/sec 并存在 10% 左右的错误(无法访问)

秒杀接口,引入 MQ ,缓存商品数量,本地化活动是否截止

  • 线程数:10000
  • 线程启动时间: 0 (同时启动)
  • 用户量: 10000 (每个线程持有一个用户)
  • 吞吐量:367/sec 并存在 16% 左右的错误(被占用,无法访问)

JMeter 使用

1. 新建 ThreadGroup

Test Plan > Add > Threads(User) > ThreadGroup

2. 设置 ThreadGroup 属性
  • Number of Threads 线程数量
  • Ramp-up period (seconds) 启动时间 0表示同时启动
  • Loop Count 循环次数

3. 配置 Http 请求
  • Add > Config Element > HTTP Request Defaults 全局默认
  • Add > Config Element > HTTP Header Manager 头部管理 配置请求头,比如 content-type cookie 等
  • Add > Sampler > HTTP Request 配置 HTTP 请求

4. 监听工具

  • Add > Listener > …
  • 常用监听工具:
    Summary Report, View Results Tree
  • 重点参数:
    Summary Report > Throughput 吞吐量 越高越好

5. 读入文件

例如:读入批量配置 cookie

  • Add > Config Element > CSV Data Set Config
  • Filename: 文件路径
  • Variable Names: 变量名称例如 token,userId
    这里读入的文件要按照这种规则写,
    例如: asdfasdfad12,1111 \n retwertwer,2222
    说明: \n 表示换行
    解析结果:
    [{token: asdfasdfad12, userId: 1111},
    {token: retwertwer, userId: 2222}]
    使用: ${变量名}
  • Delimiter: 分隔符,默认逗号

验证码

  • 工具:java.awt ImageIO
  • 思路:利用 java.awt 生成图片, ImageIO 将图片写入 response 返回流中

接口限流(与业务代码解耦)

  • 一些常用的接口限流算法:漏桶算法、令牌桶算法
  • 工具: 拦截器,注解, redis
  • 思路: 通过拦截器,判断是否标识注解,如果标识,使用 redis 控制访问次数

redis 控制访问次数:
利用 redis 可控制 key 存在时间的特性。如果访问时 key 不存在,新建 key 设置过期时间,没访问一次,value 加一,达到访问上限,则返回,不允许访问方法。如果 key 存在,处理方法同上。

工程地址

https://github.com/tangYong1412/secKill.git