最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaAgent實(shí)現(xiàn)http接口發(fā)布方式淺析

 更新時(shí)間:2023年03月02日 11:19:11   作者:Redick01  
這篇文章主要介紹了JavaAgent實(shí)現(xiàn)http接口發(fā)布方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧

需求

公司運(yùn)維系統(tǒng)想要監(jiān)控服務(wù)是否正常啟動(dòng),這些服務(wù)是k8s部署的,運(yùn)維人員的要求業(yè)務(wù)服務(wù)提供一個(gè)http接口用于監(jiān)控服務(wù)健康監(jiān)測(cè),要求所有的接口請(qǐng)求的URL,參數(shù)等都是相同的,這么做的目的是不需要通過(guò)規(guī)范來(lái)約束開(kāi)發(fā)人員去開(kāi)一個(gè)服務(wù)健康監(jiān)測(cè)的接口。

使用服務(wù)接口來(lái)檢測(cè)服務(wù)我覺(jué)得相比較監(jiān)控進(jìn)程啟動(dòng),端口監(jiān)聽(tīng)等方式更準(zhǔn)確一些。所以,為了滿足運(yùn)維同學(xué)的要求,起初想到的方案是提供一個(gè)jar,專門集成到項(xiàng)目中用于發(fā)布監(jiān)控接口,但是想了一下,這么做需要涉及到服務(wù)的改造,我理想的方式是對(duì)應(yīng)用無(wú)侵入的方式實(shí)現(xiàn)。

初步方案

說(shuō)到對(duì)應(yīng)用無(wú)入侵,首先想到的就是javaagent技術(shù),此前使用該技術(shù)實(shí)現(xiàn)了無(wú)入侵增強(qiáng)程序日志的工具,所以對(duì)使用javaagent已經(jīng)沒(méi)有問(wèn)題,此時(shí)需要考慮的是如何發(fā)布接口了。

基礎(chǔ)技術(shù) JavaAgent

支持的技術(shù) SpringBoot和DubboX發(fā)布的rest服務(wù)

公司服務(wù)大致分為兩類,一個(gè)是使用springboot發(fā)布的Spring MVC rest接口,另一種是基于DubboX發(fā)布的rest接口,因?yàn)楣驹谙蚍?wù)網(wǎng)格轉(zhuǎn),所以按要求是去dubbo化的,沒(méi)辦法還是有其他小組由于一些其他原因沒(méi)有或者說(shuō)短期內(nèi)不想進(jìn)行服務(wù)改造的項(xiàng)目,這些項(xiàng)目比較老,不是springboot的,是使用spring+DubboX發(fā)布的rest服務(wù)。所以這個(gè)agent要至少能支持這兩種技術(shù)。

支持SpringBoot

想要支持SpringBoot很簡(jiǎn)單,因?yàn)镾pringBoot支持自動(dòng)裝配,所以,我要寫一個(gè)spring.factories來(lái)進(jìn)行自動(dòng)裝配。

支持DubboX

業(yè)務(wù)系統(tǒng)是傳統(tǒng)spring+DubboX實(shí)現(xiàn)的,并不支持自動(dòng)裝配,這是個(gè)問(wèn)題點(diǎn),還有個(gè)問(wèn)題點(diǎn)就是如何也發(fā)布一個(gè)DubboX的rest接口,這兩個(gè)問(wèn)題實(shí)際上就需要對(duì)SpringBean生命周期和Dubbo接口發(fā)布的流程有一定的了解了,這個(gè)一會(huì)兒再說(shuō)。

技術(shù)實(shí)現(xiàn)

pom文件依賴

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.6.RELEASE</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.3.6.RELEASE</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>2.3.6.RELEASE</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <exclusions>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.7</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.8.4</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.0.1</version>
        </dependency>
    </dependencies>

實(shí)現(xiàn)一個(gè)JavaAgent

實(shí)現(xiàn)一個(gè)JavaAgent很容易,以下三步就可以了,這里不細(xì)說(shuō)了。

定義JavaAgent入口

public class PreAgent {
    public static void premain(String args, Instrumentation inst) {
        System.out.println("輸入?yún)?shù):" + args);
        // 通過(guò)參數(shù)控制,發(fā)布的接口是DubboX還是SpringMVC
        Args.EXPORT_DUBBOX = args;
    }
}

Maven打包配置

        <plugins>
            <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>1.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
                            <promoteTransitiveDependencies>false</promoteTransitiveDependencies>
                            <createDependencyReducedPom>true</createDependencyReducedPom>
                            <minimizeJar>false</minimizeJar>
                            <createSourcesJar>true</createSourcesJar>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Premain-Class>com.ruubypay.agent.PreAgent</Premain-Class>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>

MANIFEST.MF編寫

注:該文件在resource/META-INF/目錄下

Manifest-Version: 1.0
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Premain-Class: com.ruubypay.agent.PreAgent

支持SpringBoot發(fā)布的Http接口

編寫Controller

接口很簡(jiǎn)單就發(fā)布一個(gè)get接口,響應(yīng)pong即可。

@RestController
public class PingServiceController {
    @GetMapping(value = "/agentServer/ping")
    public String ping() {
        return "pong";
    }
}

創(chuàng)建spring.factories

通過(guò)這個(gè)配置文件可以實(shí)現(xiàn)SpringBoot自動(dòng)裝配,這里不細(xì)說(shuō)SpringBoot自動(dòng)裝配的原理了,該文件的配置內(nèi)容就是要自動(dòng)裝配的Bean的全路徑,代碼如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.ruubypay.config.WebConfiguration

WebConfiguration配置類

這個(gè)配置配置類很簡(jiǎn)單,@Configuration聲明這是個(gè)配置類,@ComponentScan掃描包。

@Configuration
@ComponentScan(value = "com.ruubypay")
public class WebConfiguration {
}

支持DubboX發(fā)布的rest接口

定義API

使用的是DubboX發(fā)布rest接口需要javax.ws.rs包的注解,@Produces({ContentType.APPLICATION_JSON_UTF_8})聲明序列化方式,@Pathrest接口的路徑,@GET聲明為get接口。

@Produces({ContentType.APPLICATION_JSON_UTF_8})
@Path("/agentServer")
public interface IPingService {
    /**
     * ping接口
     * @return
     */
    @GET
    @Path("/ping")
    String ping();
}

編寫API實(shí)現(xiàn)類

@Component("IPingService")
public class IPingServiceImpl implements IPingService {
    @Override
    public String ping() {
        return "pong";
    }
}

實(shí)現(xiàn)發(fā)布Dubbo接口

如何實(shí)現(xiàn)發(fā)布接口是實(shí)現(xiàn)的難點(diǎn);首先程序并不支持自動(dòng)裝配了,我們就要考慮如何獲取到Spring上下文,如果能夠注冊(cè)BeanSpring容器中,如何觸發(fā)發(fā)布Dubbo接口等問(wèn)題。

Spring上下文獲取及注冊(cè)Bean到Spring容器中

觸發(fā)Bean注冊(cè),獲取Spring上下文我們通過(guò)Spring的Aware接口可以實(shí)現(xiàn),我這里使用的是ApplicationContextAware;注冊(cè)BeanSpring容器中可以使用BeanDefinition先創(chuàng)建Bean然后使用DefaultListableBeanFactoryregisterBeanDefinitionBeanDefinition注冊(cè)到Spring上下文中。

@Component
public class AgentAware implements ApplicationContextAware {
    private static final String DUBBOX = "1";
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        // 如果不是DubboX,不用發(fā)布接口
        if (DUBBOX.equals(Args.EXPORT_DUBBOX)) {
            // 注冊(cè)配置Bean WebConfiguration
            webConfiguration();
            // 發(fā)布DubboX接口
            exportDubboxService();
        }
    }
    public void webConfiguration() {
        System.out.println("創(chuàng)建WebConfiguration的bean");
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory listableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getAutowireCapableBeanFactory();
        // 創(chuàng)建WebConfiguration的bean
        BeanDefinition webConfigurationBeanDefinition = new RootBeanDefinition(WebConfiguration.class);
        // 注冊(cè)到集合beanFactory中
        System.out.println("注冊(cè)到集合beanFactory中");
        listableBeanFactory.registerBeanDefinition(WebConfiguration.class.getName(), webConfigurationBeanDefinition);
    }
}

發(fā)布Dubbo接口

通過(guò)ApplicationContextAware我們已經(jīng)能夠獲取Spring上下文了,也就是說(shuō)應(yīng)用程序的Dubbo注冊(cè)中心,發(fā)布接口協(xié)議,Dubbo Application等配置都已經(jīng)存在Spring容器中了,我們只要拿過(guò)來(lái)使用即可,拿過(guò)來(lái)使用沒(méi)問(wèn)題,我們接下來(lái)就需要考慮,如何發(fā)布接口,這需要對(duì)Dubbo服務(wù)發(fā)布的流程有一定的了解,這里我不細(xì)說(shuō)了,感興趣的可以自己了解下,或者看我以前發(fā)布的文章;

首先Dubbo接口的Provider端的核心Bean是com.alibaba.dubbo.config.spring.ServiceBean,使用Spring配置文件中的標(biāo)簽<dubbo:service標(biāo)簽生成的Bean就是ServiceBean,所以,這里我們只需要?jiǎng)?chuàng)建ServiceBean對(duì)象并且初始化對(duì)象中的必要數(shù)據(jù),然后調(diào)用ServiceBean#export()方法就可以發(fā)布Dubbo服務(wù)了。

這里需要的對(duì)象直接通過(guò)依賴查找的方式從Spring容器獲取就可以了 ApplicationConfig,ProtocolConfig,RegistryConfig,IPingService。

    public void exportDubboxService() {
        try {
            System.out.println("開(kāi)始發(fā)布dubbo接口");
            // 獲取ApplicationConfig
            ApplicationConfig applicationConfig = applicationContext.getBean(ApplicationConfig.class);
            // 獲取ProtocolConfig
            ProtocolConfig protocolConfig = applicationContext.getBean(ProtocolConfig.class);
            // 獲取RegistryConfig
            RegistryConfig registryConfig = applicationContext.getBean(RegistryConfig.class);
            // 獲取IPingService接口
            IPingService iPingService = applicationContext.getBean(IPingService.class);
            // 創(chuàng)建ServiceBean
            ServiceBean<IPingService> serviceBean = new ServiceBean<>();
            serviceBean.setApplicationContext(applicationContext);
            serviceBean.setInterface("com.ruubypay.api.IPingService");
            serviceBean.setApplication(applicationConfig);
            serviceBean.setProtocol(protocolConfig);
            serviceBean.setRegistry(registryConfig);
            serviceBean.setRef(iPingService);
            serviceBean.setTimeout(12000);
            serviceBean.setVersion("1.0.0");
            serviceBean.setOwner("rubby");
            // 發(fā)布dubbo接口
            serviceBean.export();
            System.out.println("dubbo接口發(fā)布完畢");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

使用方式

  • DubboX: java -javaagent:ruubypay-ping-agent.jar=1 -jar 服務(wù)jar包
  • springboot的http接口:java -javaagent:ruubypay-ping-agent.jar -jar 服務(wù)jar包

總結(jié)

這個(gè)工具實(shí)現(xiàn)起來(lái)不復(fù)雜,總也就六個(gè)類和一個(gè)接口,但其實(shí)實(shí)現(xiàn)其能力所涉及的支持還是比較考驗(yàn)對(duì)框架的理解的,比如Spring生命周期,DubboX發(fā)布接口的流程以及實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的JavaAgent的方式。

到此這篇關(guān)于JavaAgent實(shí)現(xiàn)http接口發(fā)布方式淺析的文章就介紹到這了,更多相關(guān)JavaAgent http接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis核心源碼深度剖析SQL語(yǔ)句執(zhí)行過(guò)程

    MyBatis核心源碼深度剖析SQL語(yǔ)句執(zhí)行過(guò)程

    這篇文章主要介紹了MyBatis核心源碼深度剖析SQL執(zhí)行過(guò)程,mybatis執(zhí)行SQL的流程都是根據(jù)statement字符串從configuration中獲取對(duì)應(yīng)的mappedStatement,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2022-05-05
  • Java語(yǔ)言Consistent Hash算法學(xué)習(xí)筆記(代碼示例)

    Java語(yǔ)言Consistent Hash算法學(xué)習(xí)筆記(代碼示例)

    這篇文章主要介紹了Java語(yǔ)言Consistent Hash算法學(xué)習(xí)筆記(代碼示例),分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • 為什么不建議使用Java自定義Object作為HashMap的key

    為什么不建議使用Java自定義Object作為HashMap的key

    這篇文章主要介紹了為什么不建議使用Java自定義Object作為HashMap的key,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-06-06
  • idea中springboot項(xiàng)目連接數(shù)據(jù)庫(kù)報(bào)錯(cuò)的原因解析

    idea中springboot項(xiàng)目連接數(shù)據(jù)庫(kù)報(bào)錯(cuò)的原因解析

    這篇文章主要介紹了idea中springboot項(xiàng)目連接數(shù)據(jù)庫(kù)報(bào)錯(cuò)的原因解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Spring定時(shí)任務(wù)注解@Scheduled詳解

    Spring定時(shí)任務(wù)注解@Scheduled詳解

    這篇文章主要介紹了Spring定時(shí)任務(wù)注解@Scheduled詳解,@Scheduled注解是包org.springframework.scheduling.annotation中的一個(gè)注解,主要是用來(lái)開(kāi)啟定時(shí)任務(wù),本文提供了部分實(shí)現(xiàn)代碼與思路,需要的朋友可以參考下
    2023-09-09
  • Java 排序算法整合(冒泡,快速,希爾,拓?fù)?,歸并)

    Java 排序算法整合(冒泡,快速,希爾,拓?fù)?,歸并)

    這篇文章主要介紹了Java 排序算法整合(冒泡,快速,希爾,拓?fù)洌瑲w并),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • MyBatis-Plus如何實(shí)現(xiàn)自動(dòng)加密解密

    MyBatis-Plus如何實(shí)現(xiàn)自動(dòng)加密解密

    這篇文章主要介紹了MyBatis-Plus實(shí)現(xiàn)自動(dòng)加密解密方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Android開(kāi)發(fā)在輪播圖片上加入點(diǎn)擊事件的方法

    Android開(kāi)發(fā)在輪播圖片上加入點(diǎn)擊事件的方法

    這篇文章主要介紹了Android開(kāi)發(fā)在輪播圖片上加入點(diǎn)擊事件的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11
  • Java中ArrayList集合的常用方法大全

    Java中ArrayList集合的常用方法大全

    這篇文章主要給大家介紹了關(guān)于Java中ArrayList集合的常用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 談?wù)凥ashmap的容量為什么是2的冪次問(wèn)題

    談?wù)凥ashmap的容量為什么是2的冪次問(wèn)題

    這篇文章主要介紹了談?wù)凥ashmap的容量為什么是2的冪次問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09

最新評(píng)論

广元市| 泗阳县| 博野县| 永新县| 桃园县| 衡东县| 吉林省| 绥江县| 孝义市| 双牌县| 道真| 公安县| 东海县| 天等县| 庄浪县| 云安县| 榆中县| 成安县| 通许县| 楚雄市| 克什克腾旗| 焦作市| 汨罗市| 威远县| 福贡县| 屏东市| 长泰县| 渝中区| 双柏县| 泰兴市| 大洼县| 吐鲁番市| 军事| 紫阳县| 当阳市| 温州市| 成安县| 宜城市| 扎赉特旗| 阿合奇县| 龙州县|