Skip to content

Commit

Permalink
refactor: add native-agent-proxy、rename native-agent-server to native…
Browse files Browse the repository at this point in the history
…-agent-management-web and rename native-agent-client to native-agent
  • Loading branch information
flzj-kl committed Oct 22, 2024
1 parent cd87438 commit 8f285b9
Show file tree
Hide file tree
Showing 92 changed files with 1,711 additions and 452 deletions.
80 changes: 80 additions & 0 deletions cluster-management/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

## Arthas Native Agent - 集群管理

![](images/cluster_management.png)

# 快速开始

## 启动native-agent
native-agent,启动在需要动态attach的服务器上
启动参数

| 参数 | 必填 | 解释 |
|----------------------|-----|-------------------------------------|
| http-port | N | http端口 ,默认2671 |
| ws-port | N | ws端口,默认2672 |
| registration-typ | Y | 注册中心类型(目前实现的有etcd和zookeeper,推荐etcd) |
| registration-address | Y | 注册中心的地址 |

example:
```shell
java -jar native-agent.jar --ip 164.196.97.123 --http-port 2671 --ws-port 2672 --registration-type etcd --registration-address 164.196.97.123:2379
```

## 启动native-agent-proxy
做为native-agent和native-agent-management-web的网络中转

| 参数 | 必填 | 解释 |
|---------------------------------|-----|------------------------------------------------------------------|
| port | N | http/ws端口 ,默认2233 |
| ip | Y | proxy的ip |
| management-registration-type | Y | native-agent-manangement-web的注册中心类型(目前实现的有etcd和zookeeper,推荐etcd) |
| management-registration-address | Y | native-agent-manangement-webd的注册中心地址 |
| agent-registration-type | Y | native-agent的注册中心类型(目前实现的有etcd和zookeeper,推荐etcd) |
| agent-registration-address | Y | native-agent的注册中心地址 |


example:
```shell
java -jar native-agent-proxy.jar --ip 164.196.97.123 --management-registration-type etcd --management-registration-address 164.196.97.123:2379 --agent-registration-type etcd --agent-registration-address 164.196.97.123:2379
```

## 启动native-agent-management-web
native-agent的管理页面

| 参数 | 必填 | 解释 |
|----------------------|-----|-------------------------------------|
| port | N | http端口 ,默认3939 |
| registration-typ | Y | 注册中心类型(目前实现的有etcd和zookeeper,推荐etcd) |
| registration-address | Y | 注册中心的地址 |


example:
```shell
java -jar native-agent-management-web.jar --registration-type etcd --registration-address 164.196.97.123:2379
```


## 监控指定JVM
进入native-agent-server管理页面,点击VIEW JAVA PROCESS INFO 按钮,可以查看到当前服务器上的Java进程
![](images/native_agent_list.png)
进入到Java进程页后,我们可以点击Monitor按钮,Monitor目标Java进程
![](images/native_agent_java_process_page.png)
之后点击MONITOR按钮就可以进入到监控界面了
![](images/native_agent_moniotr_page.png)

# 扩展注册中心
目前实现的有zookeeper和etcd,如果想要扩展注册中心,可以看看下面的实现。下面演示的是native-agent-management-web的扩展,其他也是同样的道理。

需要实现com.alibaba.arthas.nat.agent.management.web.discovery.NativeAgentProxyDiscovery接口,并在META-INF/arthas/com.alibaba.arthas.native.agent.management.web.NativeAgentProxyDiscoveryFactory 添加上你的实现
```properties
zookeeper=com.alibaba.arthas.nat.agent.management.web.discovery.impl.ZookeeperNativeAgentProxyDiscovery
etcd=com.alibaba.arthas.nat.agent.management.web.discovery.impl.EtcdNativeAgentProxyDiscovery
注册中心名称=你的实现
```
# 添加你的实现
注册中心名称=你实现类的具体路径
之后你启动native-agent-management-web就可以,通过--registration-type参数,来指定你实现的注册中心
```shell
java -jar native-agent-management-web.jar --registration-type 注册中心名称 --registration-address 注册中心的地址
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@
<version>3.7.0</version>
</dependency>

<dependency>
<groupId>io.etcd</groupId>
<artifactId>jetcd-core</artifactId>
<version>0.7.0</version>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ public class NativeAgentConstants {

public static final int ARTHAS_SERVER_HTTP_PORT = 8563;

public static final int MAX_HTTP_CONTENT_LENGTH = 1024 * 1024 * 10;

public static final String NATIVE_AGENT_KEY = "/native-agent";

public static final String NATIVE_AGENT_PROXY_KEY = "/native-agent-proxy";

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.alibaba.arthas.nat.agent.server.dto;
package com.alibaba.arthas.nat.agent.common.dto;

/**
* @description: NativeAgentInfoDTO
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.alibaba.arthas.nat.agent.common.utils;

import okhttp3.*;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
* @description: OkHttpUtil
* @author:flzjkl
* @date: 2024-10-20 21:35
*/
public class OkHttpUtil {

private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();

private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");

public static String get(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();

try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}

public static String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url(url)
.post(body)
.header("Content-Type", "application/json")
.build();

try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.alibaba.arthas.nat.agent.common.utils;


/**
* @description: WelcomeUtil
* @author:flzjkl
* @date: 2024-09-22 18:26
*/
public class WelcomeUtil {

public static void printNativeAgentWelcomeMsg() {
String welcomeMsg = " _ _ _ \n" +
" _ __ __ _ | |_ (_) __ __ ___ __ _ __ _ ___ _ __ | |_ \n" +
" | '_ \\ / _` | | __| | | \\ \\ / / / _ \\ / _` | / _` | / _ \\ | '_ \\ | __|\n" +
" | | | | | (_| | | |_ | | \\ V / | __/ | (_| | | (_| | | __/ | | | | | |_ \n" +
" |_| |_| \\__,_| \\__| |_| \\_/ \\___| \\__,_| \\__, | \\___| |_| |_| \\__|\n" +
" |___/ ";
System.out.println(welcomeMsg);
System.out.println("=======================================================================================================================");
}

public static void printManagementWebWelcomeMsg() {
String welcomeMsg = " _ _ _ _ _ \n" +
" _ __ __ _ | |_ (_) __ __ ___ __ _ __ _ ___ _ __ | |_ _ __ ___ __ _ _ __ __ _ __ _ ___ _ __ ___ ___ _ __ | |_ __ __ ___ | |__ \n" +
" | '_ \\ / _` | | __| | | \\ \\ / / / _ \\ / _` | / _` | / _ \\ | '_ \\ | __| | '_ ` _ \\ / _` | | '_ \\ / _` | / _` | / _ \\ | '_ ` _ \\ / _ \\ | '_ \\ | __| \\ \\ /\\ / / / _ \\ | '_ \\ \n" +
" | | | | | (_| | | |_ | | \\ V / | __/ | (_| | | (_| | | __/ | | | | | |_ | | | | | | | (_| | | | | | | (_| | | (_| | | __/ | | | | | | | __/ | | | | | |_ \\ V V / | __/ | |_) |\n" +
" |_| |_| \\__,_| \\__| |_| \\_/ \\___| \\__,_| \\__, | \\___| |_| |_| \\__| |_| |_| |_| \\__,_| |_| |_| \\__,_| \\__, | \\___| |_| |_| |_| \\___| |_| |_| \\__| \\_/\\_/ \\___| |_.__/ \n" +
" |___/ |___/ ";
System.out.println(welcomeMsg);
System.out.println("=========================================================================================================================================================================================================================");
}

public static void printProxyWelcomeMsg() {
String welcomeMsg = " _ _ _ \n" +
" _ __ __ _ | |_ (_)__ __ ___ __ _ __ _ ___ _ __ | |_ _ __ _ __ ___ __ __ _ _ \n" +
"| '_ \\ / _` || __|| |\\ \\ / / / _ \\ / _` | / _` | / _ \\| '_ \\ | __| | '_ \\ | '__| / _ \\ \\ \\/ /| | | |\n" +
"| | | || (_| || |_ | | \\ V / | __/ | (_| || (_| || __/| | | || |_ | |_) || | | (_) | > < | |_| |\n" +
"|_| |_| \\__,_| \\__||_| \\_/ \\___| \\__,_| \\__, | \\___||_| |_| \\__| | .__/ |_| \\___/ /_/\\_\\ \\__, |\n" +
" |___/ |_| |___/ ";
System.out.println(welcomeMsg);
System.out.println("==========================================================================================================================");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>native-agent-server</artifactId>
<artifactId>native-agent-management-web</artifactId>

<properties>
<maven.compiler.source>8</maven.compiler.source>
Expand Down Expand Up @@ -42,9 +42,8 @@
</dependency>

<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-boot</artifactId>
<version>${project.version}</version>
<groupId>com.alibaba.middleware</groupId>
<artifactId>cli</artifactId>
</dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
Expand All @@ -69,7 +68,7 @@
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.alibaba.arthas.nat.agent.server.server.NativeAgentServerBootstrap</mainClass>
<mainClass>com.alibaba.arthas.nat.agent.management.web.server.NativeAgentManagementWebBootstrap</mainClass>
</transformer>
</transformers>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.alibaba.arthas.nat.agent.management.web.discovery;

import java.util.List;

/**
* @description: NativeAgentProyDiscovery
* @author:flzjkl
* @date: 2024-09-19 7:22
*/
public interface NativeAgentProxyDiscovery {

/**
* list native agent proxy address
* @param address register address
* @return native agent proxy address
*/
List<String> listNativeAgentProxy(String address);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.alibaba.arthas.nat.agent.management.web.discovery.impl;

import com.alibaba.arthas.nat.agent.common.constants.NativeAgentConstants;
import com.alibaba.arthas.nat.agent.management.web.discovery.NativeAgentProxyDiscovery;
import io.etcd.jetcd.ByteSequence;
import io.etcd.jetcd.Client;
import io.etcd.jetcd.KV;
import io.etcd.jetcd.KeyValue;
import io.etcd.jetcd.kv.GetResponse;
import io.etcd.jetcd.options.GetOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
* @description: EtcdNativeAgentDiscovery implements NativeAgentDiscovery
* @author:flzjkl
* @date: 2024-09-15 9:19
*/
public class EtcdNativeAgentProxyDiscovery implements NativeAgentProxyDiscovery {

private static final Logger logger = LoggerFactory.getLogger(EtcdNativeAgentProxyDiscovery.class);


@Override
public List<String> listNativeAgentProxy(String address) {
// Create kv client
Client client = null;
KV kvClient = null;
List<String> res = null;
try {
client = Client.builder().endpoints("http://" + address).build();
kvClient = client.getKVClient();

// Get value by prefix /native-agent-client
GetResponse getResponse = null;
try {
ByteSequence prefix = ByteSequence.from(NativeAgentConstants.NATIVE_AGENT_PROXY_KEY, StandardCharsets.UTF_8);
GetOption option = GetOption.newBuilder().isPrefix(Boolean.TRUE).build();
getResponse = kvClient.get(prefix, option).get();
} catch (Exception e) {
logger.error("get value failed with prefix" + NativeAgentConstants.NATIVE_AGENT_PROXY_KEY);
throw new RuntimeException(e);
}

// Build Map
List<KeyValue> kvs = getResponse.getKvs();
if (kvs == null || kvs.size() == 0) {
return null;
}
res = new ArrayList<>(kvs.size());
for (KeyValue kv : kvs) {
String value = kv.getValue().toString(StandardCharsets.UTF_8);
res.add(value);
}
} finally {
if (kvClient != null) {
kvClient.close();
}
if (client != null) {
client.close();
}
}
return res;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.alibaba.arthas.nat.agent.management.web.discovery.impl;

import com.alibaba.arthas.nat.agent.common.constants.NativeAgentConstants;
import com.alibaba.arthas.nat.agent.management.web.discovery.NativeAgentProxyDiscovery;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
* @description: ZookeeperNativeAgentProxyDiscovery implements NativeAgentProxyDiscovery
* @author:flzjkl
* @date: 2024-07-24 20:33
*/
public class ZookeeperNativeAgentProxyDiscovery implements NativeAgentProxyDiscovery {

private static final int SESSION_TIMEOUT = 20000;
private static final CountDownLatch connectedSemaphore = new CountDownLatch(1);

@Override
public List<String> listNativeAgentProxy(String address) {
if (address == null || "".equals(address)) {
return null;
}

// Wait for connection to be established
try {
ZooKeeper zooKeeper = new ZooKeeper(address, SESSION_TIMEOUT, event -> {
if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
connectedSemaphore.countDown();
}
});
connectedSemaphore.await();

// Gets a list of all children of the parent node
List<String> children = zooKeeper.getChildren(NativeAgentConstants.NATIVE_AGENT_PROXY_KEY, false);
if (children == null || children.size() == 0) {
return children;
}

zooKeeper.close();
return children;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Loading

0 comments on commit 8f285b9

Please sign in to comment.