Skip to content

online problems practice

landon edited this page Dec 7, 2018 · 10 revisions

线上问题排查定位实战(游戏服务器)

  1. 监控先行
  2. 线上常见问题
  3. 问题排查、定位、解决
  4. 参考、补充
  5. Q & A

监控先行

  1. 游戏正式上线后,研发这边可能没有线上服务器的权限,不能直接在线上服务器排查问题,所以必须要监控先行-grafana
    • 测试期间有线上服务器权限,可以使用一些命令行直接排查问题
    • 不过强烈建议将监控指标定时采样到监控服务器
  2. 监控指标
    • 业务参数
      • tps(throughput)、latency
      • connections
      • threadpool#queue size
      • method execute time(logic handler/db save/db load/startup/shutdown/login/logout)
      • error log
    • jvm 参数(jstat/jmx)
      • class
      • S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
      • DeadlockDetector
      • thread state
      • cpu
    • db
      • mongo/redis
      • slow operations
      • high flow
      • connections
    • os参数
      • cpu、memory、io(带宽/流量)、network
  3. 业务参数直接打点监控、jvm参数可直接通过jmx api获取
    • 注腾讯的机器只能往里进 不能出来 即不能push信息到外部;只开放部分端口
    • 要使用pull的方式
  4. 监控图形化界面、报警(钉钉)

线上常见问题和现象

  1. 玩家卡
    • cpu高(如死循环、无限递归、fgc-stw),当前业务线程被占用,其他消息排队
    • 线程被阻塞,如访问一个三方http,超时
    • 死锁
    • 方法执行耗时如大量玩家登录
    • 并发太高,线程处理不过来,导致排队,出现'雪崩效应'
  2. 内存飙高(溢出、泄露)
    • java 进程#res、OU一直增加
    • FGC、FGCT增加,回收后内存没有明显变化
    • 注:GC后res不变,不会还内存给os
    • oom
    • oom-killer
    • 堆外内存泄露
  3. 数据库
    • crash(如mongo primary节点挂掉-如被oom-kill)
    • 连接数问题,可能出现操作mongo时抛出异常
    • redis变慢
    • 数据库内网流量很大(一个mongo副本集可能服务器多台backend),内网带宽被撑爆
  4. 业务bug
    • 刷资源-回档
      • 如策划配错了一个大数值
      • 如邮件领取bug导致邮件未删除
      • 如业务bug先加未扣
      • 如扣钱逻辑不验证,外挂发过来负数,导致加钻
    • 逻辑参数验证问题
      • 如输入被外挂攻击,如之前的商店购买,正常最多购买10个,但是外挂发过来1亿个
    • 未处理异常
      • 时间调度业务未处理异常,导致影响其他时间调度的业务
      • 打点、推送、日志等抛出异常,影响业务逻辑
    • 网络层问题
      • 顶号、断线重连、每日重置
    • 登录异常(登录抛异常导致玩家无法登录,要注意新业务不要影响就玩家要做数据兼容,或者数据时要登录做脚本修复-避免玩家无法登录)、支付问题(支付未发货、刷单—未排重、丢单)
    • vms/global
      • 版本更新、登录验证、支付
    • 三方http未做超时处理(连接超时、read超时),导致卡住业务线程,如监控的上报服务
    • ...

问题排查定位、解决

  1. 整体情况

    top # 监控整体CPU和内存
    P   # 按照CPU排序
    M   # 按照内存排序 可主要观察res
    
    jps -v # 查看java进程启动参数
    
    load/us/id/...也可以看一下
    
    整体cpu如果超过70% 就要报警
    整体内存如果超过70% 就要报警
    
    free -g # 需要看 + buffers/cache
    
  2. 整体卡

    jstat -gcutil # 确认一下是否是fgc引起的stw
    top –Hp pid  # 查看哪个线程占用cpu高
    printf 0x%x tid # 转为16进制
    jstack pid | grep nid –A 10 # 查看线程堆栈,找到占用cpu高的线程堆栈从而确认
    
    # 可多次jstack,如果发现某业务线程的堆栈一直是固定的某一个,可能死循环、死锁、blocked
    
  3. 内存问题较高

    jinfo pid/jps -v # 确认整体jvm启动参数
    top + M + res # 确认Java进程res是否较高
    jmap -heap # 确认java内存整体占用(cms#jdk低版本显示有bug),主要确认堆内存和metaspace是否占用过高
    jstat -gcuitl # 二者结合
    jmap -histo | head # 按照实例排序,注意如果加上live参数的话,会强制执行一次fgc
    
    jcmd pid VM.native_memory summary # Native Memory Tracking,需要启动参数增加-XX:NativeMemoryTracking=detail
    
    # 其他工具
    pmap -x pid
    google-perftools #分析堆外内存
    
    # 注:如果发现内存确实涨的很厉害,很快可能要oom了
    1. 使用jmap -dump:format=b,live,file=MemoryLeak.hprof pid # 将堆内存快照导出来分析,可能会卡几秒,mat进行分析
    2. 如果无法即时发现oom的问题,那么此时建议重启服务器,否则oom或者oom-killer可能会回档,后果比较严重
    
    # 之前出现过的oom-killer问题
    1. python进程占用内存较高,触发了oom-killer,killer了java进程
    2. java进程越来越多的临时对象进入ou,但是一直未触发fgc(但此时res可能已经很高),此时mongod触发存库,也占用内存,触发了oom-killer(单机集群)
    3. 可以强制执行一次fgc 如通过jmap histo:live或者jcmd pid GC.run或者System.gc
    
  4. 数据库统计

    # mongo统计
    mongostat -h xxx:40001  -u 'uuu' -p ppp--authenticationDatabase admin -n 10
    
    mongotop -h xxx:40001  -u 'yy' -p ppp --authenticationDatabase admin -n 1
    
    db.serverStatus();
    db.stats();
    db.players.stats();
    rs.status();
    
    开启Profiling,慢查询
    
    # redis
    1. redis-benchmark
    2. info(注:掌趣包括腾讯的一些机器很多命令不能使用,如keys *)
    
    
  5. 其他辅助

    • http://xxx 玩家实时在线
    • http://yyy 监控系统信息(cpu/内存/流量)
    • 如果是内部测试可以使用jconsole/jvisualvm/yourkit/jprofiler直接观察
      • 建议使用java11开源的jfr
    • 日常开发可直接使用远程调试debug
    • 服务器日志
      • 熟练使用less(/、G、gg、n、N、ctrl + b、ctrl + f)、grep(-A、-B、-C)
      • 注:线上服务器通常不要直接使用less或者vim打开大文件,会比较占用内存和cpu,而且使用完毕一定要退出,否则会一直在后台,如top直接就可以看到less会占用很高的cpu
  6. 问题定位和解决

    • 直接增加日志排查,更建议使用btrace/greys/jvm-sandbox
    • 使用bsh,查询内存数据
    • 导号到内网,尝试复现解决bug
    • 配置表可以直接热更(指后端)
    • hotfix解决bug(建议使用instrumentation)

参考、补充

  1. java -profiling-practice
  2. Java调优系列之工具篇之btrace、gperftools
  3. JVM内存非典型术语介绍
  4. oom-metaspace
  5. fastjson-heap-oom
  6. 游戏服务器数据存储策略和宕机保护
  7. Java项目中mongo问题总结
  8. jvm-sandbox
  9. greys
  10. btrace
  11. gperftools
  12. show-busy-java-threads
  13. 【译】MongoDB的监控
  14. Redis性能监控

Q & A

  1. jmap -histo 发现Player实例有819个,但在线玩家只有90多个,而数据库实际的玩家也只有690多个?why?
    • jmap -histo:live参数后,执行fgc后,Player实例变为117个,说明确实是临时对象
    • TODO 需要排除原因,为什么实例有819个?难道有多个实例Player指向同一个player?
  2. 做一个实现,有一个hashmap,put了很多对象,然后调用了clear,但是没有触发gc,此时实际占用的内存?
    • TODO 测试
  3. jdk11的zgc可以了解一下,避免stw
  4. 之前服务器突然卡了一下(所以玩家卡了一小下),可能是因为fgc#stw
Clone this wiki locally