天天看點

一文解讀業務平台更新JDK11的适配之路

作者:阿裡開發者
本文基于兩個出發點,描述了業務平台于21年12月啟動了對JDK版本更新的适配之路,并回顧了整個更新過程,對更新過程中的問題做了記錄。

作者 | 鄭波(岱澤)

來源 | 阿裡開發者公衆号

業務平台更新JDK11,基于兩個出發點:一、jdk8于2019年1月停止維護,springboot2.1之後的版本已經相容JDK11,springboot3.0完全放棄對JDK8的支援,未來屬于更高版本的JDK;二、在試點國産化晶片的過程中,由于JDK8對Arm架構的優化不足,導緻國産化晶片無法發揮自身的性能優勢,為了更好的适配國産化,務必要求對JDK版本進行更新。基于上述兩個出發點,業務平台于21年12月啟動了對JDK版本更新的适配之路。這裡回顧整個更新過程,對更新過程中的問題做一下記錄

一、更新版本的選擇

當時有兩個JDK版本可供選擇,JDK11、JDK17,從長遠開來,JDK17更代表未來,但由于JDK11 相比JDK17的變化并不大,相比之下從JDK11更新到JDK17的挑戰要相對小。由于更新的基本都是電商核心系統,基于風險的控制,從JDK8更新到JDK11,随後再從JDK11更新到JDK17是一個更合理的選擇。

二、GC選擇及功能适配

業務平台核心系統使用了非常多的定制化功能,比如GCIH、CMS GC、異步日志、Wisp、Jwarmup、UncommonNullCast、多租戶,為了減少對業務的影響,同時保障JDK11相比JDK8不會産生性能的退化,相關的特性均需要在JDK11上進行适配。同時為了避免GC算法的調整對業務運維及穩定性的影響,更新初期決定依舊使用CMS GC,僅灰階少量的G1

特性 特性說明
GCIH 營銷利用GCIH緩存營銷資料,大促強依賴的特性
CMS GC 核心業務使用的GC算法,為了避免對業務使用上的影響,需要保留Cms GC的支援
異步GC日志 GC日志異步化,降低業務的影響
Wisp 協程支援,buy2、carts2上均在使用,對業務的性能3-5%的性能優化
JWarmup 啟動預熱,核心系統利用該功能降低啟動過程中C1、C2帶來的CPU飙升,業務抖動問題

UncommonNullCast

-XX:CompileCommand=

退優化相關的優化參數,避免部分場景下退優化帶來的性能問題
-Dcom.alibaba.jdk.verifyECDSATrailing 跳過ECDSA尾部零校驗,相容老的ECDSA資料,Tp3和支付寶互動中,需要依賴

三、更新JDK11相關元件的更新

在更新JDK11的過程中,業務代碼的改造隻是其中之一,還涉及到業務依賴的各種元件之間的更新适配,包括Pandora、Tomcat、星環容器、天啟、Doom、天擎等測試工具的更新支援

元件 更新改造點
Tomcat

非Pandoraboot的應用,強依賴Tomcat,目前大部分業務使用的依舊是Tomcat7,但Tomcat7 本身對JDK11的支援存在問題(ECJ的版本過低,在存在動态編譯代碼的情況下,比如:jsp、模闆預演、groovy等,由于不識别jdk11,将目标代碼編譯成低版本的代碼,導緻性能及功能受損)。由于tomcat7 和tomcat8對jar包加載的順序有了調整,導緻更新到tomcat8成本會相對較高,為了降低改造成本,對tomcat7進行改造。(https://bz.apache.org/bugzilla/show_bug.cgi?id=57129)

最新的版本: taobao-tomcat-7.0.108.ecj

Pandora Pandora各元件對JDK11的版本支援,在項目啟動之初,Pandora已經在對JDK11進行了适配,但在實際更新使用中,依舊發生了一些不相容的問題,期間主要有
  • 服務端使用JDK11版本運作,用戶端使用JDK8的場景下,服務端抛的異常經過Hession序列化後,無法在JDK8上進行反序列化的情況。該問題前期評估,主要是用戶端感覺的錯誤發生變化,風險可控,實際在上線過程中,消費者側的感覺發生變化。
最新的版本: 2022-07-stable
天啟 天啟作為業務平台最核心的測試用力回歸工具,在整個适配開始之初,就作為高優先級适配,天啟内部使用了很多序列化及記錄Record的過程,本身為了做代碼增強,使用了相對較多的hack的方式,是以這部分改造及适配成本最大,适配過程中,一方面需要調整doom的依賴,另外一方面需要保障測試用力能正常回歸
天擎 天擎作為業務平台預發環境隔離的工具,預發回歸測試均需要進行依賴。這部分的改造也需要提前進行适配。

四、灰階及上線流程的選擇

業務平台核心應用很多都是伴随taobao業務成長起來的應用,具有曆史代碼多、依賴元件廣的特點,核心系統中存在非常多的二三方包依賴,在更新之初考慮使用JDK提供的相容性掃描工具進行分析,但在實操過程中,掃描到的不相容代碼過多,但實際上大部分并沒有使用到的情況。如果按照掃描出來的結果推動相關二三方包的适配,整個工程量是完全無法評估的,整個更新節奏也無法把控。為了解決該問題,我們決定整體的更新節奏調整并不追求完全的代碼相容。隻對實際影響業務運作的代碼做相容處理。因為整體的更新節奏也就變成了如下幾步

  1. 1) 代碼使用JDK8進行編譯,但要求代碼可以同時在JDK8及JDK11上運作
  2. 2) 上線過程中,先将日常及預發環境的版本切換成JDK11和JDK8同時運作,回歸測試過程中同時測試JDK11、JDK8版本下的運作情況
  3. 3) 線上逐漸灰階JDK11運作環境的功能,做好監控及線上排查定位。随着幾次大促下來後,逐漸将所有的容器切換到JDK11,下線JDK8環境的容器。
  4. 4) 利用運作态的JDK11特性,優化系統性能
  5. 5) 将編譯從JDK8切換到JDK11 ,同時充分JDK11本身的新的特性。
  6. 基于上述的更新步驟,對業務代碼的更新改造也做了調整,業務在使用過程中,同時安裝JDK8和JDK11,業務利用腳本的方式控制線上的JDK11及JDK8的灰階比例。同時經過多輪大促: 38大促灰階10台容器、日常灰階100台、618灰階一個單元、99大促灰階所有機房
if [ -f /home/admin/logs/jdk11.enable ]; then
    export JAVA_HOME=/opt/taobao/install/ajdk11_11.0.14.13/
    export JDK11_ENABLE=true
    echo "enable jdk11 , use new JAVA_HOME : ${JAVA_HOME}"
fi


if [ "$JDK11_ENABLE" == "true" ]; then
    CATALINA_OPTS="${CATALINA_OPTS} -Xlog:gc*:${MIDDLEWARE_LOGS}/gc.log:time"
    CATALINA_OPTS="${CATALINA_OPTS} --add-exports=java.base/jdk.internal.loader=ALL-UNNAMED --add-exports=java.base/jdk.internal.loader=jdk.unsupported --patch-module jdk.unsupported=/home/admin/buy2/bin/java9-migration-helper-0.1.jar"
    CATALINA_OPTS="${CATALINA_OPTS} -Dio.netty.tryReflectionSetAccessible=true --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED"
    CATALINA_OPTS="${CATALINA_OPTS} --add-exports=java.base/jdk.internal.util.jar=ALL-UNNAMED --add-exports=java.base/jdk.internal.util.jar=jdk.unsupported"
    CATALINA_OPTS="${CATALINA_OPTS} --add-opens=java.base/com.alibaba.wisp.engine=ALL-UNNAMED"
    CATALINA_OPTS="${CATALINA_OPTS} -XX:CompileCommand=stableif,*::*"
    test -z "$JPDA_ADDRESS" && export JPDA_ADDRESS=*:8000
    #gson相容
    CATALINA_OPTS="${CATALINA_OPTS} -Djava.locale.providers=COMPAT,SPI"
else
    CATALINA_OPTS="${CATALINA_OPTS} -Xloggc:${MIDDLEWARE_LOGS}/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
    CATALINA_OPTS="${CATALINA_OPTS} -XX:-UncommonNullCast -XX:CompileCommand=stableif,*::*"
    test -z "$JPDA_ADDRESS" && export JPDA_ADDRESS=8000
fi           

五、二三方包适配及改造

JDK11相比JDK8之間的關鍵的變化

參考:Oracle JDK Migration Guide

● 版本号格式的變化

● 本地化的優先級變化

● module化

● 廢棄代碼清理

● JDK日志架構變化

由于業務代碼中舊的代碼量較多,為了減少整個更新的複雜度,整體的更新政策,以相容舊的代碼邏輯為主,盡可能的更新到新的版本中(并不是使用jdk11的最佳實踐進行直接更新)。

在實際的适配過程中,發現主要的相容問題集中在版本号格式的變化帶來的不相容。對于這部分代碼邏輯主要要求相關業務進行改進即可,對于一些無法找到維護者的二方包來說,直接通過反編譯的方式進行整體改造。

二方包 相容版本 改造原因
citrus-webx-all-in-one 3.2.4.1-jdk11 JDK11版本号格式變化,導緻無法啟動,由于目前已經無法找到對應維護者,針對這部分二方包,反編譯後送出倉庫供業務使用。
toolkit-webx-all-in-one 2.0.3-jdk11

toolkit.common.lang

com.alibaba.toolkit:toolkit-common-lang:jar

1.0-jdk11
citrus-webx-all-in-one 3.2.4.1-jdk11
forest-store 8.1.11 使用了非公開的類,在更新到jdk11後,相關的類發生了變化,需要做響應的改造更新
ip-client 5.5.69
sic-client 1.5.33
com.alibaba.ultron:common-sdk-datasource:1.0.0-buy2.0-4 1.0.0-jdk11-beta.2
common-uic-common 3.8.8-jdk11 +

com.cainiao.cdc:cdc-client

com.cainiao.cdc:cdc-common

1.13.25 使用了unsafe的包,導緻在更新到JDK11後,相關的類無法使用
gson 2.8.9 由于JDK11的本地化變化,導緻gson在解析時間格式上存在不相容的情況,更新gson版本,同時在啟動時添加 -Djava.locale.providers=COMPAT,CLDR 參數。https://github.com/google/gson/pull/1211

點選檢視原文,擷取更多福利!

https://developer.aliyun.com/article/1162353?utm_content=g_1000368533

版權聲明:本文内容由阿裡雲實名注冊使用者自發貢獻,版權歸原作者所有,阿裡雲開發者社群不擁有其著作權,亦不承擔相應法律責任。具體規則請檢視《阿裡雲開發者社群使用者服務協定》和《阿裡雲開發者社群知識産權保護指引》。如果您發現本社群中有涉嫌抄襲的内容,填寫侵權投訴表單進行舉報,一經查實,本社群将立刻删除涉嫌侵權内容。

繼續閱讀