1. 程式人生 > >Dubbo分散式日誌追蹤,多執行緒不能獲取竄ID和IP問題

Dubbo分散式日誌追蹤,多執行緒不能獲取竄ID和IP問題

接著上一篇日誌,當用MDC或者ThreadContext來put或者get資料的時候,不同執行緒是獲取不到的,他們都是ThreadLocal維護,所以執行緒獨立。

如果需要子執行緒獲取則將引數傳入,在Thread的run方法執行的時候將傳入的ID和IP都put到MDC或者ThreadContext中。

  • 這裡使用ThreadContext:
<context:component-scan base-package="spring04"/>

    <bean id="threadPool"
          class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <!-- 核心執行緒數 -->
        <property name="corePoolSize" value="3"/>
        <!-- 最大執行緒數 -->
        <property name="maxPoolSize" value="10"/>
        <!-- 佇列最大長度 >=mainExecutor.maxSize -->
        <property name="queueCapacity" value="25"/>
        <!-- 執行緒池維護執行緒所允許的空閒時間 -->
        <property name="keepAliveSeconds" value="300"/>
        <!-- 執行緒池對拒絕任務(無執行緒可用)的處理策略 ThreadPoolExecutor.CallerRunsPolicy策略 ,呼叫者的執行緒會執行該任務,如果執行器已關閉,則丟棄.  -->
        <property name="rejectedExecutionHandler">
            <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/>
        </property>
    </bean>
  • 建立一個AbstractRunnable實現Runnable,以後建立執行緒都用AbstractRunnable建立
package spring04;

import org.slf4j.MDC;

public abstract class AbstractRunnable implements Runnable {
    private String traceid;
    private String ip;

    public AbstractRunnable(String traceid, String ip) {
        this.traceid = traceid;
        this.ip = ip;
    }

    private void log() {
        MDC.put(Constant.TRANC_ID, traceid);
        MDC.put(Constant.LOCAL_IP, ip);
    }

    protected abstract void thread();

    public void run() {
        log();
        thread();
    }

    public String getTraceid() {
        return traceid;
    }

    public void setTraceid(String traceid) {
        this.traceid = traceid;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }
}
  • 個執行緒池context
package spring04;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

@Component
public class TreadContext {

    @Autowired
    private ThreadPoolTaskExecutor executor;

    private static TreadContext context;

    private List<AbstractRunnable> threads = new ArrayList<AbstractRunnable>();

    @PostConstruct
    private void init() {
        context = this;
    }

    /**
     * 關閉執行緒池
     */
    public void close() {
        executor.shutdown();
    }

    /**
     * 執行所有執行緒池
     */
    public void open() {
        for (Runnable thread : this.threads) {
            executor.execute(thread);
        }
    }

    /**
     * 新增多個執行緒任務
     *
     * @param threads
     * @return
     */
    public TreadContext source(List<AbstractRunnable> threads) {
        this.threads.addAll(threads);
        return context;
    }

    /**
     * 新增單個執行緒任務
     *
     * @param thread
     */
    public void source(AbstractRunnable thread) {
        this.threads.add(thread);
    }

    /**
     * 獲取執行緒池管理物件
     *
     * @return
     */
    public static TreadContext getContext() {
        return context;
    }
}
  • 常量
package spring04;

public class Constant {
    public static final String TRANC_ID = "TRANC_ID";
    public static final String LOCAL_IP = "LOCAL_IP";
}
  • 執行緒類
package spring04;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class MyThread extends AbstractRunnable {

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

    public MyThread(String traceid, String ip) {
        super(traceid, ip);
    }

    /**
     * 用來替代run方法
     */
    protected void thread() {
        logger.info("thread name:{}  ,trace_id:{}  ,local_ip:{}", Thread.currentThread().getName(), MDC.get(Constant.TRANC_ID), MDC.get(Constant.TRANC_ID));
    }

}
  • 執行的main方法
package spring04;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.List;

public class Main {

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

    private static String ID = "10000000000001";
    private static String IP = "192.168.80.123";

    public static void main(String[] args) {
        AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("application04.xml");
        TreadContext context = appContext.getBean(TreadContext.class);
        MDC.put(Constant.TRANC_ID, ID);
        MDC.put(Constant.LOCAL_IP, "192.168.80.123");
        AbstractRunnable thread1 = new MyThread(ID, IP);
        AbstractRunnable thread2 = new MyThread(ID, IP);
        List<AbstractRunnable> threads = new ArrayList<AbstractRunnable>();
        threads.add(thread1);
        threads.add(thread2);
        context.source(threads).open();
        logger.info("thread name:{}  ,trace_id:{}  ,local_ip:{}", Thread.currentThread().getName(), MDC.get(Constant.TRANC_ID), MDC.get(Constant.LOCAL_IP));
        appContext.registerShutdownHook();
    }
}
  • 執行結果:

這裡寫圖片描述