由RP编程联想到一个Apache Async Http Client的问题
最近RP编程很火,笔者也借机脑补了一下,借此跟之前工作时遇到的一个问题发生了关联···
The Four Reactive Principles
- Responsive
- Resilient
- Scalable
- Message Driven
其中便是第二点Resilient(弹性的、有复原力的),当看到这个原则时,立刻想起来不久前一个用户遇到的一个BUG便跟这个Resilient有关,并导致用户必须重启服务才能解决,到底是啥有趣的BUG呢,请容笔者细细道来。
某日,一业务开发同学(客户啊)邮件过来直接就问:我的服务发生OOM后经过一次FGC恢复了,但是我的I/O Rector has been shutdown之后就一直没法恢复了是怎么回事呀?是不是你们又搞出来一个BUG呀?收到邮件后仔细看了看,发现报错是从一个RxCachedThreadScheduler-36线程抛出来的信息,大意就是说无法处理请求了(异步请求),啥?RxJava?我们还没用到这玩意儿呢!看了看异常栈之后才顿然发现,其实跟这玩意没关系(注:这个是tomcat自身的一个守护线程,采用观察者模式,一旦IO thread 发生crush后会记录日志通知用户,此处省略一万字···)
仔细看了看代码之后发现,我们在处理async http request的时候用了apache async client包,正是这个包在处理代码时一旦进入STOPED状态后,将无法再次重新进入ACTIVE状态,除非重启进程或者重新new一个client对象,这就让笔者非常纠结了,具体可参见:httpasyncclient-4.1.2.jar 包中CloseableHttpAsyncClientBase.java这个类,纵观此类,2处可导致该client进入STOPED状态:
第一处:
this.reactorThread = threadFactory.newTread(new Runnable() {
@Override
public void run() {
try {
final IOEventDispatch ioEventDispatch = new InternalIODispatch(handler);
connmgr.execute(ioEventDispatch);
} catch (final Exception ex) {
log.error("I/O reactor terminated abnormally", ex);
} finally {
status.set(Status.STOPED)
}
第二处:
@Override
public void close() {
if (this.status.compareAndSet(Status.ACTIVE, Status.STOPED)) {
if (this.reactorThread != null) {
try {
this.connmgr.shutdown();
} catch (IOException ex) {
this.log.error("I/O error shutting down connection manager", ex);
}
try {
this.reactorThread.join();
} catch (final InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
OK,看到这2个地方,应该大家都明白了,第一个地方红色代码处,一旦发生了OOM,new操作会失败抛异常并导致Stauts为STOPED,诡异的是没有找到任何代码再将此状态置回为ACTIVE,那么导致的结果就是这个reactorThread一旦catch住了一个异常(为啥要Catch Exception,尼玛···)这个async client就直接无法再被使用了,更加诡吊的是这个作者在start()方法里写的竟然是:
if (this.status.compareAndSet(Status.INACTIVE, Status.ACTIVE)) {
startThread ...
}
这是完全不给STOPED后再start起来的机会呀!俺们在外面封装了该client,遇到异常我们吃不到,启动也启动不了,这后路断的够绝!
看来是时候给这位大佬提点意见了,不为别的,只为Resilient ... ...
转载于:https://my.oschina.net/u/3796442/blog/1633849
上一篇: 因为manjaro系统更新而导致的python版本混乱问题
下一篇: manjaro启用fcitx5