1、案例介绍:

一个基于B/S的MIS系统,硬件为2个CPU,8GB内存的HP系统,服务器是WebLogic 9.2(其实就是前面那个集群间同步导致内存溢出的那篇),正常运行一段时间后,最近发现在运行期间频繁出现集群节点的虚拟机进程自动关闭的现象,从系统日志中发现,在虚拟机进程崩溃之前都发生了大量相同的异常
如下面

java.net.SocketException:Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:235)
at org.apache.axix.transport.http.HttpSender.readHeaderFromSocket(HTTPSender.java:583)
at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:143) 
......

看到这个net.SocketException:Connection reset 就知道是远端断开连接的问题,

2、问题出现的地方

系统最近和一个OA门户(办公管理系统)做了一个集成,在MIS系统工作流的待办事项发生变化时,通过Web服务通知OA门户,把待办事项的变化同步到OA门户,通过SoapUI测试了一下同步待办事项的几个Web服务,发现调用后需要长达3分钟的时间才能返回结果,并且返回结果都是连接中断

3、怎么导致出现这个问题的

由于MIS系统的用户多,待办事项变化很快,为了不被OA系统速度拖累,使用了异步的方式调用了Web服务,但由于两边服务速度完全不对等时间越长就累积了越多Web服务没有调试完成,导致在等待的线程Socket连接越来越多,最终在超过虚拟机的承受能力后使虚拟机进程崩溃

解决办法:通知OA门户方修复无法使用的集成接口,并将异步调用改为生产者/消费者模式的消息队列实现后,系统恢复正常

4、总结

这里就是因为用户太多变化的事项太多,而这个又是服务之间的调用(微服务),同步肯定不行,而异步因为调用的服务运行的时间长一点,不能瞬间结束,所以就堆积下来了,微服务虽然可以设置连接时间,但是一般不会太长,用户不可能等太久,所以只能用消息队列了。

从这我想到了京东面试官问我,如果redis雪崩了呢?
当时没怎么回答上来,因为虽然知道雪崩,但是在项目设计时不应该预防雪崩吗?可能我理解错误,看完这个案例我想到可以先把用户的请求信息放进消息队列,再从消费者端分批次(比如一次几百万或者几千万的请求信息,必须小于redis同时处理的 最大限度)拿出,再用redis进行处理,这里可以预防雪崩。