【Arthas 专题篇. 番外篇 一 tunnel-server以及产品化】Arthas tunnel web管控微服务项目

本文介绍了Arthas Tunnel Server的基础使用,包括通过agent方式添加探针、配置Java VM OPTIONS、Springboot集成及非Springboot项目的注入。此外,文章探讨了tunnel-server的集群监控和产品化需求,如权限控制、代码操作及服务性能告警等功能。
摘要由CSDN通过智能技术生成

一. tunnel的基础使用

tunnel 通过使用server/client管理不同机器的JVM进程。


1.1 使用agent方式,添加arthas探针。

tunnel-server 是管理agentId的方式,先要认识如何通过agent运行项目。

1.1.1 配置java VM OPTIONS

全量arthas的下载地址

java -javaagent:/tmp/arthas-agent.jar -jar demo.jar

运行后会把项目的类信息通过ArthasClassloader 加载到内存中,AgentBootstrap提供监听线程获取类信息。

1.1.2 springboot-starter 注入

现在使用的是3.6.3版本,因为该版本开始添加了用户权限控制,这个方式更适合springboot项目

<dependency>
    <groupId>com.github.hiwepy</groupId>
    <artifactId>redisson-plus-spring-boot-starter</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

当使用starter包要配置,访问地址,有两种方式

1.1.2.1 使用yaml配置
arthas:
  # 通过http访问的端口
  http-port: 8987
  # 通过telnet访问的端口
  telnet-port: 6736
  session-timeout: 2000
  # 绑定的ip
  ip: 0.0.0.0

且可以用到redis存储管理tunnel-server信息

<dependency>
    <groupId>com.zengtengpeng</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>1.0.12</version>
</dependency>

springboot注入信息配置

import com.alibaba.arthas.spring.ArthasProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.SocketUtils;

import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @Author: eliooyang
 */
@Slf4j
@Configuration
@ConditionalOnClass(value = ArthasProperties.class)
public class ArthasConfigMapConfig {

    @Value("${spring.name:default_null}")
    private String serviceName;

    @Value("${server.port:8080}")
    private String serverPort;

    @Autowired
    private Environment environment;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Bean("arthasConfigMap")
    public Map<String, String> arthasConfigMap(@Autowired ArthasProperties arthasProperties) {
        Map<String, String> map = new HashMap<>(8);

        // 接收环境变量参数,否则随机生成
        String agentId = environment.getProperty("arthas.agentId");
        //优先使用环境变量arthas.name,其次使用服务名+随机数
        if (StringUtils.isEmpty(agentId)) {
            Random secureRandom = new SecureRandom();
            agentId = serviceName + ":" + secureRandom.nextInt(1000);
        }
        map.put("agent-id", agentId);

        //优先从配置中获取tunnel-server,如果没有,则从redis中获取,如果redis没有则使用默认
        String tunnelServer = arthasProperties.getTunnelServer();
        if (tunnelServer == null) {
            String tunnelServerKey = "arthas.tunnel-server:" + agentId;
            tunnelServer = redisTemplate.opsForValue().get(tunnelServerKey);
            if (tunnelServer == null) {
                tunnelServer = "ws://127.0.0.1:7777/ws";
                redisTemplate.opsForValue().set(tunnelServerKey, tunnelServer);
            }
        }
        map.put("tunnel-server", tunnelServer);

        Integer serverPortInt = null;
        if (StringUtils.isNotBlank(serverPort)) {
            serverPortInt = Integer.parseInt(serverPort);
        }

        // 优先从环境变量中获取,其次从配置文件中获取,否则为serverPort+1,否则随机(值为0),若值为-1则不监听端口
        String httpPort = environment.getProperty("arthas.httpPort");
        if (httpPort == null) {
            if (arthasProperties.getHttpPort() == 0) {
                if (serverPortInt != null) {
                    map.put("http-port", "" + (serverPortInt + 1));
                } else {
                    map.put("http-port", "" + SocketUtils.findAvailableTcpPort());
                }
            } else {
                map.put("http-port", "" + arthasProperties.getHttpPort());
            }
        } else {
            map.put("http-port", httpPort);
        }
        // 优先读取环境变量接口
        String telnetPort = environment.getProperty("arthas.telnetPort");

        if (StringUtils.isEmpty(telnetPort)) {
            if (arthasProperties.getTelnetPort() == 0) {
                if (serverPortInt != null) {
                    map.put("telnet-port", "" + (serverPortInt + 2));
                } else {
                    map.put("telnet-port", "" + SocketUtils.findAvailableTcpPort());
                }
            } else {
                map.put("telnet-port", "" + arthasProperties.getHttpPort());
            }
        } else {
            map.put("telnet-port", telnetPort);
        }
        // 如果有配置target-ip,那么使用,否则默认127.0.0.1
        if (StringUtils.isNotBlank(arthasProperties.getIp())) {
            map.put("ip", arthasProperties.getIp());
        }
        // 鉴权用的用户名,默认arthas,targetIp非127.0.0.1才生效
        if (StringUtils.isNotBlank(arthasProperties.getUsername())) {
            map.put("username", arthasProperties.getUsername());
        } else {
            map.put("username", "username");
        }
        log.debug("username:{}", map.get("username"));

        // 鉴权用的密码,targetIp非127.0.0.1才生效
        if (StringUtils.isNotBlank(arthasProperties.getPassword())) {
            map.put("password", arthasProperties.getPassword());
        } else {
            map.put("password", "pwd");
        }

        // 失效命令,设置为空,为了不禁用stop命令
        map.put("disabledCommands", "");
        log.info("server info:{}", map);
        return map;
    }
}

可以通过访问:127.0.0.1:8563 自己定义的端口,在浏览器访问,主要是为了提供tunnel-server服务给到管理
在这里插入图片描述

1.1.2 非springboot的Java项目,注入方式
<dependency>
     <groupId>com.taobao.arthas</groupId>
     <artifactId>arthas-agent-attach</artifactId>
     <version>${arthas.version}</version>
 </dependency>
 <dependency>
     <groupId>com.taobao.arthas</groupId>
     <artifactId>arthas-packaging</artifactId>
     <version>${arthas.version}</version>
 </dependency>

1.2 运行 tunnel-server

tunnel-server下载

java -jar  arthas-tunnel-server.jar

默认情况下,arthas tunnel server 的 web 端口是8080,arthas agent 连接的端口是7777。启动后访问 http://127.0.0.1:8080,通过 agentId 连接到已注册的

1.2.1 tunnel-server 链接方式
1.2.1.1 sh方式,需要安装telnet

指定ws链接方式

as.sh --tunnel-server 'ws://127.0.0.1:7777/ws' --app-name xxx

可以通过 --agent-id 指定对应的探针

./as.sh --tunnel-server --agent-id <agentId>
1.2.2 集群内指定服务监控

tunnel-server 调用流程,可以通过redis统一管理ip+port信息,如果有服务粒度的划分,根据需求进行细化。
在这里插入图片描述

二. tunnel-server-web 产品化

2.1 需求脑爆
  1. 应用agentId同步到redis中,生命周期:正常->不可用->下线。不可用状态主要针对一些已经故障的应用。
  2. 应用的agent端口的占用问题,服务下线,端口占用取消,arthas会有线程持续运行着,需要优化。
  3. tunnel-server端对agent的管理需要有权限控制。
  4. 支持编译代码功能,以及代码回滚
  5. 服务性能监听与告警,设置告警策略与等级,告警巡检形式,同步信息形式。
  6. 等等…

注: 项目还在编码,后续分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霸道产品爱上我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值