前记
记录一些实战经验
线上统一时间全部OOM(out of momory)
为了保证线上服务可用,直接重启了机器,先保证可用
这就导致了无法dump出事发时的内存,看了下JVM的监控表,发现在某一个时间线程一直在上升到了3W。而我们正常的线程数是600左右,看了下其实的时间点,是有一个代码提交了
1
HttpClient.setMaxÇonnTotal(400).setMaxConnPerRoute(150).evictExpiredConnections().build()
之前加了这个参数是因为,有不少 NoHttpResponseException 异常,在TCP周期,三次握手,然后发送数据,最后四次挥手,Http1.1之后,keep-alive是默认开启,在设置的timeout后,连接就会释放。而NoHttpResponseException异常,是因为,在timeout后,服务端发出FIN,还没到达客户端的时候,客户端发起新的数据请求,而服务端在四次挥手期间不能接受报文,所以返回RST,引发了NoHttpResponseException。然后通过查看文档,发现增加一个 evictExpiredConnections()可以再调用的时候产生一个线程,会定时清理空闲链接。
因为我们对每个请求都创建了一个HttpClient都会调用evictExpiredConnections,就会导致有多少个请求会创建多少个定时形成。
针对以上问题,我们首先吧httpClient改成了单例,另外对线程数做了监控,能在oom前及时发现处理
记一次线程池引发的故障
我定义了一个线程池来执行任务,但是程序执行结束后任务没有完全执行完
业务场景:
统计业务需要,订单信息需要从主库经过业务代码写入统计库(中间需要逻辑处理不能走binlog)之前的接口是单线程的,100万条订单信息,100条需要10s ,所以需要很长时间。所以计划使用线程池,为每一个中心分配一条线程去执行业务
开了5个核心线程,使用有界阻塞队列。中间发现有个线程的状态是wait,但是相对应的日志才跑了一半。之后发现是因为业务代码有异常,所以中断了。我是用submit提交任务,但是任务中的异常被吞掉了
通过看源码,发现异常是设置到了一个变量outcome中,就是对submit方法返回的FutureTask对象执行get()方法得到的结果
但是在线程池中,并没有获取执行子线程的结果,所以异常就没有被抛出来、
所以在定义 ThreadFacotory创建线程的时候,调用 setUncaughtExceptionHandle,自定义异常处理方法。之后就在线程池,子线程的异常要专门去捕获一下
支付宝支付问题
-
支付超时问题
支付宝在发起支付后,可以设置支付超时时间,我们设置的是5分钟,然后我们自己设置的支付超时时间是5分钟,按道理来说,在我们这里规定的支付超时之后,就会返回库存,并且订单设置为超时,用户如果在此后支付支付宝也不会通过,但是如果出现误差,导致支付宝还能成功,在回调这里,就需要添加新的规则,比如给用户退款。同时我们的支付超时也稍微调小了点,和支付宝那边的超时拉开距离。保证我们的超时时间小于支付宝超时时间
—zw—- 理想:同时过期,但不会发生
现实
— z -支付失败– w—-
—w-支付成功需要退款–z
—最主要的是在回调那里,做好判断,需要判断当前订单的状态,不能任务支付宝回调就是成功
-
超卖问题
之前是在没有事务中用了forupdate
改成了 加事务的forupdate
改成了 乐观锁
dubbo中遇到的问题
自定义了异常,抛出的确是 RuntimeException
通过抛出异常,发现异常处理的Invoker,发现异常类和接口在同一jar包,才会抛出我们自定义的异常
其实dubbo的这个考虑,是基于序列化来考虑的,如果provider抛出一个仅在provider自定义的一个异常,那么该异常到达consumer是无法序列化的
dubbo中如何定义全局异常处理
通过filter和spi