99精品久久精品一区二区-亚洲熟妇无码?v在线播放-日本国产精品无码字幕在线观看-久久久亚洲永夜AV-亚洲一级无码一区二区一-免费国产成高清人在线视频-中文字幕乱码免费观看-国产毛片精品妇女久久久

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

目標(biāo)驅(qū)動(dòng)Java Agent開(kāi)發(fā)實(shí)戰(zhàn):不修改代碼實(shí)現(xiàn)方法耗時(shí)監(jiān)控

目標(biāo)驅(qū)動(dòng)Java Agent開(kāi)發(fā)實(shí)戰(zhàn):不修改代碼實(shí)現(xiàn)方法耗時(shí)監(jiān)控 在業(yè)務(wù)系統(tǒng)里做性能診斷、故障排查、方法鏈路觀測(cè)時(shí)很多人第一反應(yīng)是改代碼加日志或者引入一個(gè)重量級(jí) APM。但遇到線上不能隨意發(fā)布、依賴不好升級(jí)、框架源碼不好改的場(chǎng)景Java Agent 幾乎是繞不開(kāi)的方案。Java Agent 可以做到不修改業(yè)務(wù)源碼就在類加載階段對(duì)目標(biāo)類進(jìn)行增強(qiáng)也正因如此很多團(tuán)隊(duì)都想做一個(gè)屬于自己的輕量 Agent 工具。不過(guò)絕大多數(shù)人剛接觸 Java Agent 時(shí)都會(huì)卡在字節(jié)碼操作、Instrumentation 機(jī)制、類加載器邊界這些問(wèn)題上寫出來(lái)的 Agent 經(jīng)常出現(xiàn)“不生效”“重復(fù)增強(qiáng)”“把應(yīng)用改崩了”之類的詭異現(xiàn)象。本文將圍繞 embabel 這類目標(biāo)驅(qū)動(dòng)的 Java Agent 開(kāi)發(fā)框架展開(kāi)先解釋 Java Agent 與目標(biāo)驅(qū)動(dòng)開(kāi)發(fā)的核心概念再通過(guò)一個(gè)可運(yùn)行的方法耗時(shí)監(jiān)控 Agent 實(shí)戰(zhàn)案例完整演示從工程搭建、目標(biāo)聲明、增強(qiáng)邏輯到運(yùn)行驗(yàn)證的全過(guò)程。文章還會(huì)整理高頻故障的排查思路和生產(chǎn)環(huán)境落地的注意事項(xiàng)。適合剛接觸 Java Agent 的讀者入門也適合正在設(shè)計(jì)內(nèi)部診斷組件的后端同學(xué)參考。1. 為什么 Java Agent 開(kāi)發(fā)如此繁瑣1.1 傳統(tǒng) Agent 開(kāi)發(fā)的“三座大山”如果一個(gè)團(tuán)隊(duì)打算自研一個(gè) Java Agent最常遇到的阻礙通常有三個(gè)。第一是字節(jié)碼操作門檻。JVM 加載類時(shí)ClassFileTransformer 會(huì)收到類的字節(jié)碼數(shù)組開(kāi)發(fā)者需要在這個(gè)數(shù)組上操作增加方法計(jì)時(shí)、打印入?yún)?、吞掉異常等邏輯。直接操作字?jié)碼不現(xiàn)實(shí)常用 ASM 或 ByteBuddy 這類庫(kù)來(lái)做。ASM 更底層性能好但代碼寫起來(lái)很繁瑣ByteBuddy 封裝程度高但對(duì)新手來(lái)說(shuō) API 依然有學(xué)習(xí)成本。第二是 Instrumentation 機(jī)制細(xì)節(jié)。Java 提供 premain 和 agentmain 兩種入口分別用于啟動(dòng)時(shí)增強(qiáng)和運(yùn)行時(shí) Attach 增強(qiáng)。要做運(yùn)行時(shí)增強(qiáng)還需要正確處理 retransform/redefine 的時(shí)機(jī)以及不同 JVM 版本對(duì) Can-Redefine-Classes、Can-Retransform-Classes 的限制。第三是類加載器邊界。同一個(gè)類可能被多個(gè) ClassLoader 加載Agent 中的增強(qiáng)類可能對(duì)目標(biāo)類的 ClassLoader 不可見(jiàn)一旦邊界處理不對(duì)要么增強(qiáng)不生效要么直接拋 NoClassDefFoundError。1.2 傳統(tǒng)方式寫一個(gè)方法耗時(shí)統(tǒng)計(jì)有多麻煩先看一個(gè)傳統(tǒng) ByteBuddy 方式的方法耗時(shí)統(tǒng)計(jì)樣例。雖然 ByteBuddy 已經(jīng)幫我們屏蔽了大量字節(jié)碼細(xì)節(jié)但開(kāi)發(fā)者仍然需要理解 AgentBuilder、Transformer、Advice 這些概念public class CostAgent { public static void premain(String arg, Instrumentation inst) { new AgentBuilder.Default() .type(ElementMatchers.nameStartsWith(com.example)) .transform((builder, typeDescription, classLoader, module, protectionDomain) - builder.visit(Advice.to(CostAdvice.class) .on(ElementMatchers.named(hello)))) .installOn(inst); } }這段代碼還不算復(fù)雜。真正復(fù)雜的是當(dāng)目標(biāo)類變成幾十個(gè)、方法變成幾百個(gè)、每個(gè)增強(qiáng)動(dòng)作還不太一樣時(shí)開(kāi)發(fā)者就不得不維護(hù)一堆類型匹配規(guī)則、方法匹配規(guī)則、Advice 類映射關(guān)系。可讀性和可維護(hù)性都會(huì)明顯下降。1.3 目標(biāo)驅(qū)動(dòng)換一種思考方式目標(biāo)驅(qū)動(dòng)開(kāi)發(fā)的核心思路是開(kāi)發(fā)者不再面向“字節(jié)碼增強(qiáng)規(guī)則”編程而是面向“我要增強(qiáng)誰(shuí)、增強(qiáng)后做什么”編程。開(kāi)發(fā)者只需要聲明目標(biāo)類、目標(biāo)方法、增強(qiáng)動(dòng)作框架負(fù)責(zé)把聲明翻譯成底層 Instrumentation 和字節(jié)碼增強(qiáng)邏輯。這個(gè)體驗(yàn)有點(diǎn)像我們?cè)?Spring 里通過(guò)注解聲明切面而不需要手寫 AOP 代理的生成邏輯。embabel 這類目標(biāo)驅(qū)動(dòng)框架就是要把 Java Agent 開(kāi)發(fā)從“底層機(jī)制編碼”提升到“目標(biāo)聲明與動(dòng)作編排”的層次從而降低 Agent 開(kāi)發(fā)門檻提升治理規(guī)則的可維護(hù)性。2. Java Agent 與目標(biāo)驅(qū)動(dòng)開(kāi)發(fā)的核心概念2.1 Java Agent 到底是什么Java Agent 是 JVM 對(duì)外提供的一種擴(kuò)展機(jī)制。開(kāi)發(fā)者可以編寫一個(gè)包含 premain 或 agentmain 方法的 JAR 包通過(guò)-javaagent:xxx.jar參數(shù)在應(yīng)用啟動(dòng)前掛載或者通過(guò) Attach API 在運(yùn)行期掛載到目標(biāo) JVM。掛載成功后Agent 可以獲得 Instrumentation 對(duì)象注冊(cè) ClassFileTransformer從而在 JVM 加載類或重新轉(zhuǎn)換類時(shí)修改字節(jié)碼。典型應(yīng)用場(chǎng)景包括性能監(jiān)控統(tǒng)計(jì)方法耗時(shí)、采集 JVM 指標(biāo)。鏈路追蹤自動(dòng)給 RPC 方法注入 traceId。故障診斷動(dòng)態(tài)打印參數(shù)、返回值和異常堆棧。熱修復(fù)替換某些方法的實(shí)現(xiàn)邏輯。增強(qiáng)框架在 Spring、MyBatis 等框架調(diào)用鏈路上增加邏輯。2.2 Premain 與 Agentmain 的區(qū)別入口方式掛載時(shí)機(jī)使用方式典型場(chǎng)景premainJVM 啟動(dòng)時(shí)main 方法執(zhí)行前-javaagent:xxx.jar靜態(tài)增強(qiáng)適合發(fā)布時(shí)統(tǒng)一掛載agentmainJVM 運(yùn)行中Attach API動(dòng)態(tài)掛載適合診斷已有進(jìn)程premain 的優(yōu)點(diǎn)是掛載時(shí)機(jī)早能在業(yè)務(wù)類加載前就完成 Transformer 注冊(cè)增強(qiáng)邏輯可控性高。agentmain 的優(yōu)點(diǎn)是無(wú)需重啟進(jìn)程但需要處理類重新轉(zhuǎn)換的問(wèn)題復(fù)雜度更高。目標(biāo)驅(qū)動(dòng)框架一般都會(huì)同時(shí)支持這兩種入口。2.3 目標(biāo)驅(qū)動(dòng)開(kāi)發(fā)框架解決了什么問(wèn)題目標(biāo)驅(qū)動(dòng)開(kāi)發(fā)框架解決的核心問(wèn)題是讓 Agent 增強(qiáng)邏輯更加“可聲明、可編排、可復(fù)用”。如果不使用目標(biāo)驅(qū)動(dòng)框架每增加一個(gè)增強(qiáng)目標(biāo)開(kāi)發(fā)者都要理解類型匹配器、方法匹配器、Advice 綁定規(guī)則、類加載器可見(jiàn)性。如果使用目標(biāo)驅(qū)動(dòng)框架增強(qiáng)目標(biāo)可以寫成類似下面這種結(jié)構(gòu)目標(biāo)類com.example.demo.HelloService目標(biāo)方法hello增強(qiáng)動(dòng)作方法進(jìn)入時(shí)記錄時(shí)間、方法退出時(shí)打印耗時(shí)這樣開(kāi)發(fā)者只需要專注增強(qiáng)動(dòng)作本身類型匹配、方法匹配、Advice 織入方式都由框架層統(tǒng)一處理。這也是“目標(biāo)驅(qū)動(dòng)”四個(gè)字的核心含義。3. 環(huán)境準(zhǔn)備與工程搭建3.1 基礎(chǔ)環(huán)境說(shuō)明本文實(shí)戰(zhàn)案例使用以下環(huán)境JDK 8 或更高版本Maven 3.6 以上操作系統(tǒng)Windows / macOS / Linux 均可字節(jié)碼操作庫(kù)ByteBuddy不同項(xiàng)目的 JDK 版本會(huì)存在差異實(shí)際開(kāi)發(fā)時(shí)應(yīng)根據(jù)線上運(yùn)行環(huán)境調(diào)整編譯源碼級(jí)別。本文示例統(tǒng)一使用 JDK 8 兼容的編譯方式方便在大多數(shù)存量項(xiàng)目中復(fù)現(xiàn)。3.2 Maven 工程結(jié)構(gòu)規(guī)劃為了讓 Agent 和被增強(qiáng)的應(yīng)用分離建議使用多模塊工程。本文的工程結(jié)構(gòu)如下javaagent-tutorial/ ├── agent-core/ │ ├── pom.xml │ └── src/main/java/com/example/agent/ │ ├── AgentMain.java │ ├── AgentAction.java │ ├── AgentTarget.java │ └── HelloCostAction.java │ └── src/main/resources/META-INF/services/com.example.agent.AgentAction └── demo-app/ ├── pom.xml └── src/main/java/com/example/demo/ ├── DemoApp.java └── HelloService.java模塊劃分的原則很簡(jiǎn)單agent-core 負(fù)責(zé) Agent 掛載和增強(qiáng)邏輯。demo-app 負(fù)責(zé)模擬一個(gè)普通業(yè)務(wù)應(yīng)用。這樣在運(yùn)行驗(yàn)證時(shí)可以清楚看到業(yè)務(wù)應(yīng)用本身沒(méi)有做任何修改增強(qiáng)完全來(lái)自 Agent。3.3 manifest 配置說(shuō)明一個(gè) Java Agent JAR 包必須在 manifest 中聲明 Premain-Class 等信息否則 JVM 不會(huì)識(shí)別它的 Agent 身份。常用配置項(xiàng)如下配置項(xiàng)作用Premain-Classpremain 入口類的全限定名Agent-Classagentmain 入口類的全限定名Can-Redefine-Classes是否允許重新定義類Can-Retransform-Classes是否允許重新轉(zhuǎn)換類本文示例使用 premain 方式所以重點(diǎn)配置 Premain-Class。如果需要?jiǎng)討B(tài)掛載還需要在 manifest 中增加 Agent-Class 配置。4. embabel 目標(biāo)驅(qū)動(dòng)的核心抽象4.1 目標(biāo)聲明的表示方式在目標(biāo)驅(qū)動(dòng)框架中目標(biāo)聲明通常包含三部分信息目標(biāo)類的全限定名、目標(biāo)方法名、處理動(dòng)作?;谧⒔饪梢赃@樣表達(dá)AgentTarget(className com.example.demo.HelloService, method hello) public class HelloCostAction implements AgentAction { }框架層通過(guò)讀取注解拿到字符串形式的目標(biāo)類名和目標(biāo)方法名再將其翻譯成 ByteBuddy 能識(shí)別的匹配規(guī)則。這樣做的好處是目標(biāo)信息與動(dòng)作代碼放在同一個(gè)類上一眼就能看出這個(gè)動(dòng)作要增強(qiáng)誰(shuí)。4.2 動(dòng)作編排攔截后做什么動(dòng)作編排是目標(biāo)驅(qū)動(dòng)框架最體現(xiàn)設(shè)計(jì)價(jià)值的部分。一個(gè)增強(qiáng)動(dòng)作通??梢圆鸱殖蓛蓚€(gè)階段方法進(jìn)入階段在目標(biāo)方法執(zhí)行前執(zhí)行可以記錄開(kāi)始時(shí)間、打印入?yún)?、修改參?shù)、控制是否繼續(xù)執(zhí)行。方法退出階段在目標(biāo)方法正常返回或拋異常后執(zhí)行可以記錄耗時(shí)、打印返回值、上傳異常信息。在 ByteBuddy Advice 中對(duì)應(yīng)的是 Advice.OnMethodEnter 和 Advice.OnMethodExit 兩個(gè)注解方法。目標(biāo)驅(qū)動(dòng)框架要做的就是把這些動(dòng)作編排能力封裝成統(tǒng)一接口讓開(kāi)發(fā)者不用關(guān)心 ByteBuddy 細(xì)節(jié)。4.3 生命周期與上下文傳遞生產(chǎn)級(jí)目標(biāo)驅(qū)動(dòng)框架不只是簡(jiǎn)單做一次方法織入它還需要考慮生命周期和上下文傳遞。例如多個(gè)增強(qiáng)動(dòng)作之間存在順序要求時(shí)如何編排執(zhí)行順序。方法進(jìn)入階段產(chǎn)生的臨時(shí)數(shù)據(jù)如何傳遞到方法退出階段。同一個(gè)類被多個(gè) Agent 或者自身重復(fù)匹配時(shí)如何避免重復(fù)增強(qiáng)。這些都屬于目標(biāo)驅(qū)動(dòng)框架的工程化能力。開(kāi)發(fā)者在選擇框架時(shí)應(yīng)該重點(diǎn)考察這些能力而不只是看它能不能做一次方法耗時(shí)打印。4.4 目標(biāo)驅(qū)動(dòng)與 AOP 的異同目標(biāo)驅(qū)動(dòng) Agent 和 AOP 都解決“在不改動(dòng)業(yè)務(wù)代碼的前提下增強(qiáng)邏輯”的問(wèn)題但它們的作用層不同。AOP 通常在應(yīng)用啟動(dòng)后由 Spring 容器生成代理對(duì)象目標(biāo)驅(qū)動(dòng) Agent 則通過(guò) JVM Instrumentation 在類加載階段修改字節(jié)碼。后者不依賴 Spring 容器也不需要被增強(qiáng)類實(shí)現(xiàn)接口或允許繼承對(duì)第三方 Jar 包內(nèi)部的方法也可以生效。這決定了目標(biāo)驅(qū)動(dòng) Agent 更適合做框架級(jí)增強(qiáng)、線上診斷、統(tǒng)一治理這類場(chǎng)景。5. 完整實(shí)戰(zhàn)構(gòu)建一個(gè)方法耗時(shí)監(jiān)控 Agent5.1 場(chǎng)景拆解本文實(shí)戰(zhàn)案例要完成的任務(wù)是不修改 HelloService 的任何代碼給 hello 方法增加耗時(shí)統(tǒng)計(jì)并在方法進(jìn)入和退出時(shí)打印日志。先編寫 agent-core 模塊的 pom.xml?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.example/groupId artifactIdagent-core/artifactId version1.0.0/version packagingjar/packaging properties maven.compiler.source8/maven.compiler.source maven.compiler.target8/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding bytebuddy.version1.14.9/bytebuddy.version /properties dependencies dependency groupIdnet.bytebuddy/groupId artifactIdbyte-buddy/artifactId version${bytebuddy.version}/version /dependency dependency groupIdnet.bytebuddy/groupId artifactIdbyte-buddy-agent/artifactId version${bytebuddy.version}/version /dependency /dependencies build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-shade-plugin/artifactId version3.4.1/version executions execution phasepackage/phase goals goalshade/goal /goals configuration transformers transformer implementationorg.apache.maven.plugins.shade.resource.ManifestResourceTransformer manifestEntries Premain-Classcom.example.agent.AgentMain/Premain-Class Can-Redefine-Classestrue/Can-Redefine-Classes Can-Retransform-Classestrue/Can-Retransform-Classes /manifestEntries /transformer /transformers /configuration /execution /executions /plugin /plugins /build /project這里有一個(gè)關(guān)鍵點(diǎn)Agent JAR 打包時(shí)需要把 ByteBuddy 依賴一起打進(jìn)最終 JAR否則應(yīng)用啟動(dòng)時(shí)雖然能加載 AgentMain但找不到 net.bytebuddy 相關(guān)的類。maven-shade-plugin 的作用就是把依賴整合到一個(gè) JAR 里。版本說(shuō)明ByteBuddy 版本建議以你實(shí)際項(xiàng)目中測(cè)試過(guò)的穩(wěn)定版本為準(zhǔn)不同大版本的 Agent API 可能略有差異。5.2 agent-core 模塊實(shí)現(xiàn)首先定義目標(biāo)注解 AgentTarget它是“目標(biāo)驅(qū)動(dòng)”的可視化入口package com.example.agent; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 目標(biāo)驅(qū)動(dòng)聲明標(biāo)記一個(gè) Agent 動(dòng)作要增強(qiáng)哪個(gè)類的哪個(gè)方法。 */ Retention(RetentionPolicy.RUNTIME) Target(ElementType.TYPE) public interface AgentTarget { String className(); String method(); }接著定義動(dòng)作標(biāo)記接口 AgentAction。這個(gè)接口不定義任何必須實(shí)現(xiàn)的方法作用是讓框架能夠通過(guò) ServiceLoader 統(tǒng)一加載所有增強(qiáng)動(dòng)作package com.example.agent; /** * Agent 動(dòng)作標(biāo)記接口。 */ public interface AgentAction { }接下來(lái)是核心入口 AgentMain。它讀取 ServiceLoader 加載到的所有 AgentAction解析目標(biāo)注解并將其翻譯成 ByteBuddy 匹配和織入邏輯package com.example.agent; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.utility.JavaModule; import java.lang.instrument.Instrumentation; import java.security.ProtectionDomain; import java.util.ServiceLoader; /** * Agent 啟動(dòng)入口。 */ public class AgentMain { public static void premain(String arg, Instrumentation inst) { AgentBuilder agentBuilder new AgentBuilder.Default() .disableClassFormatChanges() .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION); ServiceLoaderAgentAction actions ServiceLoader.load(AgentAction.class); for (AgentAction action : actions) { AgentTarget target action.getClass().getAnnotation(AgentTarget.class); if (target null) { System.out.println([agent] skip action without AgentTarget: action.getClass().getName()); continue; } agentBuilder agentBuilder .type(ElementMatchers.named(target.className())) .transform(new AgentBuilder.Transformer() { Override public DynamicType.Builder? transform( DynamicType.Builder? builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) { return builder.visit(Advice.to(action.getClass()) .on(ElementMatchers.named(target.method()))); } }); System.out.println([agent] register target: target.className() # target.method() - action.getClass().getName()); } agentBuilder.installOn(inst); System.out.println([agent] target-driven agent installed successfully.); } }這段代碼最需要理解的是 ServiceLoader 的使用方式。目標(biāo)驅(qū)動(dòng)的動(dòng)作類不通過(guò)硬編碼注冊(cè)而是通過(guò)META-INF/services/com.example.agent.AgentAction文件聲明這樣新增一個(gè)增強(qiáng)動(dòng)作時(shí)不需要改動(dòng) AgentMain 的注冊(cè)代碼符合開(kāi)閉原則。再來(lái)看 HelloCostAction它就是我們要執(zhí)行的增強(qiáng)動(dòng)作。package com.example.agent; import net.bytebuddy.asm.Advice; /** * 方法耗時(shí)統(tǒng)計(jì)動(dòng)作示例。 */ AgentTarget(className com.example.demo.HelloService, method hello) public class HelloCostAction implements AgentAction { Advice.OnMethodEnter public static long enter(Advice.Origin(#t.#m) String method) { System.out.println([embabel-example] enter method); return System.nanoTime(); } Advice.OnMethodExit(onThrowable Throwable.class) public static void exit(Advice.Origin(#t.#m) String method, Advice.Enter long startNanos, Advice.Return Object result, Advice.Thrown Throwable throwable) { long costUs (System.nanoTime() - startNanos) / 1000; System.out.println([embabel-example] exit method , costUs costUs , result result , throwable throwable); } }這里的幾個(gè)注解參數(shù)需要重點(diǎn)解釋Advice.Origin 可以拿到被增強(qiáng)方法的原始描述信息#t.#m表示“類型名.方法名”。Advice.Enter 可以拿到 OnMethodEnter 方法的返回值這里是把方法進(jìn)入時(shí)間傳遞給退出階段。Advice.Return 是目標(biāo)方法的返回值如果目標(biāo)方法拋異常這個(gè)值會(huì)是 null。Advice.Thrown 是目標(biāo)方法拋出的異常沒(méi)有異常時(shí)是 null。為了讓 ServiceLoader 識(shí)別 HelloCostAction還需要在 resources 目錄下創(chuàng)建服務(wù)文件。文件路徑agent-core/src/main/resources/META-INF/services/com.example.agent.AgentAction內(nèi)容com.example.agent.HelloCostAction5.3 被監(jiān)控的示例應(yīng)用先編寫 demo-app 模塊的 pom.xml?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.example/groupId artifactIddemo-app/artifactId version1.0.0/version packagingjar/packaging properties maven.compiler.source8/maven.compiler.source maven.compiler.target8/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding /properties build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-jar-plugin/artifactId version3.3.0/version configuration archive manifest mainClasscom.example.demo.DemoApp/mainClass /manifest /archive /configuration /plugin /plugins /build /project創(chuàng)建 HelloServicepackage com.example.demo; public class HelloService { public String hello(String name) { if (slow.equals(name)) { try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } return hello name; } }創(chuàng)建應(yīng)用入口 DemoApppackage com.example.demo; public class DemoApp { public static void main(String[] args) throws Exception { HelloService service new HelloService(); System.out.println(service.hello(embabel)); System.out.println(service.hello(slow)); } }這個(gè)應(yīng)用本身非常簡(jiǎn)單只是一個(gè)包含普通方法和 sleep 的業(yè)務(wù)類。接下來(lái)我們要驗(yàn)證不修改任何業(yè)務(wù)代碼Agent 就能自動(dòng)給 hello 方法增加耗時(shí)統(tǒng)計(jì)。5.4 構(gòu)建與運(yùn)行先構(gòu)建 agent-corecd agent-core mvn clean package -DskipTests再構(gòu)建 demo-appcd ../demo-app mvn clean package -DskipTests最后用 javaagent 參數(shù)啟動(dòng)應(yīng)用java -javaagent:../agent-core/target/agent-core-1.0.0.jar -jar target/demo-app-1.0.0.jar如果你的工程目錄結(jié)構(gòu)與本文不完全一致注意把-javaagent的路徑換成實(shí)際 agent JAR 的絕對(duì)路徑或相對(duì)路徑。6. 運(yùn)行與驗(yàn)證6.1 預(yù)期輸出正常運(yùn)行后控制臺(tái)輸出大致如下[agent] register target: com.example.demo.HelloService#hello - com.example.agent.HelloCostAction [agent] target-driven agent installed successfully. [embabel-example] enter com.example.demo.HelloService.hello [embabel-example] exit com.example.demo.HelloService.hello, costUsxxx, resulthello embabel, throwablenull hello embabel [embabel-example] enter com.example.demo.HelloService.hello [embabel-example] exit com.example.demo.HelloService.hello, costUs500xxx, resulthello slow, throwablenull hello slow6.2 驗(yàn)證 Agent 確實(shí)生效如果輸出中出現(xiàn)了[embabel-example]日志說(shuō)明 Agent 已經(jīng)成功織入目標(biāo)方法。此時(shí)我們不需要在 DemoApp 中打印任何額外日志Agent 的增強(qiáng)邏輯已經(jīng)生效。還可以進(jìn)一步驗(yàn)證不添加任何 Agent 參數(shù)直接啟動(dòng) DemoApp輸出中不會(huì)有[embabel-example]日志這能幫助確認(rèn)增強(qiáng)邏輯完全來(lái)自 Java Agent。6.3 常見(jiàn)變體在實(shí)際項(xiàng)目中你可能需要同時(shí)監(jiān)控多個(gè)類、多個(gè)方法或者在同一方法上執(zhí)行多個(gè)動(dòng)作。目標(biāo)驅(qū)動(dòng)框架的思路是增加更多帶 AgentTarget 注解的 Action 類并在 ServiceLoader 文件中注冊(cè)對(duì)應(yīng)實(shí)現(xiàn)類注冊(cè)邏輯不需要改動(dòng)。7. 常見(jiàn)問(wèn)題與排查思路目標(biāo)驅(qū)動(dòng) Agent 雖然降低了開(kāi)發(fā)門檻但底層仍然是 JVM Instrumentation 和字節(jié)碼增強(qiáng)線上運(yùn)行時(shí)不缺各種問(wèn)題。下面整理一張常見(jiàn)故障速查表。問(wèn)題現(xiàn)象常見(jiàn)原因解決思路Agent 啟動(dòng)日志都沒(méi)打印JAR 未配置 Premain-Class或 javaagent 路徑錯(cuò)誤檢查 manifest 中 Premain-Class修正路徑增強(qiáng)方法沒(méi)有生效目標(biāo)類名、方法名匹配不上或類加載器不同確認(rèn)全限定名和加載器調(diào)整匹配范圍拋 ClassNotFoundException增強(qiáng)動(dòng)作類對(duì)目標(biāo)類的 ClassLoader 不可見(jiàn)將動(dòng)作類放入可見(jiàn)類加載器或使用委托機(jī)制方法被重復(fù)增強(qiáng)多個(gè) Agent 或重復(fù)注冊(cè)了 Transformer加冪等保護(hù)檢查重復(fù)掛載情況啟動(dòng)后應(yīng)用變慢增強(qiáng)方法范圍過(guò)大或動(dòng)作邏輯太重縮小目標(biāo)范圍異步化處理最少化增強(qiáng)邏輯retransform 拋出異常類格式變化被拒絕或與 JVM 參數(shù)沖突檢查 Can-Retransform-Classes關(guān)閉 disableClassFormatChanges7.1 Agent 啟動(dòng)日志都沒(méi)打印首先確認(rèn) manifest 里有沒(méi)有 Premain-Class??梢詧?zhí)行命令查看unzip -p agent-core-1.0.0.jar META-INF/MANIFEST.MF也能直接檢查agent-path是否誤寫成 jar 內(nèi)目錄。另外Agent 通常會(huì)在 main 方法之前執(zhí)行如果 premain 方法內(nèi)部拋了異常會(huì)有明確堆棧需要優(yōu)先處理這類報(bào)錯(cuò)。7.2 增強(qiáng)方法沒(méi)有生效比較常見(jiàn)的原因有三個(gè)目標(biāo)類名不是完整二進(jìn)制名例如把com.example.demo.HelloService寫成了HelloService。方法名不匹配ByteBuddy 默認(rèn)匹配精確方法名重載方法需要額外聲明參數(shù)類型。目標(biāo)類由自定義 ClassLoader 加載Agent 匹配規(guī)則沒(méi)有覆蓋到該 ClassLoader。生產(chǎn)環(huán)境排查時(shí)可以先在 premain 里打印注冊(cè)日志再通過(guò)-verbose:class日志確認(rèn)目標(biāo)類的加載情況觀察 Transformer 是否被觸發(fā)。7.3 拋 ClassNotFoundException當(dāng)被增強(qiáng)的類位于自定義 ClassLoader 中比如 Tomcat 的 WebAppClassLoader而 Action 類在 Agent JAR 中時(shí)目標(biāo)類加載器可能無(wú)法加載 Action 類。普通java -jar應(yīng)用一般沒(méi)有這個(gè)問(wèn)題但容器類應(yīng)用需要注意。解決方法是把動(dòng)作相關(guān)類放到能被目標(biāo)類加載器看到的 ClassLoader 中或者使用類加載器委托策略讓增強(qiáng)代碼在正確的加載器上下文中執(zhí)行。7.4 方法被重復(fù)增強(qiáng)重復(fù)增強(qiáng)多發(fā)生在同一個(gè) Agent 重復(fù)掛載或者多個(gè) Agent 都注冊(cè)了相同目標(biāo)的 Transformer。目標(biāo)驅(qū)動(dòng)框架里可以通過(guò)維護(hù)一個(gè)全局注冊(cè)表在 register 時(shí)檢查目標(biāo)是否已經(jīng)注冊(cè)避免重復(fù)織入。生產(chǎn)環(huán)境也應(yīng)該約定一個(gè)唯一標(biāo)識(shí)防止多個(gè)實(shí)例同時(shí)掛載同一個(gè) Agent 時(shí)互相影響。7.5 啟動(dòng)后應(yīng)用變慢Java Agent 增強(qiáng)邏輯運(yùn)行在業(yè)務(wù)線程中如果動(dòng)作里做了比較重的 IO、鎖等待或遠(yuǎn)程調(diào)用業(yè)務(wù)接口 RT 就會(huì)明顯上升。目標(biāo)驅(qū)動(dòng)框架適合做輕量級(jí)增強(qiáng)耗時(shí)統(tǒng)計(jì)之外參數(shù)采集、日志輸出都應(yīng)盡量異步和降級(jí)。必要時(shí)可以增加開(kāi)關(guān)在業(yè)務(wù)低峰期開(kāi)啟。8. 生產(chǎn)環(huán)境最佳實(shí)踐8.1 最小化增強(qiáng)范圍目標(biāo)驅(qū)動(dòng)框架提供了目標(biāo)匹配能力但開(kāi)發(fā)者不能因此濫用。建議只增強(qiáng)必要的方法不要整包掃描、全量增強(qiáng)。增強(qiáng)范圍過(guò)大不僅影響性能還會(huì)增大類加載階段的風(fēng)險(xiǎn)。可以用“白名單”思路控制目標(biāo)范圍只列出確需增強(qiáng)的類和方法其他一律排除。上線前最好在預(yù)發(fā)環(huán)境做一次全鏈路回歸觀察核心接口耗時(shí)變化。8.2 動(dòng)作邏輯保持輕量Agent 動(dòng)作在目標(biāo)方法調(diào)用鏈路上執(zhí)行任何阻塞操作都會(huì)反向影響業(yè)務(wù)。增強(qiáng)動(dòng)作應(yīng)該具備以下特點(diǎn)不執(zhí)行遠(yuǎn)程調(diào)用。不申請(qǐng)長(zhǎng)時(shí)間鎖。不批量創(chuàng)建大對(duì)象。不做大日志輸出。如果確實(shí)需要上傳數(shù)據(jù)建議統(tǒng)一寫入一個(gè)內(nèi)存隊(duì)列由獨(dú)立線程異步消費(fèi)。8.3 可觀測(cè)性日志、指標(biāo)、鏈路Agent 本身也應(yīng)該被觀測(cè)。建議在 Agent 層補(bǔ)充以下能力啟動(dòng)成功/失敗日志。目標(biāo)匹配統(tǒng)計(jì)。動(dòng)作執(zhí)行失敗計(jì)數(shù)。增強(qiáng)耗時(shí)上報(bào)。這能幫助你在 Agent 不出問(wèn)題時(shí)快速發(fā)現(xiàn)出了問(wèn)題時(shí)快速定位。8.4 灰度與快速回滾生產(chǎn)環(huán)境掛載 Java Agent 本質(zhì)上是在線修改字節(jié)碼風(fēng)險(xiǎn)不可完全忽略。上線前必須先在一組低流量節(jié)點(diǎn)驗(yàn)證再逐步擴(kuò)大范圍。接線時(shí)最好保留兩組發(fā)布配置一組開(kāi)啟 Agent一組不開(kāi)啟 Agent。一旦發(fā)現(xiàn) Agent 導(dǎo)致異??梢钥焖偻ㄟ^(guò)配置中心切換回滾。8.5 安全與最小權(quán)限對(duì)線上應(yīng)用做字節(jié)碼增強(qiáng)需要遵循最小權(quán)限原則只讀類信息時(shí)不進(jìn)行類定義。只在必要方法上織入邏輯。不在 Agent 邏輯中保存業(yè)務(wù)敏感參數(shù)。Agent 包發(fā)布前經(jīng)過(guò)代碼評(píng)審避免內(nèi)部邏輯成為攻擊面。如果你在生產(chǎn)環(huán)境需要臨時(shí)排查問(wèn)題優(yōu)先考慮使用動(dòng)態(tài)掛載的 agentmain而不是直接改動(dòng)業(yè)務(wù)代碼。9. 總結(jié)與后續(xù)學(xué)習(xí)建議通過(guò)本文的講解和實(shí)戰(zhàn)我們圍繞 embabel 這類目標(biāo)驅(qū)動(dòng)的 Java Agent 開(kāi)發(fā)框架拆解了目標(biāo)驅(qū)動(dòng)帶來(lái)的變化開(kāi)發(fā)者只需聲明目標(biāo)類、目標(biāo)方法再編寫增強(qiáng)動(dòng)作框架層負(fù)責(zé)將目標(biāo)翻譯成 Instrumentation 與字節(jié)碼增強(qiáng)邏輯。在實(shí)戰(zhàn)部分我們用 ByteBuddy 結(jié)合 ServiceLoader搭建了一個(gè)可運(yùn)行的方法耗時(shí)監(jiān)控 Agent。這個(gè)示例雖然不復(fù)雜但它完整展示了目標(biāo)驅(qū)動(dòng) Agent 的核心流程注解聲明目標(biāo)、動(dòng)作類承載增強(qiáng)邏輯、ServiceLoader 自動(dòng)注冊(cè)、premain 入口完成織入。如果你接下來(lái)要繼續(xù)深入學(xué)習(xí)建議按以下路徑推進(jìn)掌握 ASM 和 ByteBuddy 的匹配器 API理解字節(jié)碼增強(qiáng)邊界。研究 agentmain 動(dòng)態(tài)掛載技術(shù)配合 Attach API 實(shí)現(xiàn)生產(chǎn)環(huán)境局部增強(qiáng)。在 Agent 中增加指標(biāo)上報(bào)和降級(jí)開(kāi)關(guān)往生產(chǎn)級(jí)組件靠近。閱讀 SkyWalking、Arthas 等開(kāi)源項(xiàng)目的 Agent 設(shè)計(jì)思路體會(huì)底層機(jī)制。回到目標(biāo)驅(qū)動(dòng)這個(gè)話題真正適合生產(chǎn)環(huán)境的 Java Agent 開(kāi)發(fā)框架不只是讓新手能寫幾行示例代碼而是能在復(fù)雜類加載環(huán)境、高并發(fā)場(chǎng)景和灰度回滾訴求下讓增強(qiáng)邏輯變得可控、可觀測(cè)、可維護(hù)。如果你也在設(shè)計(jì)內(nèi)部診斷組件可以先從最小目標(biāo)開(kāi)始驗(yàn)證再逐步把發(fā)布和回滾流程補(bǔ)起來(lái)。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
久久性爱视频| 夜色爱爱亚洲| 色五月天丁香| 99在线精品视频免费观看20| 麻豆科斗777| 2015WWW永久免费观看播放| 99热6这里只有精品| 丁香五月激情啪啪| 丁香六月亚洲综合| 新激情五月天色播| 欧美婷| 国产免费AV在线| 五月天激情色色| 99精品视频免费观看| 激情婷婷五月黑人| 伊人六月丁香婷婷| 激情综合网,婷婷| 色婷婷成人网| 狠狠干综合| 人人操 色| 熟女人妻一区二区三区免费看| 天天日夜夜| 婷婷丁香激情综合色情| 79精品视频在线观看,| 婷婷六月久久| 亚洲激情综合五月婷婷啪啪| 五月天婷婷永久免费视频| 色情五月天小说| 超碰不卡在线| 色欲天天综合| 五月丁香色婷婷婷基地| 五月色婷婷综合丁香精品无遮挡| 99色在线观看| 天天干天干| 激情小说之五月| 99热精品在线播放观看| 色99综合视频| 九九性视频| 天天综合亚洲综合| 人人摸人人搞| 久久人操| a在线观看| 丁香五月色| 久久精品4| √天堂资源在线人妻熟女| 色色色色色色网站| 久久婷婷啪啪视频| 五月婷丁香| 成人做爰A片免费看网站找不到了 噼里啪啦在线观看免费完整版视频 | 综合五月婷婷| 少妇人妻人伦A片| 天天色视频| 九月激情网| 婷婷五月综合激情| 另类五月激情| 亚洲综合婷婷五月| 熟女五月天久久综合| 狠狠色丁香综合| 丁香婷婷五月天亚洲| 婷婷五月天Av| 91精品综合久久婷婷九色| 亚洲精品色| 天堂网啪啪| 色五月婷婷网| 婷婷综合激情| 色婷婷色综合| 五月天婷婷色五月天| 视频这里只有精品16| 婷婷丁香基地在线| 激情av| 五月丁香综合| 色婷婷狠狠18禁| www.henhenl| 婷婷丁香在线| 国内精品免费一区二区2009| 影音先锋色婷婷| 丁香五月婷婷啪啪| 精品人妻一区二区三区四区不卡在| 久久怡红院| 五月丁香偷拍| 91无码高清| 99热综合| 日本婷婷| 丁香婷婷久久五月天| 色日本综合| 亚洲综合激情五月久久| 天天干天天操天天拍| 中文字幕视频在线播放| 99精品丰满| 色婷婷五月天偷拍| 米奇影视资源777狠狠色婷婷五月天激情网| 久久这里有精品视频| 久久网日本| 中文毛片无遮挡高潮免费| 五月婷婷激情日本| 欧美性色五月天| 亚洲性爱电影| 99综合成人视频在线观看| 俺也去在线久久精品23欧美综合视频网站,丰满人妻一区二区三区在线视频53,丰满 | 婷婷久久在线| 丁香五月天激情综合网| 天天综合精品| 婷婷九九| 9久久久久| 天天日天天肏天天奸| 欧美激情伊人| 日日夜夜爽| www,久久久| aV直接看| 亚洲综合网激情小说| 饮料下药迷倒漂亮女同事强干| 久久ww| 91九色无码内射| 色噜噜狠狠色综合AV兰草影视| 激情性五月天免费小说视频| 这里只有精品96| 91超级碰在线视频| 丁香五月网址| 亚洲人妻Av| 第四色婷婷五月| 五月天婷婷无码| 丁香玖玖视频大全| 日本美女五月天| av婷婷六月丁香社区在线观看| 日本综合久久| 99精品网| 99在线爽| 国产视频色色色色色色色 | 亚洲天堂aaaa| 五月丁香综合成人社区| 成人免费在线电影| 国产精品日日躁夜夜躁| 久久精品视频99| 伦乱人妻| 99热综合网| 99re资源在线视频导航| 人人草人人视| 亚洲AV无码影院| 激情网综合| 日日影院 | 五月天激情综合首页| 99久久99久久| 丁香婷婷激情综合五月激情| 日日干夜夜干| 天天日日爽| 91大屁股在线| 五月婷婷啪啪| 日本三级日本三级99| 色综合久久88色综合天天看| 亚洲激情网| 婷婷亚洲色| 色999五月色| 丁香六月婷婷久久综合| 激情婷婷综合| 婷婷五月另类网站| 区美毛片子| 影音先锋91| 久久婷婷内射| 丁香女人五月天| 欧美韩国日本| 情趣视频66| AV在线不卡网站| 婷婷五月天在线综合| 色婷婷色九月| 无码激情AAAAA片-区区| 九九久久综合| www.wuyuetian啪啪| 夜夜撸日日骑| 九九色色网| 99热这里有精力| 九九AV| 五月婷在线| 狠狠狠狠免费| 久久亚洲无码| 色135综合网| 五月天色婷婷基地| 婷婷综合在线| 岛囯综合激情网| 这里只有精彩视频| A一级操| 丁香五月花影院| 婷婷五月六| 久久九九玖玖| 久久九久久| 五月婷婷在线免费| 五月丁香 久久久| 亚洲视频另类| 婷婷五月花| www,婷婷| 色亚洲视频| 日本在线观看91| 婷婷色影院| 激情婷婷丁香五月| 日韩无码专区| 五月婷婷之综合激情在线| 97色色视频| 五月天六月丁香| 九 九九九AV| 五月婷婷色五月| 玖玖福利视频资源| 亚洲精品操一操、噜一噜、摸一摸、爽 | 99九九视频| 激情黄色小说五月天| 五月天丁香成人社| 狠狠狠狠青草| 1级欧美日韩| 玖玖精品视频| 日本婷久久| 丁香六月视频| 五月婷婷干干干| H亚洲| 99在线免费观看| 青青草激情网| 免费不卡狠操美女视频网| 丁香五月香蕉在线| 9久久久久久久久久久| 中日韩美欧成人一区二区精品在线 | 五月天播播| 亚洲色情在线| 爱婷婷五月| 欧洲激情网站| 超碰狠狠操| 五月婷久久久| 婷婷五月天你懂的| 99久久五月天| 国产永久一黄| 91色色色视频| 亚洲a片免费观看| 日韩成人精品中文字幕| 99自拍视频| 大香蕉综合在线| 久久爱婷婷| 天天操天天草天天草天天| www.天天干.com| 任你操精品免费| 韩国97天堂| 日本欧美成人片AAAA| 亚洲成人在线播放| 五月天婷婷综合| 中美日韩成人在线| 九九热超碰| 五月丁香激| 99热这里只有精品首页| 久久Xx| 亚洲另类视频| 五月丁香琪琪| 26uuu亚洲| 五月婷婷丁香综合| 狠狠色狠狠操| 免费视频WWW在线观看网站| 亚洲天天操| 激情久久久久久| 久热黄色| 婷婷综合五月| 97碰碰草| 99精品久久久久久久| www.99日本| 九九热99熟女| 五月激情四射婷婷丁香| 26UUU精品一区二区Com| 日本操B视频| 婷婷五月天激情电影小说| 婷婷五月激情丁香| 九九99在线免费在线观看视频| 亚洲成人高清在线| 粉嫩AV久久一区二区三区| 亚洲亚洲人成综合网络| 91久久18| 婷婷97| 99综合婷婷五月| 五月婷婷婷婷婷婷艺术| 色无码| 色玖玖综合网| seav天堂| 大香蕉久久草| 337p午夜影院| 五月天偷拍| 婷婷天堂综合| 超碰婷婷五月| 婷婷午夜丁香| 色操b| 另类综合婷婷五月天欧美视频| 五月天亚洲综合网| 图片区 小说区 区 亚洲五月| 亚洲天堂婷婷丁香| 激情综合网五月| 亚洲五月天,激情视频| 五月天成人在线视频丁香| 国产片色| 色婷婷www| 成 人片 黄 色 大 片| 色狠狠婷婷| 久久在线大香蕉| 久久久妻人人人| 丁香五月av在线| 99无码| 开心五月激情网| 在线五月婷| 婷婷的99视频网站| 婷婷五月婷| 丁香五月婷婷色| 激情操逼婷婷| 婷婷五月激情热播| 久久婷丁香五月| 久色精品| 乱女乱妇熟女熟妇综合网站 | www.9797国产| 超碰妻人人| 97精品综合久久| 欧美精品熟女一区二区| 图片区 小说区 区 亚洲五月 | 久久99婷婷| 婷婷五月天激情小说网站| 久久婷网| 91日精品| 国产玖玖资源| 美女婷婷激情亚洲| 色人五月婷婷| 五月天激情综合网| 日韩欧美颜射| av在线观看免费| 婷婷成人av| WWW.激情| 久久98| 色激情五月| 国产高清RV综合aVa| 综合色情网| 久久艹网| 狠狠xx| 久久综合九色综合97婷婷| 综合久久97| 人妻内射视频| 色婷婷文字幕| 久久久久婷 | 激情文学第四色婷婷丁香五月| 五月婷婷欲色| 久久久久久久久月丁| www.25五月婷婷| 日本美女上人| 五月丁香福利| 五月丁香色| 久99久精品视频| 99.N在线视频| 九洲一级A片| 五月天四色房丁香亭亭| 全高清无码视頻| 婷婷婷婷婷婷婷婷| 天堂爱啪啪| 玖玖精品视频| 色欲久久久久久综合网综合网| 激情网婷婷婷| 久久婷婷五月综合色丁香| 夜夜干天天干| www.久久爱.com| 丁香婷婷激情六月五月开心| www.97干视频| 五月丁香777| 九久9精品| 91Chinese在线| 久久综合中文| h在线看免费版在线看| 婷婷五月天堂网| 五月婷婷成人| 天天爱天天做天天爽| 亚洲乱码日产精品BD| 五月丁香啪啪拍| 国产成人精品亚洲线观看| 五月亭亭激情综合| 久久图色4| 婷婷激情视频| 丁香五月婷婷少妇| 高清a片基地| 五月丁香六月激情欧美综合| 91操在线视频| 疯狂做受XXXX高潮A片动画| 丁香激情合作五月| 香蕉乱插| 婷婷六月色| 亚洲九九99精品视频在线播放| 69天堂99| 大香蕉婷婷五月天| 久久婷婷操| 亚洲视频另类| 五月婷婷激情久久| 亚洲激情视频网| 97操女视频| 五月天婷婷操逼视频| 久草五月婷婷| www.玖玖九| 亚洲色热| 狠狠色婷婷丁香六月| 五月天另类小说久久小说网| 婷婷性爱影院| 狠狠干五码| 婷婷五月天AV在线| 怎么样可以看免费的一级av| 91九色精品| 久久66er久久| 一二区成人电影| 五月色综合| 婷婷五月综合视频| 看黄的网站18禁| 婷婷五月综合丁香久久| 色五月丁香网| 欧美Va日本Va| 深爱开心激情网| 色九九丁香九月色九九色| 人妻啪啪啪| 亚洲人人操BD| 亚洲中文无码成人| 欧美精品999| 我淫我色婷婷五月天激情四射| 97操碰在线视频| 色播五月丁香婷婷| 99啪啪视频| 色婷婷狠狠禁久久| 国产精产国品一二三在观看| 色999亚洲人成色| 色婷婷激情五月天在线观看| 亚洲亚洲激情| 97久久人人| 亚州第一黄网| 日韩二区搞逼插逼毛片| 婷婷久热| 99日韩| 婷婷操婷婷干婷婷射| 丁香婷婷五月天网站| 五月婷婷国产| 3DAV亚洲香蕉久久 一区二区| 色综合色色色| 国産精品| 超碰资源在线| 久狠狠| 久久久五月婷婷| 丁香五月天导航| 婷婷五月天黄色网址| 4399无码视频二区| 久久综合久色欧美综合狠狠| 丁香五月激情五月| 色婷婷九月| 欧洲亚洲免费视频9 | 婷婷欧美综合| 久久草中文日韩欧美| 色五狠狠| 热99精品视频| 日本成人小说婷婷六月| 另类小说五月天激情| 婷婷激情五月天网站| 婷婷的久久网站| 五月丁香综合成人社区| 综合色婷婷| 中文字幕人妻AV| 久cao香蕉影院| 色偷偷AV亚洲男人的天堂| 五月丁香六月婷综合成人综合| 五月婷婷视频在线观看| 午夜丁香综合婷婷| 成人婷99最新| 色色色热| 色色无码| 99热传媒| 激情淫乱男女| 婷婷综合在线播放| 色5月婷婷| 丁香五月婷婷色| 黄色成人网站在线播放| 五月丁香婷婷综合| 美妞av| 无码网| 色97综合婷婷天天色| 九九视频精品这里只有| 激情五月天色爱| 五月天婷婷激情春色小说| 欧美性爱5月天天天看| 五月色婷婷激情| 综合六月激情婷婷| 伊人色综合网| 91超碰人人操| 午夜天堂一区人妻| 影音先锋五月天婷婷丁香在线观看| 91av成人| 99九九精品视频| 五月丁香婷婷色色| 99色丁香婷婷综合网| 热的无码综合视频| 91ncm视频| www.婷婷五月| 99riAV成人在线视频| 九一牛视频探花| 激情久久久久久久久久| 这里只精品| 五月精品免费XXX| 天天操天天操天天操天天操天天操| 国产亚洲色婷婷久久99精品91| 久久激情五月天| 激情五月天色色网| 亚洲欧美国产A片免费观看| 综合色影| 国产精品久久久60086| 五月天婷婷色综合| 99re在线观看| 日熟女| ay2区| 亚洲综合激情五月| 婷婷五月天激情网| 丁香六月激情毛片| 人人射av| 精品激情| 亚洲国产黄色电影| 另类色视频| 精品五月天| 欧美色婷婷| 91在线资源| 成人在线网址| 丁香五月天在线观看| 婷婷伊人网| 99情色五月天| 国内婷婷丁香社区在线播放| 精品爆操| 婷婷成人av| 九九碰九九爱97超碰| 婷婷丁香五月高清| 国产人妻777人伦精品HD| 99 福利 导航| 色婷五月天网站| 久9视频| 99热欲| 激情五月激情综合网一级丸片| 丁香五月激情五月| ZpRSw| 思思久ren热| 日韩在线观看亚洲| 欧美三级大片AA在线看| 青青草蜜臀| 97中文在线| 丁香花五月天婷婷成人社区| 深爱激情五月天色婷婷| 亚洲天堂色色| 久久久久婷婷| 另类专区在线| 狠狠色色综合| 婷婷亚洲综合| 丁香五夜激情四射夜夜夜| site:jszngf.com| 91人人操人人| BT综合在线视频观看| 丁香五月亚洲| 婷婷成人av| 亚洲综合婷婷| 丰满少妇乱A片无码| 99色区| 一本久道综合色婷婷五月| 麻豆123区| 伊人久久五月天| 精品一二三区久久AAA片| 91狠狠色丁香婷婷综合久久精品| 在线看片av| 97干在线看| 五月丁香六月综合激情无码软件亮点 | 久久人妻在线| 99视频综合网| 婷婷五月天国产在线播放| 在线亚洲综合| www,婷婷,com| 99久久精品色老| 色婷婷偷拍| www.五月天婷婷| 成人在线视频一区| 久久久大香蕉| 五月丁香六月情| 久久ww| 久婷| 色婷婷a| 六月婷婷私欲| 五月丁香六月片| 天天天摸夜夜夜玩| ww超碰在线| 夜夜躁爽日日| 超碰激情网| 狠狠va| 亚洲亚洲人成综合网络| 狠狠色激情综合| 亚洲丁香婷婷| 国产亚洲精品久久一区二区三区| 久久久激情视频| A久久| 99热思思在线观看| 久久婷婷五月综合色和| 丁香 久久| 丁香六月综合激情| 日本强伦片中文字幕免费看| 五月天婷婷爱| 狠狠综合| 五月丁香婷婷钟和色图| 播播网色播播| 天天激情5月天亚洲| 夫妇交换刺激做爰| 丁香婷婷视频在线| 色色婷| 免费看欧美成人A片无码| 亚洲综合色棒| 五月婷视频| 99性感视频| 在线超碰91| 色色婷婷丁香| 婷婷五月天激情电影小说| www.婷婷亚洲基地| 日本无码专区| 激情小说婷婷小说| 97香蕉人人在线观看| www色色com| 色五月色综合| 九九AV在线| 六月婷婷色色网| 激情床戏| 久久96热| 久久婷婷五月| 亚洲无码www| 九九在线视频| 超碰在线免费9| 色丁香在线视频| 香蕉婷婷色五月| 精品亚洲国产成AV人片传媒| 五月综合激情| 乱色色色| 色五月丁香一区在线| www.色九月| 久久久亚洲精品一区二区三区浴池| 五月天婷婷影院影院观看| 激情深爱综合| 色噜噜狠狠色综合成人网| 久久久一级AAA| 色播丁香| 九九热婷婷| 热久久视频99| 九九热视频首页/这里只有精品| 丁香五月综合久久| 免费无码毛片一区二区A片| 久久92| 九九热精品6| 亚洲中文无码成人| 99精品在线播放| www热久久yy9| 久在线综合69| 色五月丁香网| 五月成人综合| 狠狠色激情综合| 99热 这里只有精品 国产 日韩| 色吊操色妞| 亚洲天堂婷婷丁香| 婷婷五月天激情小说| 婷婷丁香97| 亚洲激情五月天| 狠狠草综合网| 色五月六月婷婷| 亚洲亚洲激情| 色狠狠999综合网| 91久久久久久久久18| 97丁香五月| 五月丁香婷婷啪啪网| 五月天色色色网| 国产精品91抖高| 国产精产国品一二三在观看| 精品一二三区久久AAA片| 激情综合五| 丁香五月天堂| 婷婷五月激情中文字幕| 四色五月婷婷| 久久小视频| 99激情视频| 五月激情综合网| 久久激情五月| AV大香蕉| 婷婷91视频| 欧美性生交xXxX久久久| 丁香五月婷婷天激情| 九九九九操逼| 操草草草| 大香AV| 五月丁香婷婷成人版| 国产婷婷综合| 久久草大香蕉| 婷色成人| 婷婷射婷婷舔| 激情五月婷黄版| 99无码超碰| 婷婷五月情| 婷婷五月丁香五月| 在线综合亚洲欧美65| 丁香婷婷五月综合欧美另类| 婷婷第一页| 91视频一起草| 激情五月伊人婷婷| 五月花丁香婷婷| 婷婷综合五月| 九九这里有精品| 一起草AV入口| 激情五月天第四色| 99热国产精品| www开心激情网| 国产欧美va| 婷婷色五月激情| 婷婷久久综合久| 99riAV成人在线视频| 99热第一页| 久久综合丁香五月| 五月丁香龟婷婷| 亚洲在线资源| 丁香五月五月婷婷欧美大香蕉| 五月天色色色网| 色综合久久天天综合网| 色婷婷丁香AV综合| 激情婷婷久久| 熟惀91九色在线| 99色在线观看视频| 色五月开心五月激情五月| 五月天婷婷无码视频| 色婷婷狠狠爱| 爱穴久久| 激情婷婷丁香五月天小说| 能直接看的AV网站| 激情亚洲网| 久久久久久久久久久久久久久久一道本| 色www.con| 婷婷激情鹿城五月天| 另类图片五月天| 白人荫道BBWBBB大荫道| 99WWW免费视频| 天天拍夜夜爽| 久久只有18视频| 一区二区三区四区牛| 五月天天天综合| 99无码精品| 国产SUV精品一区二区883| 五月天婷综合| 五月天,激情四射,婷婷频道| 免费黄色片子| 98色花堂98t.R| 丁香五月六月激情| www.99热| 婷婷九月| 婷婷丁香69精华| 色播五月婷婷| 九久久九精品视频| 婷婷黄色五月天在线视频| 99碰网站| 国产婷婷久久| 欧美激情-区二区三区| 大香蕉啪啪啪| 91精品久久久久久综合五月天| 色五月天综合网| 婷婷丁香综合网| 夜夜涩涩涩| 操人无码| 4399在线日本A片| 婷婷五月天av| 怡红院成人AV| 丁香六月色婷婷| 91色五月在线观看| 婷婷六月天精品| 亚洲成人免费在线| 九九九精品视频免费观看| 亚洲旡码| 一级性感黄色内射视频| 色九亚洲| 九热免费视频| 亚洲黄色精品| 色综合久久综合中文综合网| 激情亭亭五月| 九九精品热播| 色婷婷a v| 啪啪黄页网| 日本色色网站| 香焦网五月天| 色五月婷婷综合| 天天久久狠狠色综合| 91丨九色丨熟女|老版| 久久WW| 狠狠干狠狠干| 一级精品999WWW| 九色PORNY自拍成人精彩视频| 久久久五月婷婷| 偷拍91九色| 婷婷丁香97| 婷婷金品综合视频| 色婷婷成人丁香| 亚洲精品久久久久AV无码| 深爱激情九九五月天| 无码人妻AV久久久一区二区三区| 99在线看片| 久婷狼色诱惑在线| AV操操操| 97视频久久| 思思热视频在线| 国产精品久久在线观看技巧| 综合色色五月| 99精品福利视频| 色婷婷五月影院| 色综合综合色| 欧美成人热| 婷婷99综合| www天天色天天射| 欧美丁香五月97色| 99操| 欧美啄木乌丝袜人妻系列| 69色婷婷| 伊人久久婷婷| 思思热久久久久思思热| 97久操视频| 激情五月婷婷综合| 5月婷婷激情6月| 婷婷亚洲久久| 亚洲操操操| 色人妻五月| 久久精品五月天| 丁香五月成人| 日韩五月丁香| 天天日日夜夜爽| 色婷婷香蕉在线| 久草性爱| 久久A热| 狠狠综合区| 日本久久精品| 婷婷五月综合亚洲| 国产亚洲精品人人| 欧美三级大片AA在线看| 91精品久久久久久77777| 国产丁香五月天婷婷| 日亚二欧美| 国精产品一区一区三区免费视频| 国产婷婷五月色情综合| 少妇丁香婷婷 | 天堂婷婷综合| 开心五月综合激情网| 亚洲看av的网站| 色五月综合在线| 啪啪日本欧美| 色色A| xx人人xx| 九九草热在线观看| 五月久久婷婷| 人人操碰| 欧美三级A做爰在线观看| 婷婷五月天AV| 久久婷婷五月天激情| 色99自拍| 人妻久久久久久久 | 五月天婷婷日日爱| 啪啪六月婷婷| 草榴视频黄色网| 深爱激情五月网| 99热97| 国产精品蜜臀99| 色五月婷婷中文字幕在线观看 | 日本久久综合| 婷婷伊人綜合| 五月激情综合婷婷| 中文毛片无遮挡高潮免费| 香蕉久久国产AV一区二区| 欧美成人性爱网| 99热这里只有精品2016| 婷婷激情小说网| 淫视馆AV在线| 激情熟女网| 伊人在线大香蕉网| 97很鲁在线视频| 99热成人| 这里只有精品1| 午夜亚洲国产精品av一区二区| www天天爽| 婷婷五月天亚洲图片| 美女丁香五月天| 久久XX| 婷婷色丁香五月| 精品九九网| 琪琪色网址| 五月天婷婷综合色| 色婷婷成人做爰A片免费看网站| 五月婷婷色| 久久99热这里只有| 99日本精品视频热| 大香蕉婷婷久久| 天堂爱啪啪| 99久在线精品99re5热视频| 卡视频1区2区| 久久久久久久久久久久63| 婷婷狠狠青青| 色情婷婷久久五月天| 婷婷在线五月综合| 玖玖婷婷色欲| 嫩模草| 婷婷激情六月中文| 丁香婷婷浪潮AV久久综合| 碰碰人人人| 日韩中出视频| 色综合播放| 九九激情视频| 91丨九色丨熟女丰满| www.97碰碰com| 欧美激情综合色综合啪啪五月| 91人人澡人人爽人人看| 国产成人在线精品| 五月丁香成人网| 99热这里有精品6| 狠狠操天天操天天操| 99视频精品8 | 亚洲网视屏| 欧美成人A片AAA片在线播放 | 久久婷婷在线| 久热只有这里精品| 日日操日日撸| 激情久久综合| 91操人视频| 成人国产欧美大片一区| 99热最新国内| 综合玖玖偷拍| 伊人久久婷婷| 开心四月婷婷在线色播播| 深爱激情久久| 开心婷婷五月| 天天操天天曰| 日日干四虎| 人妻在线网站| 激情综合网五月婷婷| 五月天 综合 在线| 一本久道综合色婷婷五月| 精品久热69| 伊人婷婷五月天| 无码成人播放器| 绿色小导航AV| 丁香婷婷激情综合五月激情| 超碰狠狠色| 天天日天天插| 丁香激情网| 久久久五月天婷婷成人网| 五月天丁香婷| 插插干干干色| 色欲午夜无码久久久久久张津瑜| 深爱激情综合| 婷婷综合国产| 狼人久草| 五月天社区狠狠| 色色色999| 中文字幕在线视频播放| 日韩成人电影在线播放| 夜夜天天久久婷婷| 99亚洲视频| 精品夜夜澡人妻无码AV| 婷婷激情在线| 亚洲99在线视频| 91avse| 丁香婷婷欧美综合| 97资源碰碰| 天天色综合网吨吧| 色色五月天婷婷| 婷婷操无码| 人妻久久久久| 九九热在线视频观看| 亚洲色色色| 97资源碰碰在线| 色综合网综合| 丁香婷婷五月| 久久99看免费| 久久66精品| 婷婷久久五月天| 色综合av超碰| www.日韩艹| 五月丁香六月激情欧美综合| 丁香五月婷婷激情中文| 5月婷婷6月丁香aV| 九九热九九| 激情骚五月| 亚洲久久婷婷| 婷婷丁香久久| www久久99| 激情五月天综合婷婷网| 超碰亚洲欧美| 五月停停直播| 91精品久久久久久综合五月天| 超碰99热在线观看| 色婷婷色情| 狠狠操天天干| 99免费综合网| 五月色丁香| 欧美婷婷精品激| WWW.夜夜| 97caop| 丁香六月 婷婷六月| 国产成人综合网| 国产九九一区二区三区| 九一99| 五月天婷婷青青草| 狠狠狠激情网| 中文成人在线| 亚洲视频在线观看99| 中文av网| 激情五月天在线观看婷婷| 丁香婷婷五月综合色情| 欧美性爱中文字幕| 狠狠摸狠狠摸| 麻豆精品| 五月婷婷激情综合av| 天堂网色婷婷| 色色亚洲五月天| 国产亚洲av片| 79精品视频在线观看,| 极品五月天| 色婷婷久久综合丁香五月| 亚洲狠狠丁香婷婷香蕉| 日韩欧美骚货| 精品九九久久| 亚洲色基地| 人妻少妇色综合| 久久久婷婷五月亚洲97号色| 国产性爱一级| 51成人| 欧美色色色色色| 久久只有精| 疯狂做受XXXX高潮A片| 五月婷婷六月丁香综合视频在线| 五月激情天| 婷婷色五月久久| 日本婷婷色| 亚洲色视频| 婷婷五月天中文字幕| 九月激情综合| www.激情五月天。com| 狠狠操综合| www.五月激情.com| 久久婷婷免费| AV操操操| 久久久久久综合88| 丁香五月成人网| 五月婷婷和六月| 国产99久| 超碰网站在线观看| 开心五月婷婷激情| 极品人妻VIDEOSSS人妻| 26UUU精品一区二区c〇m| 丁香婷婷综合色五月激情国产基地| 婷婷丁香十月| www久| 欧美日韩精品人妻狠狠躁免费视频| 五月天婷婷五月| 伊人9在线| 久久这里只有精品热在99| 欧洲亚洲欧洲99久久| 91啦丨九色丨刺激中文| 99在线视频精品| 激情六月丁香综合| 日韩aⅴ视频| 丁香五月影视| 少妇久久诱惑视频| 一区二区aV电影免费看| 四色99久久| 狠狠五月天婷婷激情网。| 日韩免费99| 可以看的av| 五月六月婷婷| www.色五月| 操精品9| 日本高清久久| 天天日天天日天天搞| 婷婷伊人综合中文字幕| 日本精品人妻无码77777| 日日操夜夜撸| 色婷婷精品小视频| 正宗黄色毛片| 欧美交换配乱吟粗大25P| 26uuu成人网| 丁香六月天AV| 婷婷六月视频| 五月日韩中文字幕| 日韩成人电影在线播放| 久久综合伊人综合在线| 性生活视频98791| 亚洲V国产V欧美V久久久久久| 五月丁香在线| 激情五月色综合国产精品| 色色色婷婷五月天| 丁香五月天日韩无码| 激情综合久久| pom538精品视频| 天天干天天射综合网| 九九精品热| 五月天婷婷色情| 1024国产在线| 丁香五月人妻| www.婷婷五月天| 激情五月天婷婷视频| 草综合网| 婷婷五月天情色| 亚洲99精品九九在线| 亚洲天堂久久| 久热人妻| 天天日天天爽| 色婷婷激情五月天| ji'qing'luan'ren'lun| 亚洲综合九九| 99久久97久久欧美综合网| 久久久久久久久月丁| 六月婷婷综合| 亚洲a色| 亚洲综合视频网| 日本VA视频| 婷婷五月天激情综合深爱| 婷婷八月激情| 青青草原亚洲天堂| 色玖玖玖| 久久精品噜噜噜成人A∨色欲| 丁香婷婷成年| 成人做爰高潮A片免费视频| 99色婷婷视频| 五月色色网| 久色激情| 久久金品黃色| 欧美丁香五月| 一级操逼内射在线视频| 五月婷在线色视频| 国产26uuu视频| www.日日日.com| 99热精品10| wwW天天干| 午夜色色色极品视频| 欧美内射AA| 色欲久久综合| 日本99久久| 丁香五月婷婷色| 丁香五月电影| 色婷婷综合网| 激情久久四色| 99 频99热国里只有精品| 79精品在线视频| 综合久久丁香婷婷,五月婷婷六月丁香,开心激情综合网,六月丁香在线观看,婷婷丁 | 色偷偷综合| 丁香五月自拍| 国产成人一区二区三区在线观看| 97五月天| 免费无码毛片一区二区A片| 日本乱子人伦在线视频| 98国产精品综合一区二区三区 | 丁香五月婷婷Av| 99热加勒比| 嫩草视频在线观看| 九九国产视频| 亚洲综合新99视频| 九九这里精品| 亚洲色婷婷五月| 99热免费观看| 狠狠色婷婷7777久| 99色色网| 成人五月丁香花| 嘿嘿视频免费看9| 五月婷婷日本| 色婷婷久久久| 熟女重口味αV| 天天色色婷婷| 婷婷淫淫狠狠六月| 色色色婷婷五月| 开心激情站| 激情图片亚洲| 五月叮香啪| 日韩无码专区| 337p午夜影院| 五月天天爽| 成人亚洲精品| 欧美性猛交99久久久久99按摩| 久草 tingting| 天天肏在线观看| 五月婷婷六月丁香激情综合网| 99er6热在线观看精品6| 激情婷婷丁香| 久久激情视频| 久久亭亭电影| 大香蕉五月天婷婷| 第一区久久网站| 五月丁香六月婷婷久久肏| 欧美激情综合色综合啪啪五月| 久热99中文字幕| 五月婷婷色综图片| 九九草热在线观看| 激情五月天偷拍综合网| 亚洲激情久久| 好大好粗嗯啊-一级黄色大片免费观看-成人AV| 午夜丁香六月婷| 99国产小视频免费观看| 婷婷亚洲欧美丁香五月| www.99热视频| 一区操| 丁香五月综合色婷婷| 在线可以看的av网址| 欧美激情综合| 色婷综合| 涩涩涩,com| 九九在线视频| 亚洲第一成人无码A片| 午夜成人网站在线观看| 天天久久综合| 成人网站在线观看视频| 一级内射毛片| 色色网站免费在线视频| 亚洲狠狠干| 成人综合网站| 日韩成人中文字幕| 亚洲另类噜噜| 久热无码| 操比激情五月综合| 99热青青草原| 久久a热| 天堂综合久| 一本综合丁香日日狠狠色| 欧美黄色AA片哗啦啦啦| 亚洲不卡123| 插少妇综合网| 伊人啪啪网| 伊人狠狠色婷婷综合丁香一区| 3www激情| 婷婷色在线观看| 99re这里有精品手机在线| 久久六月天| 2015WWW永久免费观看播放| 日韩六六久久电影| 激情小说在线视频| 任你操精品免费| 天天综合中文| 人人插操| 六月婷婷视频| 玖玖资源在线视频| 99狠狠| 99色性爰网络| 欧美日韩婷婷五月天| 婷婷五月天,影院| 尔尔AV一区| 五月婷婷六月天| 色老久久| 欧美色碰| 天天干天天干天天干天天干天天干| 色噜噜丁香| 色五月丁香一区在线| 五月婷婷丁香六月| 久久久www| 亚洲成人一区| 武则天精品久久| 伊人网碰碰| 综合激情五月婷婷| 婷婷五月天狠狠色| 丁香六月婷婷开心婷婷网| 日日操夜夜骑| 91丨九色丨国产打屁股网站| 久久欧洲综合网| 夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂亚洲亚洲亚洲亚洲亚洲亚洲亚洲亚洲色 | 黄网在线观看免费| 欧美日韩国产日本精品四虎网网站物| 99久久久国产精品免费蜜乳tv| 最新无毒无码AV| 成人网丁香五月| 午夜天堂一区人妻| 亚洲综合视频一下| 精品亚洲国产成AV人片传媒| 天色综合网站| 综合 激情 婷婷| 一本伊人色婷| 亚洲图色五月天| 婷婷性福五月天| 久久婷婷五月天蜜桃| 97精品综合|