我遇到的生产事故

事故一,jvm相关

  1. 大对象(运营商数据;数据库查询未加查询条件,结果集过大;第三方接口或异步消息);来回转化

  2. 死循环;

  3. 推文并发量大

  4. String.intern() 导致oom

  5. static字符串拼接 导致oom

  6. 堆内存过小

  7. ConcGCThreads 线程过多,stw,导致性能上不去

  8. jvm配置问题,堆、对象晋升(进入老年代过快或过慢)

  9. 额度服务因stw停顿过长导致程序性能不稳定

  10. 堆外内存过大;

堆外内存,人脸ocr服务,照片上传 排查方法:

`jmap -heap 查看进程jvm的使用情况`
`jmap -histo  pid  统计对象的数量`
`jmap -dump:live  dump堆对象`
`jstack 快速连续几次输出(建议shellfor循环,sleep 1秒)`
`jstat -gcutil pid 2`
`工具:show-busy-java-threads`
 `阿里的阿尔萨斯`
`查询是否有慢sql`
``select * from information_schema.`PROCESSLIST` t where t.INFO is not null ORDER BY t.TIME desc;``
`针对慢查询sql生成kill语句;`
``select CONCAT('kill -9 ',t.ID,';') from information_schema.`PROCESSLIST` t where t.INFO is not null ORDER BY t.TIME desc;``
`统计tcp的数量`
`netstat -na|grep ESTABLISHED|wc -l`
`pstree -a|wc -l 统计当前进程总数`
`ulimit -a 查看用户支持线程数`

事故二:并发多线程问题

  1. 内存中额度扣减或增加,并行时,最终不一致;

  2. log4j 1多线程堵塞;

  3. 多线程静态锁synchronized;

  4. 消息消费执行顺序不一致 解决:

  • 确保执行顺序 -> 设置msgid(rocketMq)或partitionKey (kafka)

  • 多线程时,同一个用户确保在一个线程里

  • 将额度扣减和增加改为 sql语句执行,利用mysql本身的机制处理

事故三:并发幂等问题

  1. 额度重复恢复 --> 推入消息队列,做幂等处理

  2. 用户重复下单 --> 临时表,redis分布式锁

  3. 本地有序queue 以上方案都需要确保停机数据不丢失

事故四:缓存雪崩

  1. 同一时间大批量临时额度到期导致

  2. redis故障 解决:

  • 大批量数据刷入缓存,失效时间+一定范围的随机数,错峰

  • 针对热点数据或共用数据,定时批量刷缓存

  • 针对数据的实时性要求不高的话,可做本地缓存

事故五:redis相关事故

  1. 代码生成器自带开启事务,导致redis链接未及时释放,无连接可用;

  2. 缓存共用,某些后台项目使用keys *

  3. 大对象存储,长时间占用cpu资源和带宽导致redis其他操作大量超时;

  4. redis缓存不设置有效期;解决:

  5. 代码生成器默认无事务,并制定规范;

  6. 自建redis 屏蔽keys操作

  7. 制定规范禁止大于100kb的数据存储,可以统一缓存工具类限制value大小

事故六:磁盘IO导致线程阻塞,cpu彪高

特征:

  1. cpu占用过高,gc频繁;

  2. 发现log4j的线程占用过高;

  3. 日志文件过大(几十g),同时日志输出延迟;禁止System.out.println,禁止console输出,日志切割

  4. log4j1.* 并发死锁

事故七:无可用线程可创建

1,appuser启动的项目,默认只有1024,通过ulimit -a查看

2,一台ecs部署多个tomcat,请求量稍微大些的时候会出现该问题

3, open文件的个数;

ps:注意下文件句柄数

 `cat /etc/security/limits.d/90-nproc.conf`
`appuser    soft    nproc     10240`
`appuser    hard    nproc     10240`

事故八:高并发情况下短连接释放过慢,大量链接处于time_wait

操作系统默认 240 秒后,才会关闭处于 time_wait 状态的连接

推荐几篇博文,从根上了解下

Linux上TCP的几个内核参数调优

从Linux源码看TIME_WAIT状态的持续时间

从Linux源码看Socket(TCP)的accept

从linux源码看socket(tcp)的timeout

vim/etc/sysctl.conf#编辑文件,加入以下内容:net.ipv4.tcp\_syncookies =1#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;net.ipv4.tcp\_tw\_reuse =1#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;net.ipv4.tcp\_tw\_recycle =1#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
,NAT环境必须为0
;net.ipv4.tcp\_fin\_timeout=30#修改系統默认的 TIMEOUT 时间。#然后执行以下命令让参数生效/sbin/sysctl -p

事故九:数据库死锁问题

  1. 常见给慢sql添加索引或修改表结构,表锁导致慢sql,以及无法insert

  2. 复杂查询带来的死锁;

事故十:域名劫持

前端h5,引导到联通的广告 更换https

事故十一:宽带资源耗尽

前端访问过慢,10mb带宽升级到100mb(app升级包未用cdn加速,直接在挂在项目的域名下) 外网100mb的宽带

  1. 静态资源cdn;

  2. 开启tomcat/ng压缩;

  3. 增加带宽

事故十二:静态锁导致的并发问题

额度重构,分表后批量生成主键id,静态方法加锁,多线程调用,导致死锁

  1. 临时去掉静态方法

  2. 使用雪花算法

事故十三:tomcat配置问题

  1. maxPostSize=“0” 之前0为不限制,升级一次tomcat版本到7.0.70,0的含义变为了post过来的数据量为0,导致生产服务不可用;

  2. 多个tomcat部署到一台实例线程数不够用,无法创建本地线程

  3. tomcat 线程少,acceptCout大,

tomcat优化:

  1. nio ;

  2. 线程池数量& acceptCount ;

  3. gzip压缩

  4. catalina.out ,日志切割(最好的办法就是不往catalina里输出日志)

`日志切割`
`vim /etc/logrotate.d/auth`
`/app/auth/apache-tomcat-8.5.28/logs/catalina.out {`
 `copytruncate`
 `dateext`
 `daily`
 `rotate 10`
 `missingok`
 `notifempty`
 `compress`
 `delaycompress`
`}`

tomcat 配置

`独立tomcat配置4c8g建议配置`
`<Executor name="tomcatThreadPool" namePrefix="quota-exec-"  maxThreads="1000" minSpareThreads="200"/>`
`<!-- namePrefix为项目名-->`
`<Connector  executor="tomcatThreadPool"  port="9000"` 
 `protocol="org.apache.coyote.http11.Http11NioProtocol"`
 `connectionTimeout="1000"`
 `redirectPort="8443"`
 `URIEncoding="UTF-8"`
 `maxPostSize="0" # 慎用此参数,在低版本上,该参数不限制postsize,7.0.70上,则表示post为0`
 `maxThreads="1000"` 
 `minSpareThreads="200"`
 `acceptCount="1000"` 
 `compression="on"` 
 `compressionMinSize="2048"` 
 `noCompressionUserAgents="gozilla,traviata"` 
 `CompressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,text/json,application/x-javascript,application/javascript,application/json,image/png,image/jpeg"`
 `/>`
`server:`
 `port: 7424 # tomcat端口号`
 `tomcat:`
 `uri-encoding: UTF-8 # tomcat编码`
 `accept-count: 1000  # 等待队列,默认100`
 `max-connections: 2000  # nio默认10000,链接数达到max-connections的时候会继续接收accept-count数`
 `max-threads: 1000  # 最大线程数,nio,4c8g建议800`
 `min-spare-threads: 100`
 `max-http-post-size: -1  # 有的版本是0,最好根据实际业务设置个大小`
 `connection-timeout:`
 `1000`
 `compression:`
 `enabled: true`
 `servlet:`
 `path: /`
 `session:`
 `timeout:`
 `600`

事故十四 数据库

  1. 多个业务库共用一个实例,部分业务统计到只数据库cpu彪高;->核心业务库独立;

  2. 慢sql,无索引,或者索引类型不对;

  3. 修改库表结构时,锁死;

  4. 复杂嵌套sql;

  5. 对查询条件的字段进行函数处理,导致全表扫描;

  6. 主键非自增,导致数据全表扫描;

事故十五:redis的key已过期,但还能获取

用户请求量,在一段时间内,只能请求2w次,用了一个固定key缓存,到了第二天还有效 当redis的cpu过高的时候,定期删除就不一定启动作用;定期删除& 惰性删除 定期删除: 定期从redis中获取数据,检查并删除,cpu过高时就无法执行,有很大概率能拿到未删除的key 惰性删除:每次get的时候主动去校验,会影响redis的性能,量不大可用

事故十六 同一个用户启动多个dubbo项目;

  1. dubbo的缓存文件是固定名称和路径的,同一个用户启动dubbo会导致.dubbo文件被覆盖

  2. 改变缓存文件的名称和路径

事故十七 定时任务中创建线程池;

  1. 重复创建线程池;

  2. 导致资源打满,cpu彪高,服务假死;

事故十八,默认超时时间 60秒

导致系统群雪崩;

  1. 业务板块拆分并独立域名;

  2. 架构有向无环;

  3. 对非关键业务熔断,制定统一的业务超时标准;

事故十九 线程池打满

服务调用使用httpclient的线程池模式, 当某个接口慢的时候,导致链接堵塞,直接把所有的线程都耗费掉了,影响了其他的系统调用;

线程池有个配置max-connections-per-route,按接口来,最多能占用多少链接,一般设置为1/2或者1/3

事故二十 消息积压

  1. 后端消费堵塞(因为内外部系统宕机)

  2. 新进来的用户处理不了(风控,授信);

  3. 慢sql+异常重试;

解决

  • 修复系统问题

  • 水平扩展,修改partition数量增加消费节点(大部分能解决,得注意下游的处理能力,要不然会压垮);

  • 直接将挤压的消息读取到一个新的topic,先不影响新用户,再监听新topic(如果后端用线程池不要共用)

  • 死信队列

事故二十一 threadlocal事故

当某个用户进入系统时,会将用户信息缓存到threadlocal中一份,开发没有在finally中移除 测试和生产tomcat配置的是线程池,最小线程都是200 当用户使用独立的线程的时候,都没有问题,当线程被重复使用时,就铁定出问题;

时间工具类,未从threadlocal中移除,导致时间不一致

定时任务单节点故障

单节点定时任务故障:

  1. 系统宕机 --> 健康检查

  2. 系统正常运行,但定时任务停止 --> 分布式定时、多节点执行,利用分布式锁,只能同时有一台执行(ps 锁一定要设置有效期)

线程池事故

  1. 使用Executors.newFixedThreadPool 创建线程池,队列是无界队列(Integer.MAX_VALUE),导致oom;

  2. 使用Executors.newCachedThreadPool 创建线程池,corepoolsize 为Integer.MAX_VALUE

  3. 核心业务和非核心业务共用线程池,非核心业务堵塞,导致核心业务无法执行(还有spring的@Async注解,类似);

  4. 定时任务里创建线程池,导致资源不够用,任务处理不及时,导致cpu彪高;

  5. disruptor 配置

事务里调用接口

接口超时导致事务回滚,导致数据库链接数过多;引起服务排队,获取不到资源:

代码生成器不能生成带事务的代码

其他非技术性事故

  1. slb白名单 checklist

  2. 数据库,redis白名单 checklist

  3. kafka 和ecs不在一个域里,网络不通 checklist

  4. sql未执行就上线 checklist

  5. 测试不到位 单元测试规范

  6. 拆表后dts同步,dba未及时将同步去掉,数据迁移规范化操作;

  7. 链接和超时时间用默认 checklist;

  8. topic未创建, checklist;

想了解更多,请关注公众号哦。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值