常见生产环境问题及排查方法

陆续解决过很多生产问题,每次没有记录过一段时间就忘记了

  1. 服务启动的时候运行卡住了

    • case by case 解决,有时候需要把日志级别改为debug才能看到真正的原因
    • 有一次是因为mysql连接密钥错误,导致启动hold住,也没有任何提示
    • 有一次是因为封装了BeanDefinitionBuilder来自定义bean,实例类的一个属性变量executor增加了@Setter和@Getter注解,所以要求必须注入一个bean对象,程序定义了多个线程池对象不知道使用哪个,无限循环创建这个bean最后会内存溢出。
      • 解决方案一:给某个主线程池加上@Primary注解
      • 解决方案二:这个属性不需要直接设为null,beanDefinitionBuilder.addPropertyValue(“excecutor”, null);
  2. 服务内存溢出

  • 查看监控可以看到线程数在不断的增加
    • 查看线程总数
      • jstack -l {pid} |grep java.lang.Thread.State|wc -l
      • top -Hp {pid}
      • ps huH p {pid}| wc -l
      • cat /proc/{pid}/status
      • pstreee -p {pid} |wc -l #需要安装:yum -y install psmisc
      • ls -l /proc/{pid}/task|wc -l
  • 统计最多的线程名字,看到带有"EDS"名字的线程数很多,这个是订阅服务的线程,原因是每次执行方法都开启了一个服务订阅线程导致
  • dump内存使用MemoryAnalyzer分析,mac上安装mat软件分析
    case1:写了一个循环处理上亿的数据发现内存得不到泄露,java.lang.StackTraceElement对象有很多,最后用memoryAnalyzer分析出应该是cat记录了所有异常的堆栈信息导致OOM,处理过程中可以调用Cat.getManager().reset();清理异常堆栈
    在这里插入图片描述
  1. RabbitMQ消息堆积1
  • 查看监控看到有少数线程blocked状态,时间点和停止消费时间点吻合
  • 结论:connetcion断开导致consumer的消费线程blocked,应该是RabbitMQ的broker出现故障导致, 参考rabbitmq异常导致线程blocked
  • 重启服务问题才解决
  1. RabbitMQ消息堆积2
  • 查看监控tidb更新平均时间达到了600ms,导致消费速度低于生产速度
  • 先临时扩容消费者,再根据tidb集群监控看到CPU使用率达到100%, 去tidb管理界面看到另外一条业务线用了很多慢查询,联系他们修正sql
  1. RocketMQ消息没有发送成功
  • RocketMQ Producer没有找到namesrvaddress导致发送失败,失败没有剖出异常
  • producer没有设置instancename,rocketmq开源版本的clientConfig实例之间需要靠instance name来区分,否则会复用同一个底层的instance对象。实际是由于有一个consumer没有设置namesrvaddress导致producer的namesrvaddress时效了
  1. Mongodb查询超时
  • 给一个复杂查询的所有字段都设置了索引,因为有一个字段用了$in查询,所以导致索引失效
  • 解决方案:索引中删除$in查询的字段
  1. Thrift请求参数丢失【gson反序列化thrift对象时基础类型变量丢失】
  • 现象: thrift服务端接口,我调用都正常,但是第三方调用的时候缺失了一个int类型的参数,第三方把请求对象打印出来和断点调试都能看到有这个int参数变量,但是可以确定的是thrift客户端缺失了参数
  • 可以借助arthas工具,watch命令观察thrift调用的参数和返回watch com.xxx.NettyClientRequestInvoker invokeOnce "{params,returnObj}" 'params[0].serviceName equals("server1")' -x 2 -b, 在请求调用前确实没有参数
  • 仔细看第三方的代码,用了gson反序列化对象,断点调试的时候字段确实有值,但是thrift对象的isSetXXX()是false,导致thrift对象在传输的时候忽略了这个变量
  • 原因分析:Thrift请求丢失字段(记一次坑爹请求),thrift optional字段设置时,只能用__set_xx()赋值,否则无效,gson反序列的原理是使用反射给变量字段赋值的
// com.google.gson.internal.bind.ReflectiveTypeAdapterFactory类内部代码
        return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
            void read(JsonReader reader, Object value) throws IOException, IllegalAccessException {
                Object fieldValue = mapped.read(reader);
                if (fieldValue != null || !isPrimitive) {
                    field.set(value, fieldValue); // gson反序列化时使用反射直接给变量赋值
                }
            }

thrift生成的类里面的StandardScheme会对基础类型变量判断是否设置过值isSetXXX

private static class UserStandardScheme extends org.apache.thrift.scheme.StandardScheme<User> {
    public void write(org.apache.thrift.protocol.TProtocol oprot, User struct) throws org.apache.thrift.TException {
      struct.validate();

      oprot.writeStructBegin(STRUCT_DESC);
      if (struct.name != null) { // 对于字符串等基础变量判断是否为null
        oprot.writeFieldBegin(NAME_FIELD_DESC);
        oprot.writeString(struct.name);
        oprot.writeFieldEnd();
      }
      if (struct.isSetAge()) { // 对于基础类型会判断isSetXXX
        oprot.writeFieldBegin(AGE_FIELD_DESC);
        oprot.writeI32(struct.age);
        oprot.writeFieldEnd();
      }
      if (struct.address != null) { // 对于字符串等基础变量判断是否为null
        if(struct.isSetAddress()) { // 如果字段是optioal的,还要判断isSetXXX,public boolean isSetAddress() { return this.address != null; // 这个方法其实还是判断的字符串是否为null}
          oprot.writeFieldBegin(ADDRESS_FIELD_DESC);
          oprot.writeString(struct.name);
          oprot.writeFieldEnd();
        }
      }
      oprot.writeFieldStop();
      oprot.writeStructEnd();
    }

  }
  1. 我的服务监控正常但是上游却报错
    现象:查看自己的服务接口响应都是正常的,但是上游却报错调用超时
    现象分析:比较时间点,虽然自己的接口是在10ms内返回,上游请求时间是10:00:00.000,超时时间是10:00:05.000,但是看自己的服务响应其实是10:00:06.000开始-10:00:06.010结束
    可能原因:中间件打点监控不是完全合理,没有上游请求发出后到下游接口开始处理之间的耗时监控
  • 之前的请求缓冲在队列里面了,线程耗尽了,不能及时响应上游的请求
  • 容器所在物理机网络问题,有时候会出现网络抖动,导致下游的输出没有及时传输到上游服务
  1. app页面在ios上出现了闪烁
    现象:前端h5页面发布服务后,只在ios端出现了闪烁
    现象分析:前端生产环境回退了服务问题还在、客户端web容器已经2个月没有更新过、在safari浏览器打开不会出现闪烁、在beta环境正常
    原因:大佬定位到是反爬组上线了一个新的反爬插件

优秀的排查文章

Java系统线上生产问题排查一把梭

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值