由RP編程聯想到一個Apache Async Http Client的問題

最近RP編程很火,筆者也藉機腦補了一下,藉此跟以前工做時遇到的一個問題發生了關聯···java

 

The Four Reactive Principlesreact

  • Responsive
  • Resilient
  • Scalable
  • Message Driven

 

其中即是第二點Resilient(彈性的、有復原力的),當看到這個原則時,馬上想起來不久前一個用戶遇到的一個BUG便跟這個Resilient有關,並致使用戶必須重啓服務才能解決,究竟是啥有趣的BUG呢,請容筆者細細道來。apache

 

某日,一業務開發同窗(客戶啊)郵件過來直接就問:個人服務發生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狀態:tomcat

第一處:異步

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)

          }

第二處:async

@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()方法裏寫的居然是:ide

if (this.status.compareAndSet(Status.INACTIVE, Status.ACTIVE)) {this

     startThread ...spa

}

這是徹底不給STOPED後再start起來的機會呀!俺們在外面封裝了該client,遇到異常咱們吃不到,啓動也啓動不了,這後路斷的夠絕!

 

看來是時候給這位大佬提點意見了,不爲別的,只爲Resilient ... ... 

相關文章
相關標籤/搜索