日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1. Dubbo簡介及線程池策略

Apache Dubbo 是一款高性能、輕量級的開源 JAVA 服務框架。提供了六大核心能力:面向接口代理的高性能RPC調用,智能容錯和負載均衡,服務自動注冊和發現,高度可擴展能力,運行期流量調度,可視化的服務治理與運維。Dubbo之前是阿里開發,并得到廣泛的應用,后來貢獻給了Apache開源組織。

? Dubbo默認的底層網絡通訊使用的是Netty,服務提供方NettyServer使用兩級線程池,其中 EventLoopGroup(boss) 主要用來接受客戶端的鏈接請求,并把接受的請求分發給 EventLoopGroup(worker) 來處理,boss和worker線程組我們稱之為IO線程。

? 如果服務提供方的邏輯能迅速完成,并且不會發起新的IO請求,那么直接在IO線程上處理會更快,因為這減少了線程池調度。但如果處理邏輯很慢,或者需要發起新的IO請求,比如需要查詢數據庫,則IO線程必須派發請求到新的線程池進行處理,否則IO線程會阻塞,將導致不能接收其它請求。

2. 線程池報警

? 生產環境,該服務大約QPS在1萬左右,總共10個節點。最近該服務在高峰期,頻繁觸發流控和降級。查看dubbo日志,大量線程池耗盡的警告日志:

WARN  2021-05-11 **:**:** WARN AbortPolicyWithReport:65 -  [DUBBO] Thread pool is EXHAUSTED! Thread Name: DubboServerHandler-**.**.**.**:**, Pool Size: 500 (active: 500, core: 500, max: 500, largest: 500), Task: 1285578 (completed: 1285135), Executor status:(isShutdown:false, isTerminated:false, isTerminating:false)

? 該服務線程池最大500,通過日志可以看到active線程已經達到500了,線程池耗盡了,這樣勢必造成請求的積壓,觸發流控和降級。

3. 問題排查

? Dubbo可以通過配置,當線程池滿時,會dump出JStack日志出來,便于分析排查問題。一般配置如下:

<dubbo:Application name="${server.name}" >
  <dubbo:parameter key="dump.directory"  value="${account.dubbo.dump.directory:/home/dubbo_dump/}${server.name}${server.id}" />
    </dubbo:application>  

? 默認會輸出到/home/java這個目錄下。

? 通過排查日志發現,大量線程是BLOCKED狀態的,日志如下:

"DubboServerHandler-ip:port-thread-449" Id=633 BLOCKED on java.util.Collections$SynchronizedMap@2d796a15 owned by "DubboServerHandler-ip:port-thread-203" Id=325
    at java.util.Collections$SynchronizedMap.get(Collections.java:2584)
    -  blocked on java.util.Collections$SynchronizedMap@2d796a15
    at com.google.gson.Gson.getAdapter(Gson.java:332)
    at com.google.gson.Gson.fromJson(Gson.java:802)
    at com.google.gson.Gson.fromJson(Gson.java:768)
    at com.google.gson.Gson.fromJson(Gson.java:717)
    at com.google.gson.Gson.fromJson(Gson.java:689)
    ...

? 通過查看日志發現,最后問題出現在Gson做json反序列化時造成的。再來查看下Gson的源碼發現:

public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
    TypeAdapter<?> cached = typeTokenCache.get(type);
    if (cached != null) {
      return (TypeAdapter<T>) cached;
    }
    ...
  }

? Gson這里是獲取適配器,Gson是通過適配器設計模式,問題就出現在獲取適配器這里。再來看下typeTokenCache的定義:

  private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache
      = Collections.synchronizedMap(new HashMap<TypeToken<?>, TypeAdapter<?>>());

? 在早期的JDK版本中,使用線程安全的Map一般都是通過synchronizedMap這種方式,其實底層就是通過synchronized鎖實現的。synchronized是互斥鎖,也是重量級鎖,雖然目前得到很多優化,但是當高并發下,線程獲取不到鎖,會立馬進入BLOCKED狀態,這就是Dubbo線程池滿的原因。

? 解決方式如下:

? 在早期由于沒有提供JUI包,也就是ConcurrentHashMap,所以使用synchronizedMap這種方式實現高并發。從JDK1.7版本的ReentrantLock+Segment+HashEntry,到JDK1.8版本中synchronized+CAS+HashEntry+紅黑樹。相信新的Gson版本肯定會做相應的升級,于是查看Gson的2.8.5版本的源碼,果然升級了,源碼如下:

private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<TypeToken<?>, TypeAdapter<?>>();

? 升級Gson到2.8.5版本后,問題解決。

? 總結,線程池調優,主要關注線程的如下幾種狀態:

  • 死鎖, Deadlock(重點排查)
  • 執行中,Runnable
  • 等待資源, Waiting on condition(重點排查)
  • 等待獲取監視器, Waiting on monitor entry(重點排查)
  • 暫停,Suspended
  • 對象等待中,Object.wait() 或 TIMED_WAITING
  • 阻塞, Blocked(重點排查)
  • 停止,Parked

分享到:
標簽:線程 Dubbo
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定