【架构-Nginx】Nginx 限流实战|定点12点500万并发抢红包,限额15000请求+每日自动重置闭环方案
文章目录一、业务需求梳理 核心2大诉求整体业务流程图Mermaid彩色版二、整体架构设计思路 三、Nginx 完整配置实现 ️3.1 nginx.conf 全局限流配置3.2 红包接口 location 拦截配置四、定时重置脚本crontab每日12点执行 ⏰4.1 重置脚本 reset_redpacket.sh4.2 脚本授权命令4.3 crontab 定时任务配置五、Java后端红包库存控制逻辑兜底第二层拦截 ☕Redis库存工具类核心逻辑六、运维常用操作命令 1. 校验Nginx配置是否生效2. 手动重载Nginx刷新限流计数3. 查看Nginx限流日志4. 手动执行重置脚本测试5. 实时监控Redis红包库存七、关键问题优化点 ✨八、扩展优化方案生产高阶 一、业务需求梳理 核心2大诉求定点定时生效每日12:00自动开启红包限流拦截非12点时段接口正常放行双层限流控制第一层Nginx前置拦截全局只放行**15000**个请求超出直接返回红包已抢完JSON第二层放行的15000请求内部消耗10000个红包额度额度耗尽后接口永久拦截直到次日12点自动重置峰值场景午间瞬时**500万**并发纯Nginx层拦截减少后端服务压力避免雪崩整体业务流程图Mermaid彩色版定时重置计数/库存是否是否客户端并发请求500W QPSNginx网关层限流拦截模块定时任务每日12点重置计数当前放行计数≥15000?红包库存≤0?Java红包服务扣减红包库存返回JSON红包已抢完正常抢红包返回结果二、整体架构设计思路 Nginx 限流选型使用ngx_http_limit_req_module 共享内存计数器持久化计数文件定时定点控制Linuxcrontab每日12点执行脚本重置Nginx计数器恢复放行权限双重熔断机制Nginx层硬限制最大放行15000次超量直接拒绝不打穿Java服务Java服务层红包库存10000库存清零后接口直接返回已抢完不再执行业务逻辑数据存储Nginx共享内存存储放行请求数Redis存储红包剩余库存Java层三、Nginx 完整配置实现 ️3.1 nginx.conf 全局限流配置# 共享内存区域红包接口计数器存储15000请求计数共享内存10M limit_req_zone $uri zonered_packet:10m rate10000r/s; # 持久化计数文件重启Nginx不丢失当前放行计数 limit_req_file /var/nginx/red_packet_count.txt zonered_packet; # 自定义限流返回JSON红包已抢完 limit_req_status 429; error_page 429 packet_full; location packet_full { default_type application/json; return 200 {code:999,msg:红包已抢完,data:null}; } # 定时开关控制变量默认关闭红包限流 set $packet_switch 0; # 利用Nginx时间判断每日12点~14点开启红包限流窗口 if ($time_iso8601 ~ T12|T13) { set $packet_switch 1; }3.2 红包接口 location 拦截配置location /api/redPacket/grab { # 非12-14点直接放行不限流 if ($packet_switch 0) { proxy_pass http://java_backend; break; } # 限流规则最大放行15000个请求突发不排队超量直接429 limit_req zonered_packet burst15000 nodelay; proxy_pass http://java_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }四、定时重置脚本crontab每日12点执行 ⏰4.1 重置脚本 reset_redpacket.sh#!/bin/bash# 1.清空Nginx红包计数器持久化文件echo0/var/nginx/red_packet_count.txt# 2.重载Nginx配置刷新共享内存计数nginx-sreload# 3.调用Java后台接口重置Redis红包库存为10000curl-XPOST http://127.0.0.1:8080/api/redPacket/resetStockecho每日12点红包限流计数、库存重置完成4.2 脚本授权命令chmodx /usr/local/script/reset_redpacket.sh4.3 crontab 定时任务配置# 每日中午12:00整执行重置脚本012* * * /usr/local/script/reset_redpacket.sh/var/log/redpacket_cron.log21# 查看定时任务crontab-l# 编辑定时任务crontab-e五、Java后端红包库存控制逻辑兜底第二层拦截 ☕Redis库存工具类核心逻辑/** * 红包抢单兜底拦截Nginx放行15000次实际仅10000个红包 */ServicepublicclassRedPacketService{privatestaticfinalStringRED_PACKET_STOCK_KEYred:packet:stock;privatestaticfinalIntegerMAX_STOCK10000;AutowiredprivateStringRedisTemplateredisTemplate;// 每日定时重置库存接口crontab调用PostMapping(/api/redPacket/resetStock)publicResultVoidresetStock(){redisTemplate.opsForValue().set(RED_PACKET_STOCK_KEY,MAX_STOCK.toString());returnResult.success();}// 抢红包核心接口GetMapping(/grab)publicResult?grabPacket(){// 原子扣减库存LongremainStockredisTemplate.opsForValue().decrement(RED_PACKET_STOCK_KEY);if(remainStock0){// 库存耗尽直接返回已抢完returnResult.error(999,红包已抢完);}// 正常发放红包逻辑returnResult.success(领取成功);}}六、运维常用操作命令 1. 校验Nginx配置是否生效nginx-t2. 手动重载Nginx刷新限流计数nginx-sreload3. 查看Nginx限流日志tail-f/var/log/nginx/error.log|grepred_packet4. 手动执行重置脚本测试sh/usr/local/script/reset_redpacket.sh5. 实时监控Redis红包库存redis-cli get red:packet:stock七、关键问题优化点 ✨500万并发防雪崩全部无效请求在Nginx直接拦截不建立Java服务连接大幅降低后端CPU/连接池压力计数持久化使用limit_req_file存储放行计数Nginx重启不会丢失已放行请求数量时间窗口可控可修改Nginx$time_iso8601正则自定义红包活动时段示例12~14点双层兜底Nginx控制总放行量Redis库存控制实际红包数量双重保障超发自动循环crontab每日12点自动清零计数重置库存无需人工干预八、扩展优化方案生产高阶 分布式Nginx集群单机共享内存失效替换为lua-resty-redis实现分布式统一计数器动态调整额度通过Lua脚本读取Redis配置动态修改放行15000阈值无需改配置重载Nginx监控告警监控429状态码占比并发突增推送钉钉/短信告警流量削峰配合Nginx队列缓冲瞬时超大并发平滑丢弃无效请求