pinpoint agent線程模型
以下分析基於pinpoint1.7.1版本
pinpoint agent主要使用到的異步線程有4個
DeadlockMonitorThread : 死鎖監測線程,執行一次休眠60s
public DeadlockMonitorThread(DeadlockThreadRegistry deadlockThreadRegistry, long intervalMillis) {
this.deadlockMonitorTask = new DeadlockMonitorTask(deadlockThreadRegistry, intervalMillis);
this.deadlockMonitorThread = new Thread(deadlockMonitorTask, "Pinpoint-deadlock-monitor");
this.deadlockMonitorThread.setDaemon(true);
// for preload
deadlockMonitorTask.doTask();
}
AgentInfoSender: agent信息上報定時任務,是個timer,3秒上報一次
DefaultAgentStatMonitor: agent狀態信息上報(jvm狀態等),線程數為1的定時線程池(ScheduledExecutorService),延遲5秒執行,每5秒上報一次
private final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1, new PinpointThreadFactory("Pinpoint-stat-monitor", true));
TcpDataSender: 調用鏈數據上報通道,單線程,數據隊列(LinkedBlockingQueue)大小5120,重試隊列(LinkedBlockingQueue)大小1024,底層通迅使用的Netty
以上除了數據上報較為復雜外,其它幾個都是定時執行的單線程程序
調用鏈數據上報分為兩種
- API、sql、String常量,這類數據上報如果失敗會先放到重試隊列,后續進行重試,默認重試3次
- 調用鏈詳情數據上報失敗不會重試
數據上報流程
- 數據先被添加到上報隊列中,返回添加成功or失敗
public boolean execute(T data) {
if (data == null) {
if (isWarn) {
logger.warn("execute(). data is null");
}
return false;
}
if (!isRun.get()) {
if (isWarn) {
logger.warn("{} is shutdown. discard data:{}", executorName, data);
}
return false;
}
boolean offer = queue.offer(data);
if (!offer) {
if (isWarn) {
logger.warn("{} Drop data. queue is full. size:{}", executorName, queue.size());
}
}
return offer;
}
- 數據上報線程循環從隊列中獲取數據發送到收集器
private void doExecute() {
drainStartEntry:
while (isRun()) {
try {
Collection<T> dtoList = getDrainQueue();
int drainSize = takeN(dtoList, this.maxDrainSize);
if (drainSize > 0) {
doExecute(dtoList);
continue;
}
while (isRun()) {
T dto = takeOne();
if (dto != null) {
doExecute(dto);
continue drainStartEntry;
}
}
} catch (Throwable th) {
logger.warn("{} doExecute(). Unexpected Error. Cause:{}", executorName, th.getMessage(), th);
}
}
flushQueue();
}
還有一個UDP的數據上報通道,除了底層協議不同外,其它和TCP上報一樣
數據上報流程
總結
agent使用的異步線程都是單線程
數據上報都是先把數據放入隊列中,立即返回,隊列大小可配置,默認5120
底層數據上報通迅是基於Netty的NIO
由於調用鏈監控的粒度非常細,所以過多的日志打印會對應用造成影響,要避免不必要的日志,合理設置日志級別,線上使用的日志級別要配置高一些