成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

性能優化那些事兒(三)

原創 精選
開發 開發工具
在討論完性能優化的方面和策略之后,這次我們的文章更偏向技術層面,來分享下如何開發一個自己的性能分析工具(基于JVM)。

接上文:

在討論完性能優化的方面和策略之后,這次我們的文章更偏向技術層面,來分享下如何開發一個自己的性能分析工具(基于JVM)。

『新』知識

考慮到咱們大多數還是開發業務為主,所以Java里面一些『鮮為人知』的API可能很多人都不知道,這里就簡單介紹一番,如果想深究的,就自己谷歌一下吧。

  • JVMTI(JVM Tool Interface)是 Java 虛擬機所提供的 native 編程接口,即底層的相關調試接口調用,我們熟知的Java調試其實也是基于它。
  • Instrumentation,雖然Java提供了JVMTI,但是對應的agent需要用C/C++開發,對Java開發者而言并不是非常友好。因此在Java SE 5的新特性中加入了Instrumentation機制。有了Instrumentation,開發者可以構建一個基于Java編寫的Agent來監控或者操作JVM了,比如替換或者修改某些類的定義等。

有了上面兩個知識,其實我們就可以開發一個簡單的Agent了,Instrumentation可以理解為JVM層面的AOP(Aspect Oriented Programming),通過應用啟動時掛載Agent,我們可以對每一個class字節碼進行查看和修改。

  • ASM ASM是一種通用Java字節碼操作和分析框架,它可以用于修改現有的class文件或動態生成class文件,結合Instrumentation我們可以做到掛載Agent的時候,對字節碼進行修改,加上我們需要的性能監控手段。ASM的學習是有難度的,需要對字節碼有所了解,但由于其性能優秀,被各種工具作為修改字節碼的首選,比如大家熟悉的Cglib。
  • Javassist 依舊是一個字節碼的修改工具,但對初學者更加友好,不需要過多了解字節碼層面,可以書寫Java語法片段對已有class字節進行修改,缺點是過于模板化,難以優化,并且功能有限。我們做性能分析工具,本身是要盡可能減少插入字節碼對現有代碼的影響,并且注入的速度也要盡可能快,所以一般都會選擇ASM作為首選項。

好了,介紹完Instrumentation和ASM,我們是不是就可以滿足制作性能分析工具的前提條件了呢?你看我們通過Instrumentation進行JVM層面的AOP,再通過ASM對JAVA的字節碼進行修改,就可以著手完成性能分析最重要的埋點環節了。

看起來沒有錯,但是誰也不希望我們增強修改過的代碼一直存在內存中,分析一次就對環境造成不可逆的破壞吧。Instrumentation可以通過addTransformer添加字節碼轉換器,也可以將字節碼恢復原樣(只需要removeTransformer再retransformClasses就可以恢復了),但javaAgent畢竟是個單獨的jar包,它也會有一些依賴,將其加載進來必然會引發新的Class加載甚至是Class的沖突。那么新的問題就出來了,javaAgent如何不對現有的類有影響呢?

ClassLoader 類加載器,我們可以采用一個新的類加載器,專門加載javaAgent里面的類庫,這樣就可以解決agent的類引發沖突的問題,在舊版本JDK中我們很難對ClassLoader做卸載,并且類的卸載是很麻煩的事情,限制很多,好在我們現在多數用的都是jdk1.8,只要遵循類卸載的規則,對ClassLoader進行清理還是很輕松的。

額外的類加載器實現了業務代碼和Agent代碼類的隔離,使它們可以安全引用包,并且可以對Agent的類進行卸載,但這樣同時引入了一個新的問題。類是隔離的,我在對業務代碼進行增強時,如何向agent代碼傳遞信息?增強的代碼一定是被加載在AppClassLoader里,如何與AgentClassLoader進行通訊呢?

BootStrapClassLoader 啟動類加載器,該ClassLoader是JVM在啟動時創建的,理解這一部分知識,就一定要理解ClassLoader的雙親委派機制。我們可以創建一個非常簡單的Spy類和一個SpyHandler接口,Spy類定義好一些靜態方法用于代碼增強時調用,而SpyHandler則是定義一些用于通訊傳參的接口。我們將這兩個類打成jar包,并通過Instrumentation的appendToBootstrapClassLoaderSearch接口,在agent加載時引入BootStrapClassLoader類中,這樣我們在各個ClassLoader中都能訪問Spy類和SpyHandler接口了。

通過上面的介紹,我們現在可以動手做一個自己的APM工具了,通過Instrumentation+ASM,我們可以實現Class文件的修改增強,甚至可以修改JDK自帶的類比如String,通過自定義的ClassLoader我們可以隔離Agent的類和業務的類,通過打入BootStrap的Spy,我們可以實現跨ClassLoader之間的通訊。

萬事俱備,我們現在可以開始動手實現一個自己的APM工具了吧!

打住,其實上面這些功能不需要自己一一實現,我們不需要重復制造輪子,來自阿里開源項目JVM-SANDBOX此時華麗登場。這個項目屏蔽了ASM難以使用的缺點,也簡化了Instrumentation打樁過程,并且實現了ClassLoader的隔離,也有了BootStrapClassLoader中的Spy類,我們在此框架的基礎上進行開發更為簡單。

原圖鏈接:https://github.com/alibaba/jvm-sandbox/wiki/img/jvm-sandbox-classloader.png

集『大』成

我們擁有了JVM-SANDBOX這一利器,似乎節約了我們很多的時間,我們現在終于可以著手性能分析了。

那么怎么進行性能分析呢?

  • Zipkin,開源的鏈路追蹤。
  • Jaeger,開源的鏈路追蹤支持Zipkin協議,個人感覺更為好用。

我們可以引入Zipkin或者Jaeger作為收集者和UI展現,根據自己的喜好選擇一個好用的開源工具。通過sandbox提供的功能,我們可以很方便編寫埋點代碼,將我們的鏈路追蹤工具集成到Agent里面,最終實現無侵入的定制化鏈路追蹤。

通過集成ZipkinClient或者JaegerClient我們可以進行埋點收集,我們似乎把一些功能以搭積木的方式組裝起來,解決了一個頗為復雜的實現,這就是開源的魅力所在。其實在實際的過程中我們還遇到了一些困難,比如如何追蹤異步調用,如何追蹤跨線程的調用,如何處理線程池,如何處理ForkJoin?

其中最為復雜的是如何處理那些跨線程的派發,我們如何將鏈路的上下文在多個線程中傳遞。JDK的InheritableThreadLocal類可以完成父線程到子線程的值傳遞。但對于使用線程池等會池化復用線程的執行組件的情況,線程由線程池創建好,并且線程是池化起來反復使用的;這時父子線程關系的ThreadLocal值傳遞已經沒有意義,應用需要的實際上是把 任務提交給線程池時的ThreadLocal值傳遞到任務執行時。

說起來可能不好理解,總得來說無論是ThreadLocal還是InheritableThreadLocal都無法處理線程池或者ForkJoin帶來的線程復用的副作用,即無法有效準確安全的傳遞鏈路的上下文,不信大家可以試一試。

那么怎么解決這個問題呢?沒錯,就是修改JDK源碼,讓線程池在進行調度的時候具有安全準確傳遞上下文信息的能力,比如對Runnable和Callable接口進行增強處理,讓其可以攜帶線程的上下文。如果要對JDK的代碼進行增強,我們需要非常熟悉線程調度、線程池、Forkjoin的源碼,還需要小心處理值的傳遞確保安全,聽起來就很危險,也很困難。不用擔心我們不是第一次遇到這種問題的人,我們再次搬來了阿里的開源產品TTL,這個庫解決的就是上面描述的問題。

但是找到開源產品也并不一定能解決所有的問題,transmittable-thread-local雖然能夠解決線程復用時傳值的問題,但是它的實現對JDK代碼進行了『過分』的修改,以至于Instrumentation不能進行動態增強,它需要在啟動時未加載到ClassLoader的時候對JDK的源碼進行增強,并不能對已加載的JDK源碼進行動態增強,也就是說這種增強只能發生在一開始,不能發生在中間時間,且不可卸載。

這是因為Instrumentation的redefineClasses這個方法存在限制:重定義不得添加、移除、重命名字段或方法;不得更改方法簽名、繼承關系(不然那些商業的熱重載技術怎么賺錢。。)。而TTL的增強違反了這個原則,我們需要對其修改,并集成到Agent中。這個改造比較無趣也不好解說,可以直接看改造后的JVM-SANDBOX,我們為了后續使用方便,將TTL庫直接用BootStrapClassLoader加載了進去。

開源

最終開源的性能分析工具可以在這里找到:https://github.com/tmtbe/PVisualization,配合改造后的JVM-SANDBOX,可以實現360度無死角的性能鏈路追蹤分析,開發埋點也非常便捷,也無需考慮任何線程池的問題。

原圖鏈接:https://github.com/tmtbe/PVisualization/raw/master/source/img.png

責任編輯:趙寧寧 來源: Thoughtworks洞見
相關推薦

2022-04-08 09:47:55

性能優化開發

2022-02-18 19:24:15

性能優化代碼

2022-06-20 05:40:25

數據庫MySQL查詢

2013-03-12 17:33:17

Linux系統性能調優

2021-06-02 08:33:31

TPCTPC-H系統

2018-09-26 06:50:19

2011-02-25 14:35:00

2022-02-08 17:39:04

MySQL服務器存儲

2013-12-26 14:23:03

定位系統GPS監測

2021-06-09 13:28:40

密碼安全身份認證數據安全

2022-02-09 17:08:57

卡頓App 流暢性用戶

2012-07-31 09:14:20

蘋果三星

2016-03-02 09:34:03

runtime消息ios開發

2017-05-18 16:30:29

Linux內存管理

2022-05-13 14:36:12

網絡犯罪網絡攻擊密碼

2012-03-12 13:55:22

交互設計

2017-08-21 17:00:55

2010-09-14 11:36:24

上網行為管理網絡安全網康科技

2022-05-23 08:34:08

微前端微服務開發

2022-10-08 00:02:00

CSS工具系統
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 二区三区视频 | 国产一区二区三区色淫影院 | 久久久久久久久久久91 | 91综合网| 天天爽夜夜爽精品视频婷婷 | 情侣酒店偷拍一区二区在线播放 | 国产在线高清 | 久久久久久免费看 | 亚洲一区二区三区免费在线 | 成人一区二区三区在线观看 | 精品视频在线一区 | 91传媒在线观看 | 国产精品久久久久久一区二区三区 | 日日草夜夜草 | 精品网| 久久合久久| 国产精品精品久久久久久 | 亚洲视频在线观看一区二区三区 | 波多野结衣先锋影音 | 亚洲免费一区二区 | 久久99精品久久久久久国产越南 | 日韩成人精品一区 | 超碰97免费在线 | 91资源在线 | 精品久久久精品 | 黄色国产大片 | 国产伦精品一区二区三区在线 | 久久精品国产一区二区电影 | 日韩国产中文字幕 | 成人高清视频在线观看 | 久草在线在线精品观看 | 97国产精品视频人人做人人爱 | 99综合在线| 国产精品1 | 日韩在线中文 | 欧美在线视频一区二区 | 日韩精品成人网 | 免费一级网站 | 亚洲精品一区中文字幕乱码 | 一区精品视频在线观看 | 国产精品久久久久久久久免费相片 |