栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

基于JavaAgent实现发布http接口

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于JavaAgent实现发布http接口

文章目录
    • 需求
    • 初步方案
    • 技术实现
      • pom文件依赖
      • 实现一个JavaAgent
      • 支持SpringBoot发布的Http接口
      • 支持DubboX发布的rest接口
      • 使用方式
    • 总结

需求

    公司运维系统想要监控服务是否正常启动,这些服务是k8s部署的,运维人员的要求业务服务提供一个http接口用于监控服务健康监测,要求所有的接口请求的URL,参数等都是相同的,这么做的目的是不需要通过规范来约束开发人员去开一个服务健康监测的接口。

    使用服务接口来检测服务我觉得相比较监控进程启动,端口监听等方式更准确一些。所以,为了满足运维同学的要求,起初想到的方案是提供一个jar,专门集成到项目中用于发布监控接口,但是想了一下,这么做需要涉及到服务的改造,我理想的方式是对应用无侵入的方式实现。

初步方案

    说到对应用无入侵,首先想到的就是javaagent技术,此前使用该技术实现了无入侵增强程序日志的工具,所以对使用javaagent已经没有问题,此时需要考虑的是如何发布接口了。

基础技术 JavaAgent

支持的技术 SpringBoot和DubboX发布的rest服务

    公司服务大致分为两类,一个是使用springboot发布的Spring MVC rest接口,另一种是基于DubboX发布的rest接口,因为公司在向服务网格转,所以按要求是去dubbo化的,没办法还是有其他小组由于一些其他原因没有或者说短期内不想进行服务改造的项目,这些项目比较老,不是springboot的,是使用spring+DubboX发布的rest服务。所以这个agent要至少能支持这两种技术。

支持SpringBoot

    想要支持SpringBoot很简单,因为SpringBoot支持自动装配,所以,我要写一个spring.factories来进行自动装配。

支持DubboX

    业务系统是传统spring+DubboX实现的,并不支持自动装配,这是个问题点,还有个问题点就是如何也发布一个DubboX的rest接口,这两个问题实际上就需要对SpringBean生命周期和Dubbo接口发布的流程有一定的了解了,这个一会儿再说。

技术实现 pom文件依赖
    
        
            org.springframework.boot
            spring-boot-starter-web
            2.3.6.RELEASE
            true
        
        
            org.springframework.boot
            spring-boot-autoconfigure
            2.3.6.RELEASE
            true
        
        
            org.springframework.boot
            spring-boot-configuration-processor
            2.3.6.RELEASE
            true
        
        
            com.alibaba
            fastjson
            1.2.70
        
        
            org.apache.zookeeper
            zookeeper
            3.4.6
            
                
                    log4j
                    log4j
                
            
        
        
            com.101tec
            zkclient
            0.7
        
        
            com.alibaba
            dubbo
            2.8.4
            
                
                    org.springframework
                    spring
                
            
        
        
            javax.ws.rs
            javax.ws.rs-api
            2.0.1
        
    
实现一个JavaAgent

    实现一个JavaAgent很容易,以下三步就可以了,这里不细说了。

  • 定义JavaAgent入口
public class PreAgent {

    public static void premain(String args, Instrumentation inst) {
        System.out.println("输入参数:" + args);
        // 通过参数控制,发布的接口是DubboX还是SpringMVC
        Args.EXPORT_DUBBOX = args;
    }
}
  • Maven打包配置
        
            
                maven-deploy-plugin
                
                    true
                
            
            
                org.apache.maven.plugins
                maven-shade-plugin
                1.4
                
                    
                        package
                        
                            shade
                        
                        
                            true
                            false
                            true
                            false
                            true

                            
                                
                                    
                                        com.ruubypay.agent.PreAgent
                                    
                                
                            
                        
                    
                
            
        
  • MANIFEST.MF编写

注:该文件在resource/meta-INF/目录下

Manifest-Version: 1.0
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Premain-Class: com.ruubypay.agent.PreAgent
支持SpringBoot发布的Http接口
  • 编写Controller

    接口很简单就发布一个get接口,响应pong即可。

@RestController
public class PingServiceController {

    @GetMapping(value = "/agentServer/ping")
    public String ping() {
        return "pong";
    }
}
  • 创建spring.factories

    通过这个配置文件可以实现SpringBoot自动装配,这里不细说SpringBoot自动装配的原理了,该文件的配置内容就是要自动装配的Bean的全路径,代码如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
  com.ruubypay.config.WebConfiguration
  • WebConfiguration配置类

    这个配置配置类很简单,@Configuration声明这是个配置类,@ComponentScan扫描包。

@Configuration
@ComponentScan(value = "com.ruubypay")
public class WebConfiguration {
}
支持DubboX发布的rest接口
  • 定义API

    使用的是DubboX发布rest接口需要javax.ws.rs包的注解,@Produces({ContentType.APPLICATION_JSON_UTF_8})声明序列化方式,@Pathrest接口的路径,@GET声明为get接口。

@Produces({ContentType.APPLICATION_JSON_UTF_8})
@Path("/agentServer")
public interface IPingService {

    
    @GET
    @Path("/ping")
    String ping();
}
  • 编写API实现类
@Component("IPingService")
public class IPingServiceImpl implements IPingService {

    @Override
    public String ping() {
        return "pong";
    }
}
  • 实现发布Dubbo接口

    如何实现发布接口是实现的难点;首先程序并不支持自动装配了,我们就要考虑如何获取到Spring上下文,如果能够注册Bean到Spring容器中,如何触发发布Dubbo接口等问题。

Spring上下文获取及注册Bean到Spring容器中

    触发Bean注册,获取Spring上下文我们通过Spring的Aware接口可以实现,我这里使用的是ApplicationContextAware;注册Bean到Spring容器中可以使用BeanDefinition先创建Bean然后使用DefaultListableBeanFactory的registerBeanDefinition将BeanDefinition注册到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,不用发布接口
        if (DUBBOX.equals(Args.EXPORT_DUBBOX)) {
            // 注册配置Bean WebConfiguration
            webConfiguration();
            // 发布DubboX接口
            exportDubboxService();
        }
    }

    public void webConfiguration() {
        System.out.println("创建WebConfiguration的bean");
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory listableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getAutowireCapableBeanFactory();
        // 创建WebConfiguration的bean
        BeanDefinition webConfigurationBeanDefinition = new RootBeanDefinition(WebConfiguration.class);
        // 注册到集合beanFactory中
        System.out.println("注册到集合beanFactory中");
        listableBeanFactory.registerBeanDefinition(WebConfiguration.class.getName(), webConfigurationBeanDefinition);
    }

}

发布Dubbo接口

    通过ApplicationContextAware我们已经能够获取Spring上下文了,也就是说应用程序的Dubbo注册中心,发布接口协议,Dubbo Application等配置都已经存在Spring容器中了,我们只要拿过来使用即可,拿过来使用没问题,我们接下来就需要考虑,如何发布接口,这需要对Dubbo服务发布的流程有一定的了解,这里我不细说了,感兴趣的可以自己了解下,或者看我以前发布的文章;

    首先Dubbo接口的Provider端的核心Bean是com.alibaba.dubbo.config.spring.ServiceBean,使用Spring配置文件中的标签

    这里需要的对象直接通过依赖查找的方式从Spring容器获取就可以了 ApplicationConfig,ProtocolConfig,RegistryConfig,IPingService。

    public void exportDubboxService() {
        try {
            System.out.println("开始发布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);
            // 创建ServiceBean
            ServiceBean 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");
            // 发布dubbo接口
            serviceBean.export();
            System.out.println("dubbo接口发布完毕");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
使用方式
  1. DubboX: java -javaagent:ruubypay-ping-agent.jar=1 -jar 服务jar包
  2. springboot的http接口:java -javaagent:ruubypay-ping-agent.jar -jar 服务jar包
总结

    这个工具实现起来不复杂,总也就六个类和一个接口,但其实实现其能力所涉及的支持还是比较考验对框架的理解的,比如Spring生命周期,DubboX发布接口的流程以及实现一个最简单的JavaAgent的方式。

    另外也欢迎指正错误,如果有更好的实现方式也欢迎交流。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/450756.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号