1. 程式人生 > >pinpoint agent執行緒模型

pinpoint agent執行緒模型

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

以上除了資料上報較為複雜外,其它幾個都是定時執行的單執行緒程式

呼叫鏈資料上報分為兩種

  1. API、sql、String常量,這類資料上報如果失敗會先放到重試佇列,後續進行重試,預設重試3次
  2. 呼叫鏈詳情資料上報失敗不會重試

資料上報流程

  1. 資料先被新增到上報佇列中,返回新增成功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;
}
  1. 資料上報執行緒迴圈從佇列中獲取資料傳送到收集器
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

由於呼叫鏈監控的粒度非常細,所以過多的日誌列印會對應用造成影響,要避免不必要的日誌,合理設定日誌級別,線上使用的日誌級別要配置高一些