在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Java與云原生的矛盾原因

jf_ro2CN3Fa ? 來源:芋道源碼 ? 作者:芋道源碼 ? 2022-10-31 11:15 ? 次閱讀

0. 前言

前陣子在 B 站刷到了周志明博士的視頻,主題是云原生時代下 Java,主要內容是云原生時代下的挑戰與 Java 社區的對策。這個視頻我在兩年前看到過,當時也是印象深刻。現在筆者也是想和大家一起看看相關項目的推進以及一些細節。這篇筆記會大量參考視頻中提到的內容,如果讀者看過相關視頻,可以跳過這篇筆記。

視頻分享中提到,Java 與云原生的矛盾大概原因有二:

首當其沖的是 Java 的“一次編寫,到處運行”(Write Once, Run Anywhere) 。在當年是非常好的做法,直接開啟了許多托管語言的興盛期。但云原生時代大家會選擇以隔離的方式,通過容器實現的不可變基礎設施去解決。雖然容器的“一次構建,到處運行”(Build Once, Run Anywhere)和 Java 的“一次編寫,到處運行”(Write Once, Run Anywhere)并不是一個 Level 的——容器只能提供環境兼容性和有局限的平臺無關性(指系統內核功能以上的 ABI 兼容),但服務端的應用都跑在 Linux 上,所以對于業務來說也無傷大雅。

其二,則是 Java 總體上是面向長時間的“巨塔式”服務端應用而設計的

靜態類型動態鏈接的語言結構,利于多人協作開發,讓軟件觸及更大規模;

即時編譯器、性能制導優化、垃圾收集子系統等 Java 最具代表性的技術特征,都是為了便于長時間運行的程序能享受到硬件規模發展的紅利。

但在,微服務時代是提倡服務圍繞業務能力(不同的語言適合不同的業務場景)而非技術來構建應用,不再追求實現上的一致。一個系統由不同語言、不同技術框架所實現的服務來組成是完全合理的。

服務化拆分后,很可能單個微服務不再需要再面對數十、數百 GB 乃至 TB 的內存。有了高可用的服務集群,也無須追求單個服務要 7×24 小時不可間斷地運行,它們隨時可以中斷和更新。不僅如此,微服務對鏡像體積、內存消耗、啟動速度,以及達到最高性能的時間等方面提出了新的要求。這兩年的網紅概念 Serverless(以及衍生出來的 Faas) 也進一步增加這些因素的考慮權重。

而這些卻正好都是 Java 的弱項:哪怕再小的 Java 程序也要帶著厚重的 Rumtime(Vm 和 StandLibrary)——基于 Java 虛擬機的執行機制,使得任何 Java 的程序都會有固定的內存開銷與啟動時間,而且 Java 生態中廣泛采用的依賴注入進一步將啟動時間拉長,使得容器的冷啟動時間很難縮短。

舉兩個例子。

軟件工業中已經出現過不止一起因 Java 這些弱點而導致失敗的案例。如 JRuby 編寫的 Logstash,原本是同時承擔部署在節點上的收集端(Shipper)和專門轉換處理的服務端(Master)的職責,后來因為資源占用的原因,被 Elstaic.co 用 Golang 的 Filebeat 代替了 Shipper 部分的職能。

又如 Scala 語言編寫的邊車代理 Linkerd,作為服務網格概念的提出者,卻最終被 Envoy 所取代,其主要弱點之一也是由于 Java 虛擬機的資源消耗所帶來的劣勢。

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

1. 變革之火

1.1 Complie Native Code

顯然,如果將字節碼直接編譯成可以脫離 Java 虛擬機的原生代碼則可以解決所有問題。

如果真的能夠生成脫離 Java 虛擬機運行的原生程序,將意味著啟動時間長的問題能夠徹底解決,因為此時已經不存在初始化虛擬機和類加載的過程。也意味著程序馬上就能達到最佳的性能,因為此時已經不存在即時編譯器運行時編譯,所有代碼都是在編譯期編譯和優化好的。同理,厚重的 Runtime 也不會出現在鏡像中。

Java 并非沒有嘗試走過這條路。

從 GCJ 到 Excelsior JET 再到 GraalVM 中的 SubstrateVM 模塊再到 2020 年中期建立的 Leyden 項目,都在朝著提前編譯(Ahead-of-Time Compilation,AOT)生成原生程序這個目標邁進。Java 支持提前編譯最大的困難在于它是一門動態鏈接的語言,它假設程序的代碼空間是開放的(Open World),允許在程序的任何時候通過類加載器去加載新的類,作為程序的一部分運行。要進行提前編譯,就必須放棄這部分動態性,假設程序的代碼空間是封閉的(Closed World),所有要運行的代碼都必須在編譯期全部可知。

這一點不僅僅影響到了類加載器的正常運作。除了無法再動態加載外,反射(通過反射可以調用在編譯期不可知的方法)、動態代理、字節碼生成庫(如 CGLib)等一切會運行時產生新代碼的功能都不再可用——如果將這些基礎能力直接抽離掉,Hello world 還是能跑起來,大部分的生產力工具都跑不起來,整個 Java 生態中絕大多數上層建筑都會轟然崩塌。

隨便列兩個 Case:Flink 的 SQL API 會解析 SQL 并生成執行計劃。這個時候會通過 JavaCC 動態生成類加載到代碼空間中去;Spring 也有類似的情況,當 AOP 通過動態代理的方式去生成相關邏輯時,本質還是在 Runtime 時生成代碼并加載進去。

要獲得有實用價值的提前編譯能力,只有依靠提前編譯器、組件類庫和開發者三方一起協同才可能辦到——可以參考 Quarkus。

Quarkus 和我們上述的方法如出一轍,以 Dependency Inject 為例:所有要運行的代碼都必須在編譯期全部可知,在編譯期就推導出來相關的 Bean,最后交給 GraalVM 來運行。

1.2 Memory Access Efficiency Improvement

Java 即時編譯器的優化效果拔群,但是由于 Java “一切皆為對象”的前提假設,導致它在處理一系列不同類型的小對象時,內存訪問性能很差。這點是 Java 在游戲、圖形處理等領域一直難有建樹的重要制約因素,也是 Java 建立 Valhalla 項目的目標初衷。

這里舉個例子來說明此問題,如果我想描述空間里面若干條線段的集合,在 Java 中定義的代碼會是這樣的:

publicrecordPoint(floatx,floaty,floatz){}
publicrecordLine(Pointstart,Pointend){}
Line[]lines;

面向對象的內存布局中,對象標識符(Object Identity)存在的目的是為了允許在不暴露對象結構的前提下,依然可以引用其屬性與行為,這是面向對象編程中多態性的基礎。在 Java 中堆內存分配和回收、空值判斷、引用比較、同步鎖等一系列功能都會涉及到對象標識符,內存訪問也是依靠對象標識符來進行鏈式處理的,譬如上面代碼中的“若干條線段的集合”,在堆內存中將構成如下圖的引用關系:

9b7d204c-583d-11ed-a3b6-dac502259ad0.jpg

計算機硬件經過 25 年的發展,內存與處理器雖然都在進步,但是內存延遲與處理器執行性能之間的馮諾依曼瓶頸(Von Neumann Bottleneck)不僅沒有縮減,反而還在持續加大,“RAM Is the New Disk”已經從嘲諷梗逐漸成為了現實。

一次內存訪問(將主內存數據調入處理器 Cache)大約需要耗費數百個時鐘周期,而大部分簡單指令的執行只需要一個時鐘周期而已。因此,在程序執行性能這個問題上,如果編譯器能減少一次內存訪問,可能比優化掉幾十、幾百條其他指令都來得更有效果。

額外知識:馮諾依曼瓶頸 不同處理器(現代處理器都集成了內存管理器,以前是在北橋芯片中)的內存延遲大概是 40-80 納秒(ns,十億分之一秒),而根據不同的時鐘頻率,一個時鐘周期大概在 0.2-0.4 納秒之間,如此短暫的時間內,即使真空中傳播的光,也僅僅能夠行進 10 厘米左右。

數據存儲與處理器執行的速度矛盾 是馮諾依曼架構的主要局限性之一,1977 年的圖靈獎得主 John Backus 提出了“馮諾依曼瓶頸”這個概念,專門用來描述這種局限性。

Java 編譯器的確在努力減少內存訪問,從 JDK 6 起,HotSpot 的即時編譯器就嘗試通過逃逸分析來做標量替換(Scalar Replacement)和棧上分配(Stack Allocations)優化。基本原理是,如果能通過分析得知一個對象不會傳遞到方法之外,那就不需要真實地在對象中創建完整的對象布局。完全可以繞過對象標識符,將它拆散為基本的原生數據類型來創建,甚至是直接在棧內存中分配空間(HotSpot 并沒有這樣做),方法執行完畢后隨著棧幀一起銷毀掉。

不過,逃逸分析是一種過程間優化(Interprocedural Optimization),非常耗時,也很難處理那些理論上有可能但實際不存在的情況。這意味著它是 Runtime 時發生的 。而相同的問題在 C、C++ 中卻并不存在,上面場景中,程序員只要將 Point 和 Line 都定義為 struct 即可,C# 中也有 struct,是依靠 .NET 的值類型(Value Type)來實現的。這些語言在編譯期就解決了這些問題。

而 Valhalla 的目標就是提供類似的值類型支持,提供一個新的關鍵字(inline),讓用戶可以在不需要向方法外部暴露對象、不需要多態性支持、不需要將對象用作同步鎖的場合中,將類標識為值類型。此時編譯器就能夠繞過對象標識符,以平坦的、緊湊的方式去為對象分配內存。

Valhalla 目前還處于 Preview 階段。可以在這里看到推進的情況。希望能在下個 LTS 版本正式用上它吧。

1.3 Coroutine

Java 語言抽象出來隱藏了各種操作系統線程差異性的統一線程接口,這曾經是它區別于其他編程語言的一大優勢。不過,這也是曾經。

Java 目前主流的線程模型是直接映射到操作系統內核上的 1:1 模型,這對于計算密集型任務這很合適,既不用自己去做調度,也利于一條線程跑滿整個處理器核心。但對于 I/O 密集型任務,譬如訪問磁盤、訪問數據庫占主要時間的任務,這種模型就顯得成本高昂,主要在于內存消耗和上下文切換上。

舉個例子。64 位 Linux 上 HotSpot 的線程棧容量默認是 1MB,線程的內核元數據(Kernel Metadata)還要額外消耗 2-16KB 內存,所以單個虛擬機的最大線程數量一般只會設置到 200 至 400 條,當程序員把數以百萬計的請求往線程池里面灌時,系統即便能處理得過來,其中的切換損耗也相當可觀。

Loom 項目的目標是讓 Java 支持額外 的 N:M 線程模型,而不是像當年從綠色線程過渡到內核線程那樣的直接替換,也不是像 Solaris 平臺的 HotSpot 虛擬機那樣通過參數讓用戶二選其一。

Loom 要做的是一種有棧協程(Stackful Coroutine),多條虛擬線程可以映射到同一條物理線程之中,在用戶空間中自行調度,每條虛擬線程的棧容量也可由用戶自行決定。

此外,還有兩個重點:

盡量兼容所有原接口。這意味著原來所有的線程接口都可以當作協程使用。但我覺得挺難的——假如里面的代碼調到 Native 方法,這個 Stack 就和這個線程綁定了,畢竟 Coroutine 是個用戶態的東西。

支持結構化并發:簡單來說就是異步的代碼寫起來像同步的代碼,這點 GO 做的很好。畢竟嵌套的回調函數著實讓人痛苦。

上述的內容如果拆開來細說,基本就是:

協程的調度;

協程的同步、互斥與通訊;

協程的系統調用包裝,尤其是網絡 IO 請求的包裝;

協程堆棧的自適應。

小知識:每個協程,都有一個自己專享的協程棧。這種需要一個輔助的棧來運行協程的機制,叫做 Stackful Coroutine;而在主棧上運行協程的機制,叫做 Stackless Coroutine。

Stackless Coroutine意味著:

運行時:活動記錄放在主線程的棧上

暫停時:堆中保留活動記錄

可以調用其他函數

只能在頂層暫停運行,不可以在子函數/子協程里暫停

而Stackfull Coroutine意味著:

運行時:單獨的運行棧

可以在調用棧的任何一級暫停

生命周期可以超過它的創建者

可以從一線程上跑到另一個線程上

因此,一個完備的協程庫基本頂得上一個操作系統里的進程部分了。只是它在用戶態,進程在內核態。

這個項目可以在這里看到。目測 JDK 19 就可以嘗嘗鮮了。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://gitee.com/zhijiantianya/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

2. 小結

目前在云原生領域,Java 可能未必是好的選擇——在這個領域最讓人難以忍受的就是其龐大的 Runtime 以及較長的 Startup 時間,在以前這是 Java 優點的來源,但到了云原生時代,則成了 Java 顯而易見弱點。因此 Java 想在云原生時代繼續保持前幾十年的趨勢,解決這個問題迫在眉睫。從這個點來看,我很看好 Quarkus。

Valhalla 帶來的優化很多場景都可以用上,一些長時間運行應用也可以獲得更多的性能收益。

而協程針對的是 IO 密集型場景,本身也可以通過 NIO、AIO 方式來避免線程的大量消耗。因此 Loom 在筆者看來更像是錦上添花的事。

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    19

    文章

    2973

    瀏覽量

    104896
  • 容器
    +關注

    關注

    0

    文章

    496

    瀏覽量

    22085
  • 編譯器
    +關注

    關注

    1

    文章

    1637

    瀏覽量

    49191
  • 云原生
    +關注

    關注

    0

    文章

    250

    瀏覽量

    7958

原文標題:追隨云原生的 Java

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    進擊的 Java云原生時代的蛻變

    導讀:云原生時代的來臨,與Java 開發者到底有什么聯系?有人說,云原生壓根不是為了 Java存在的。然而,本文的作者卻認為云原生時代,
    發表于 09-17 15:54

    只需 6 步,你就可以搭建一個云原生操作系統原型

    編者按: 過去的三年對基礎軟件領域來說是不平凡的三年,是波濤洶涌的三年。隨著國際形勢和行業格局的變化,大家一定充分感受到了云原生和操作系統這兩個話題的熱度。那么當云原生和操作系統這兩個熱點話題相遇
    發表于 09-15 14:01

    華為云發布云原生基礎設施,云原生2.0時代正式開啟

    早在2010年,Paul Fremantle在一篇博客文章中首次提到了Cloud Native(云原生)。當時的云原生特指適合云計算模式的應用程序編寫方式。可能Paul Fremantle也不會想到,十年過去了,云原生會引領IT
    的頭像 發表于 09-30 11:25 ?2283次閱讀

    云原生應用中的“云”指的是什么?

    云原生應用是獨立的小規模松散耦合服務的集合,旨在提供備受認可的業務價值,例如快速融合用戶反饋以實現持續改進。簡而言之,通過云原生應用開發,您可以加速構建新應用,優化現有應用并在云原生架構中集成。其
    的頭像 發表于 11-27 17:24 ?2228次閱讀

    華為云正式提出云原生2.0的概念

    華為云發布云原生產業白皮書,并提出云原生2.0的概念。
    的頭像 發表于 12-07 11:51 ?3764次閱讀

    云原生時代的Java,仍在受歡迎嗎

    Java 誕生距今已有 25 年,但它仍然長期占據著“天下第一”編程語言的寶座。只是其統治地位并非堅不可摧,反倒可以說是危機四伏。云原生時代,Java 技術體系的許多前提假設都受到了挑戰,目前已經有
    的頭像 發表于 12-07 14:35 ?1385次閱讀

    引領云原生2.0時代,賦能新云原生企業

    十年云計算浪潮下,DevOps、容器、微服務等技術飛速發展,云原生成為潮流。Forrester首席分析師戴鯤表示,云原生是企業數字化轉型的基礎,企業需要建立云原生優先的戰略,構建一體化全棧云原
    的頭像 發表于 12-11 16:04 ?1841次閱讀

    云原生2.0時代 我們還要做什么?

    華為云自2015年以創始會員的身份參與了云原生計算基金會的組建,在過去的這5年時間里,華為云全面見證了云原生技術和產業的興起和發展:開源項目能力的完善期、云原生產業的發展與融合期,再到如今,
    的頭像 發表于 12-21 13:36 ?1841次閱讀

    如何更好地構建云原生應用生態,推動業界更好地落地云原生

    ? 近年來,“云原生”成為炙手可熱的概念,云原生技術在制造、政務、電信、金融等垂直行業的應用占比也在快速攀升,有力地支撐了業務系統重構,越來越多的企業和開發者開始把業務與技術向云原生演進。 ? 中國
    的頭像 發表于 12-24 11:13 ?2636次閱讀

    解讀騰訊云原生 鵝廠云原生的“新路”與“歷承”

    在云計算產業中,云原生是一個長期討論的“老話題”。而在今年新基建、產業數字化的宏觀背景下,云原生的應用主體開始擴張,關于這條技術路徑的討論也重新火熱了起來。 云原生突然“翻紅”的原因
    的頭像 發表于 12-28 18:10 ?3519次閱讀

    華為云中什么是云原生服務中心

    云原生服務中心(Operator Service Center,OSC)是面向服務提供商和服務使用者的云原生服務生命周期治理平臺,提供大量的云原生服務,并使用自研部署引擎,支持所有服務包統一管理
    發表于 07-27 15:44 ?711次閱讀
    華為云中什么是<b class='flag-5'>云原生</b>服務中心

    什么是分布式云原生

    什么是分布式云原生 華為云分布式云原生服務(Ubiquitous Cloud Native Service, UCS)是業界首個分布式云原生產品,為企業提供云原生業務部署、管理、應用生
    發表于 07-27 15:52 ?1589次閱讀

    云原生和非云原生哪個好?六大區別詳細對比

    云原生和非云原生各有優劣,具體選擇取決于應用場景。云原生利用云計算的優勢,通過微服務、容器化和自動化運維等技術,提高了應用的可擴展性、更新速度和成本效益。非云原生則可能更適合對延遲敏感
    的頭像 發表于 09-13 09:53 ?439次閱讀

    什么是云原生MLOps平臺

    云原生MLOps平臺,是指利用云計算的基礎設施和開發工具,來構建、部署和管理機器學習模型的全生命周期的平臺。以下,是對云原生MLOps平臺的介紹,由AI部落小編整理。
    的頭像 發表于 12-12 13:13 ?134次閱讀

    云原生LLMOps平臺作用

    云原生LLMOps平臺是一種基于云計算基礎設施和開發工具,專門用于構建、部署和管理大型語言模型(LLM)全生命周期的平臺。以下,是對云原生LLMOps平臺作用的梳理,由AI部落小編整理。
    的頭像 發表于 01-06 10:21 ?68次閱讀
    主站蜘蛛池模板: 亚洲丁香网| 亚洲你懂得| 9999毛片免费看| 欧美色婷婷天堂网站| 午夜性福利| 狠狠色狠狠干| rrr523亚洲国产片| 国产成人综合自拍| 99插插| 激情五月综合| 欧美高清老少配性啪啪| 久久天天干| 欧美三级午夜伦理片| 免费大片av手机看片| 欧美一级免费| 永久免费人成网ww555kkk手机| 97精品伊人久久大香线蕉| 男人和女人在床做黄的网站| 国产传媒在线观看视频免费观看| 99福利| 欧美成人自拍视频| 性欧洲女人18| 四虎官网| 四虎www成人影院免费观看| 日本天堂影院| 日本亚洲欧美美色| 激情网婷婷| 午夜88| 手机看片国产精品| 色综合久久98天天综合| 人人玩人人干| 欧美网站黄| 一区二区三区精品视频| 日本加勒比黑人| 欧美人与牲动交xxxx| 在线免费日韩| 亚洲成人在线网站| 四虎永久地址4hu紧急入口| 三级免费黄色片| 国产精品久久久久网站| 欧美一级特黄高清免费|