• 聊聊arthas的spring-boot-starter


    本文主要研究一下arthas的spring-boot-starter

    ArthasConfiguration

    arthas-spring-boot-starter/src/main/java/com/alibaba/arthas/spring/ArthasConfiguration.java

    @ConditionalOnProperty(name = "spring.arthas.enabled", matchIfMissing = true)
    @EnableConfigurationProperties({ ArthasProperties.class })
    public class ArthasConfiguration {
    	private static final Logger logger = LoggerFactory.getLogger(ArthasConfiguration.class);
    
    	@Autowired
    	ConfigurableEnvironment environment;
    
    	/**
    	 * 
    	 * 1. 提取所有以 arthas.* 开头的配置项,再统一转换为Arthas配置
    	 * 2. 避免某些配置在新版本里支持,但在ArthasProperties里没有配置的情况。
    	 * 
    */ @ConfigurationProperties(prefix = "arthas") @ConditionalOnMissingBean(name="arthasConfigMap") @Bean public HashMap arthasConfigMap() { return new HashMap(); } @ConditionalOnMissingBean @Bean public ArthasAgent arthasAgent(@Autowired @Qualifier("arthasConfigMap") Map arthasConfigMap, @Autowired ArthasProperties arthasProperties) throws Throwable { arthasConfigMap = StringUtils.removeDashKey(arthasConfigMap); ArthasProperties.updateArthasConfigMapDefaultValue(arthasConfigMap); /** * @see org.springframework.boot.context.ContextIdApplicationContextInitializer#getApplicationId(ConfigurableEnvironment) */ String appName = environment.getProperty("spring.application.name"); if (arthasConfigMap.get("appName") == null && appName != null) { arthasConfigMap.put("appName", appName); } // 给配置全加上前缀 Map mapWithPrefix = new HashMap(arthasConfigMap.size()); for (Entry entry : arthasConfigMap.entrySet()) { mapWithPrefix.put("arthas." + entry.getKey(), entry.getValue()); } final ArthasAgent arthasAgent = new ArthasAgent(mapWithPrefix, arthasProperties.getHome(), arthasProperties.isSlientInit(), null); arthasAgent.init(); logger.info("Arthas agent start success."); return arthasAgent; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    ArthasConfiguration注册了arthasConfigMap及arthasAgent两个bean

    ArthasAgent

    arthas-agent-attach/src/main/java/com/taobao/arthas/agent/attach/ArthasAgent.java

    public class ArthasAgent {
        private static final int TEMP_DIR_ATTEMPTS = 10000;
    
        private static final String ARTHAS_CORE_JAR = "arthas-core.jar";
        private static final String ARTHAS_BOOTSTRAP = "com.taobao.arthas.core.server.ArthasBootstrap";
        private static final String GET_INSTANCE = "getInstance";
        private static final String IS_BIND = "isBind";
    
        private String errorMessage;
    
        private Map configMap = new HashMap();
        private String arthasHome;
        private boolean slientInit;
        private Instrumentation instrumentation;
    
        public ArthasAgent() {
            this(null, null, false, null);
        }
    
        //......
    
        public void init() throws IllegalStateException {
            // 尝试判断arthas是否已在运行,如果是的话,直接就退出
            try {
                Class.forName("java.arthas.SpyAPI"); // 加载不到会抛异常
                if (SpyAPI.isInited()) {
                    return;
                }
            } catch (Throwable e) {
                // ignore
            }
    
            try {
                if (instrumentation == null) {
                    instrumentation = ByteBuddyAgent.install();
                }
    
                // 检查 arthasHome
                if (arthasHome == null || arthasHome.trim().isEmpty()) {
                    // 解压出 arthasHome
                    URL coreJarUrl = this.getClass().getClassLoader().getResource("arthas-bin.zip");
                    if (coreJarUrl != null) {
                        File tempArthasDir = createTempDir();
                        ZipUtil.unpack(coreJarUrl.openStream(), tempArthasDir);
                        arthasHome = tempArthasDir.getAbsolutePath();
                    } else {
                        throw new IllegalArgumentException("can not getResources arthas-bin.zip from classloader: "
                                + this.getClass().getClassLoader());
                    }
                }
    
                // find arthas-core.jar
                File arthasCoreJarFile = new File(arthasHome, ARTHAS_CORE_JAR);
                if (!arthasCoreJarFile.exists()) {
                    throw new IllegalStateException("can not find arthas-core.jar under arthasHome: " + arthasHome);
                }
                AttachArthasClassloader arthasClassLoader = new AttachArthasClassloader(
                        new URL[] { arthasCoreJarFile.toURI().toURL() });
    
                /**
                 * 
                 * ArthasBootstrap bootstrap = ArthasBootstrap.getInstance(inst);
                 * 
    */ Class bootstrapClass = arthasClassLoader.loadClass(ARTHAS_BOOTSTRAP); Object bootstrap = bootstrapClass.getMethod(GET_INSTANCE, Instrumentation.class, Map.class).invoke(null, instrumentation, configMap); boolean isBind = (Boolean) bootstrapClass.getMethod(IS_BIND).invoke(bootstrap); if (!isBind) { String errorMsg = "Arthas server port binding failed! Please check $HOME/logs/arthas/arthas.log for more details."; throw new RuntimeException(errorMsg); } } catch (Throwable e) { errorMessage = e.getMessage(); if (!slientInit) { throw new IllegalStateException(e); } } } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    ArthasAgent的init方法先尝试加载java.arthas.SpyAPI,若SpyAPI.isInited()为true则直接返回;之后执行ByteBuddyAgent.install();对于arthasHome为null则尝试读取arthas-bin.zip文件,接着创建AttachArthasClassloader,加载com.taobao.arthas.core.server.ArthasBootstrap,执行其getInstance方法,再对实例执行isBind

    ArthasEndPointAutoConfiguration

    arthas-spring-boot-starter/src/main/java/com/alibaba/arthas/spring/endpoints/ArthasEndPointAutoConfiguration.java

    @ConditionalOnProperty(name = "spring.arthas.enabled", matchIfMissing = true)
    public class ArthasEndPointAutoConfiguration {
    
    	@Bean
    	@ConditionalOnMissingBean
    	@ConditionalOnAvailableEndpoint
    	public ArthasEndPoint arthasEndPoint() {
    		return new ArthasEndPoint();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ArthasEndPointAutoConfiguration则创建ArthasEndPoint

    ArthasEndPoint

    arthas-spring-boot-starter/src/main/java/com/alibaba/arthas/spring/endpoints/ArthasEndPoint.java

    @Endpoint(id = "arthas")
    public class ArthasEndPoint {
    
    	@Autowired(required = false)
    	private ArthasAgent arthasAgent;
    
    	@Autowired(required = false)
    	private HashMap arthasConfigMap;
    
    	@ReadOperation
    	public Map invoke() {
    		Map result = new HashMap();
    
    		if (arthasConfigMap != null) {
    			result.put("arthasConfigMap", arthasConfigMap);
    		}
    
    		String errorMessage = arthasAgent.getErrorMessage();
    		if (errorMessage != null) {
    			result.put("errorMessage", errorMessage);
    		}
    
    		return result;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    ArthasEndPoint提供了一个读方法返回arthasConfigMap

    小结

    arthas的spring-boot-starter有两个自动配置,分别是ArthasConfiguration及ArthasEndPointAutoConfiguration,其中ArthasConfiguration注册了arthasConfigMap及arthasAgent两个bean,而ArthasEndPointAutoConfiguration则创建ArthasEndPoint。

  • 相关阅读:
    根据二叉树创建字符串
    c语言练习92:链表的中间结点
    某网站自动下载音乐mp3和歌词 离线音乐
    【EasyRL学习笔记】第四章 Policy Gradient 策略梯度
    DailyPractice.2023.10.19
    layui table表格使用table.resize()方法 重置表格尺寸
    基于Alexnet深度学习网络的人员口罩识别算法matlab仿真
    L2-032 彩虹瓶
    49 html鼠标事件(在线测试)
    选择排序超详细讲解C语言
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/136162640