各位同學,開發者學堂Java 圖譜中Java 進階工程師篇的課程“Java 虛拟機原理”的課程給開始更新了,第四課時“Dragonwell特性:多租戶”的幹貨總結來啦!一起學習新課程吧!
課程連結以及圖譜位址小編已經為大家指路了,搭配學習效果更佳👇
課程名稱:Dragonwell特性:多租戶
課程位址:
https://developer.aliyun.com/learning/course/56/detail/1065圖譜名稱:Alibaba Java 技術圖譜
圖譜位址:
https://developer.aliyun.com/graph/javaDragonwell特性:多租戶
1、JAVA語言的特點
JAVA語言的特點如下圖可以看到企業級性能好,穩定,生态豐富,JavaEE的标準非常好,後面還有跨平台的特性,按層次來看 Java平台,Java硬體上是arm或者x86或者PowerPC等等不同CPU,在此之上作業系統是如windows、Linux、Mac OS,再往上是JAVA platform,是一個平台,因為隻要根據 Java平台來寫應用,可以完全不管作業系統以及硬體的一些具體實作細節,跨平台性是Java的一個主要賣點,在此之上Java定義了 Java1g2e的标準,然後Tom Kate、APACHE等各種元件其實都是從JAVA EE的标準裡面衍生出來的,幫助Java很好的成長,按照 Java一開始設計的人目标去成長。
生态豐富的特點,因為Java上有Tom Kate、APACHE 、spring等各種生态,開箱即用,開發應用非常簡單;企業級性能好,Java它适合于運作一種大型、長期運作的程式,穩定性非常好,如運作一個Linux server加 JVM的一個組合,可能幾年都不用重新開機,可以跑得非常好;
2、一次編譯到處執行
一次編譯到處執行是Java的一個很大的賣點,通過一段代碼來了解在Java内是如何被加載和執行的,如在應用代碼裡面去調用 new Gson(). from Json(..);然後有一個new byte code會觸發loadClass()機制,還要去找”com.google.gson.Gson”用loadClass方法,去找Jar,因為應用的class 下有很多Jar包,如commons-io.jar、myaql-connector.jar、gson.jar,找到gson.jar裡面有com.google/gson/Gson.class檔案,然後會把 Class給讀出來,讀成一個byte的數組,調用一個define class JVM的接口,define class會進行parse、verify、link,調出,最終達到一個可以讓Jvm識别的 byte code,Jvm解釋器會去執行byte code到2000次以後,會運作一個client compiler讓代碼編譯到c1級别,c1級别其實已經在native執行了,同時會收集一些provide資訊,幫助編譯到更高的優化級别c2,然後到15,000次以後會進入到最快的c2級别,interpret和c2之間可能大概有50倍的差距,是以Java1開始是很慢的,但隻要跑穩後是非常快的。

通過上述,一段代碼想要被執行,生命周期是非常長的,優點是這種跨平台性,可以收集的資訊越跑越快,缺點就是Java代碼裝載的開銷非常大。
3、記憶體管理
Java的垃圾回收管理GC, heap就是Java裡面實際做管理的記憶體,是虛拟記憶體,一開始如設4Gheap,會想到作業系統,申請4G的heap,這些配置其實都沒有被申請出來,是按需配置設定的,這是作業系統的推薦機制,随着各種new Objiect,頁面就會被配置設定出來,如下圖所示分為9個頁面,就是RSS=9,中間如果發生garbage collection,即便會壓縮記憶體的,如這裡面有6個頁面是空閑的,他就把三個排到一起,然後剩餘的記憶體是空閑的,但是作業系統認為依然占着這些記憶體,然後它是不可用的,是以RSS依然很高,因為記憶體很有可能随着後面的配置設定馬上會被使用,Java也是積攢到一定程度來釋放的,是以很有可能占據很大的面積。
4、線程模型
用Java去寫server端應用的時有很多架構,如Tom Kate後面可能會有JPA、Hibernate ORM 、JDBC等元件是通過一個NIO接收請求,接收到請求以後是交到一個thread pool,thread pool多線程可能并不是一種特别高效的處理并發的模型,下圖可以看到一個g2e的規範,在thread的規範裡面,一個外部容器怎樣去處理并發的請求是通過在多線程裡面去并行的調用service函數來達到的,标準導緻這個事件必須通過線程池來提供并發能力。
線程多會導緻的問題,上圖是一張實際的執行圖,每一個豎條代表一個線程,每一個色塊代表一個請求,如在隻有一個核的機器上去啟動4個線程,其實作業系統提供能力,會覺得請求是并發并行來執行的,實際上都是交替的執行分時複用的,看起來是并發的,實際是交替來執行,這中間就有一個切換開銷是比較大的,是多線程的一個弊端。
5、雲原生vsJava
總結了Java的優勢,雲原生的應用應該是微服務的,但Java是一個企業級的模式都非常龐大;雲原生是低記憶體開銷,這樣可以創造很多微服務,把他們更快的合并更好的和部署,但Java是GC管理是大塊記憶體的;雲原生要求應用是快速傳遞,Java應用啟動慢,需要編譯預熱,中間是有一個抵觸的,
6、Dragonwell
所有的市面上的JDK産品大多都基于Open JDK, Open JDK加上 oracle的一些商業特性,然後形成的是oracle JDK,其它還有一些三方廠商,如說亞馬遜等都通過Open JDK進行了簡單的擴充,形成自己的JDK,阿裡雲也是通過Open JDK作為上遊擴充,然後加上阿裡雲的一些原生特性,最終形成了阿裡巴巴Dragonwell這個産品。
7、Dragonwell:Elastic Heap
阿裡雲自己的一些特性也會回歸社群,這裡介紹Dragonwell的幾個主要特性,第一個是彈性堆,就是可以把前面看到的一些那問題給解決掉,把記憶體還給作業系統;往下是程序級别,然後 Java應用級别,然後裡面有JavaHeap,Java heap裡面之間記憶體預設都是固定的,但是通過Elastic Heap機制,可能用不到這麼多記憶體就可以把應用跑得很好,會動态的去減少Heap大小,把記憶體實際還給作業系統。
下圖右半部為特性的使用場景,可能有一些線上的job,比如4個應用,平時使用者量很大,需要大量記憶體去應付很多請求,是以記憶體是不共享的,但是到晚上可能沒有很多使用者在通路線上應用了,就可以動态的把記憶體給釋放出來,然後提供給其他一些同級以上的離線服務,離線服務和線上服務可以捆綁,或者是複用記憶體,能達到一個很好的資源複用的目的。
8、Dragonwell:wisp
還有一個非常有用的特性叫做wisp協程,這個特性可以把Java的線程映射為協程,去提高Java的并發處理能力,因為目前都是微服務的狀态,微服務把應用拆掉之後,自然不同服務就要通信,通信的就會很多wisp提高這些io的效率。
現在 Java有很多異步程式設計架構,如 VERT.X這個詞的含義就是節點,跟node的jS在圖算法裡面其實是可以互相代替使用的,VERT.X和 node.js就是想制造一種Java裡的node,希望用node的這種異步程式設計模型得帶給Java。
下圖是Verte.x編寫一個資料庫的通路應用,用他官方的一個API:client.getConnection到這裡不是直接的傳回的connection,而是寫一個call back,因為這是一個組詞函數,異步的他就要寫call back,然後call back裡面去判斷請求是否成功,成功的話可以拿到result裡面一個connection,然後Connection去查一個SQL語句,比如“select*FROM...”,這裡同樣要寫一個call back result to,而不是說直接拿到 connection,一層層的回調,如果我們要繼續result再去經營什麼,比如說把它放到緩存裡面,那裡面又會進行一層嵌套的回調。
這樣代碼的控制就被反轉了,并且異常也看不到,如在某一層發生一個異常,因為都是從回調直接執行的,是看不到從哪調進來的,這是異步程式設計帶給我們一個問題,當然異步程式設計是有解決方法的。
C sharp和ES7所提供的新特性,主要是提供了協程機制,Kotlim程式作為例子,來解釋這種機制如何幫助去改變義務變成模型,在Kotlim裡面,如果想讓一段代碼可以被協程切換的話,可以用suspend标記這段代碼,然後可以對一個異步函數進行封裝,如client.getconnection,把它封裝成client.aGet connection,實際做調用了一個非方法叫suspendCoroutine做的是調用這一段代碼,并且把目前協程切走,會馬上調用 getconnection,并且得到一個continuation的回調,在 get connection的call back,如get connection實際完成的時候,會恢複協程馬上挂起,然後再完成恢複,這樣就可以讓代碼臨時挂起,過一段時間再回來執行,隻有協程可以帶給的優勢,整個執行站都是保留完整的,通過這種封裝可以這樣去寫代碼;Conn=clientaGetconnection,rs=connection=,aQuery同樣要進行包裝。
這樣可以達到異步的一個性能,同時使用完全阻塞方式去寫這個代碼,非常高效, C sharp的協程的一個解決方案,但是這裡對這些帶Kotlim的進行封裝,其實是非常繁瑣的。
9、Dragonwell:wisp原理
wisp其實就是把所有這些需要封裝注冊函數全部可以做到JDK,可以看到像 g.u.c等,其實都被wisp做了像上述的封裝,會切走協程,等到事件ready的時候再把這協程切回來,使用者不用關心。
以前阻塞的API是支援的完全不需要改代碼,可以把以前的用協程寫代碼直接切換到協程模型,進行一個模型轉換,這樣從java thread和Pthread就作業系統1:1的模型變到調用大量wisp變成少量操作統線程,性能大大提高。
10、Dragonwell:JWarmup
JWarmup特性,前面提到,Java方法要執行2000次,然後在15,000次才達到一個非常高的效率,這些執行其實是非常慢的,要比慢50倍,并且解釋執行的時候,其他編譯器其實也是比較少有資源的,就邊編解釋執行還要邊編譯這個方法。
執行的時候CPU會打得非常高,響應特别慢,JWarmu就是說讓JVM提前知道哪些方法熱的,在處理請求之前就讓這些方法提前被編譯掉,進而避免了前面邊解釋,邊編譯的開銷。
模型如圖所示,首先應用被在被他環境被跑的時候,class被加載的時候,會産生一些日志,告訴哪些class是熱的,然後這裡進行一個record,記了一個class list,然後把 class list就是真正熱的方法的一個logo檔案,給分發到線上環境,然後線上環境的機器就知道哪些方法熱的,在真正處理使用者請求之前,會根據清單去提前把方法給編譯好,JWarmup它可以大大減少應用預熱的一個開銷。