给大家的福利
零基础入门
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
因篇幅有限,仅展示部分资料
网络安全面试题
绿盟护网行动
还有大家最喜欢的黑客技术
网络安全源码合集+工具包
所有资料共282G,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
@Transactional
public BaseResponse<JSONObject> spike(String phone, Long GoodsId) {
GoodsDto goodsDto = seckillMapper.getByGoodsId(GoodsId);
if (goodsDto == null) {
return setResultError("商品信息不存在!");
}
// 用户频率限制 setnx 如果key存在话
Boolean reusltNx = redisUtil.setNx(phone, seckillId + "", 10l);
if (!reusltNx) {
return setResultError("访问次数过多,10秒后再实现重试!");// 直接return,无需执行下面的version++操作
}
Long version = goodsDto.getVersion();// 先获取版本号
int row = seckillMapper.inventoryDeduction(GoodsId, version);// 减库存
// 后续可以生成订单到订单表。。。
}
@Component
public class RedisUtil {
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 如果key存在的话返回fasle 不存在的话返回true(原生redis的setNx命令会返回0或1)
public Boolean setNx(String key, String value, Long timeout) {
Boolean setIfAbsent = stringRedisTemplate.opsForValue().setIfAbsent(key, value);
if (timeout != null) {
stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
}
return setIfAbsent;
}
public void setList(String key, List<String> listToken) {
stringRedisTemplate.opsForList().leftPushAll(key, listToken);
}
}
3. 基于库存令牌桶 + MQ 实现异步修改库存并提交订单
在高并发情况下,如果有1万个用户同时秒杀某一商品,对数据库频繁的IO操作,可能会产生数据库崩溃问题(分表分库,读写分离治标不治本),解决方法:基于MQ+库存令牌桶实现。
同时有1万个请求实现秒杀,商品库存只有100个, 实现只需要修改库存100次就可以了:
方案实现流程:商品库存是多少,就提前在redis生成多少对应的库存令牌(这里即为100),在1万个请求中,只要谁能够获取到令牌谁就能够秒杀成功, 获取到秒杀令牌后,在使用mq异步实现修改减去库存。
代码实现:
① 编写生成100个令牌桶接口
② 编写获取token代码,并用mq异步发送
RabbitMQ消费者
@Component
Slf4j
public class StockConsumer {
@Autowired
private SeckillMapper seckillMapper;
@Autowired
private OrderMapper orderMapper;
@RabbitListener(queues = "modify_inventory_queue")
@Transactional
public void process(Message message, @Headers Map<String, Object> headers, Channel channel) throws IOException {
String messageId = message.getMessageProperties().getMessageId();
String msg = new String(message.getBody(), "UTF-8");
JSONObject jsonObject = JSONObject.parseObject(msg);
// 1.获取秒杀id
Long goodsId = jsonObject.getLong("seckillId");
SeckillEntity seckillEntity = seckillMapper.findBySeckillId(goodsId);
if (seckillEntity == null) {
log.warn("goodsId:{},商品信息不存在!", goodsId);
return;
}
Long version = seckillEntity.getVersion();
// 2.减库存
int inventoryDeduction = seckillMapper.inventoryDeduction(goodsId, version);
if (!toDaoResult(inventoryDeduction)) {
log.info(">>>seckillId:{}修改库存失败", goodsId);
return;
}
// 3.添加订单
OrderEntity orderEntity = new OrderEntity();
String phone = jsonObject.getString("phone");
orderEntity.setUserPhone(phone);
orderEntity.setSeckillId(goodsId);
orderEntity.setState(1l);
int insertOrder = orderMapper.insertOrder(orderEntity);
if (!toDaoResult(insertOrder)) {
return;
}
log.info(">>>成功消费seckillId:{},秒杀成功!", goodsId);
}
// 调用数据库层判断
public Boolean toDaoResult(int result) {
return result > 0 ? true : false;
}
}
③ 提供一个根据用户信息查询秒杀结果接口(实际开发中,也可以根据userId)
@GetMapping("/checkSpike")
public BaseResponse<JSONObject> getOrder(String phone, Long goodsId) {
if (StringUtils.isEmpty(phone)) {
return setResultError("手机号码不能为空!");
}
if (goodsId== null) {
return setResultError("商品库存id不能为空!");
}
OrderEntity orderEntity = orderMapper.findByOrder(phone, goodsId);
if (orderEntity == null) {
return setResultError("正在排队中.....");// 要么还没被mq消费,要么没抢到token令牌
}
return setResultSuccess("恭喜你秒杀成功!");
}
public interface OrderMapper {
@Select("SELECT goods_id,user_phone,stateFROM order_table WHERE USER_PHONE=#{phone} and goods_id=#{goodsId} AND STATE=1")
OrderEntity findByOrder(@Param("phone")String phone, @Param("goodsId")Long goodsId);
}
前端需要写一个定时器,用于查询秒杀成功状态:
前端调用秒杀接口spike,如果秒杀成功的话,返回正在排队中。。。
前端写一个定时器调用checkSpike接口,使用手机号/userId + 商品id查询是否秒杀成功。
(如果调用spike返回售罄,则前端不用写定时器)
三. 网关优化
1. 基于Google的guava实现限流(基于令牌桶)
令牌桶实现原理: 以规定的速率往令牌桶中存入Token,用户请求必须获取到令牌中的Token才可以处理 请求,如果没有从令牌桶中获取到令牌则丢失该请求。 例如:令牌桶中最多只能存放50个Token,以规定速率存入Token实现在高并发情况下限流 。
Google的Guava工具包中就提供了一个限流工具类——RateLimiter,本文也是通过使用该工具类来实现限流功能。RateLimiter是基于“令牌通算法”来实现限流的,具体步骤如下:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
在zuul网关过滤器的run方法里,加入以下代码:
@Component
@Slf4j
public class GatewayFilter extends ZuulFilter {
// 每秒存入令牌中token数为1
private static final RateLimiter rateLimiter = RateLimiter.create(1);
public Object run() throws ZuulException {
/** 这里省略一系列的验证token,黑名单白名单等... */
/*
默认超时时间是0,意思是拿不到就立即返回false,如果想修改超时时间,采用该代码:
boolean tryAcquire = rateLimiter.tryAcquire(0, TimeUnit.SECONDS);
*/
boolean tryrateLimiter.tryAcquire(); //阻塞等待超时时间,这里设为0,如果没有拿到令牌,直接拒绝访问,无需等待
if (!tryAcquire) {// 返回false,表示没有获取到令牌,直接return
resultError(500, ctx, "现在抢购的人数过多,请稍等一下下哦!");
return;
}
// 否则,获取到令牌,放行,继续执行后续逻辑,待所有过滤都通过,则直接访问秒杀接口...
}
}
2. 使用Hystrix实现服务线程池隔离
默认情况下,上面的秒杀接口spike和查询秒杀结果接口checkSpike,都在一个线程池;在高并发场景,秒杀接口的压力会非常大,当一秒内用户全部请求秒杀接口,线程池都去处理秒杀接口,没有空闲线程去处理查询秒杀结果接口,这时候会产生延迟等待问题(默认tomcat只有一个线程池去处理所有请求,一旦线程池满了,导致其他线程无法访问)。
同时请求spike和checkSpike接口,打印日志如下:
>>>>>秒杀接口线程池名称:http-nio-9800-exec-1
>>>>>查询秒杀结果线程名称:http-nio-9800-exec-2
可以看到,两个接口处于同一个线程池,下面引入Hystrix实现服务降级,隔离:
<!-- 引入hystrix依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
**先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7**
**深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/c12e6e964b33dfa8a98fa373a93ea235.png)
![img](https://img-blog.csdnimg.cn/img_convert/a77384b772a1477081bf237593031f2b.png)
![img](https://img-blog.csdnimg.cn/img_convert/9fc2bc050848a76c90d36ea64484fe7a.png)
![img](https://img-blog.csdnimg.cn/img_convert/db5dad658fbc97068b2ec12c179d5625.png)
![img](https://img-blog.csdnimg.cn/img_convert/00ff536c81be3e75b8027decfcc91f4b.png)
![img](https://img-blog.csdnimg.cn/img_convert/a3ce4f605d726bac56ec62c8db06f5c9.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
15499936356)]
[外链图片转存中...(img-4VJfYxmh-1715499936356)]
[外链图片转存中...(img-CW2N1F4Z-1715499936357)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**