Solicitando a alocação dos mesmos dois modos de um traceid

 

Às vezes precisamos de toda a traceid em um pedido são os mesmos, a fim de obter uma resolução unificada do arquivo de log. Fácil de solucionar.

Atribuído a cada pedido com um traceid tanto quanto eu sei, existem duas maneiras: MDC e ThreadLocal, implementação interna do MDC também é ThreadLocal, seções a seguir descrevem esses dois métodos.

A, MDC

  MDC (mapeada diagnóstico Contextos), que se traduz em: Mapa contexto de diagnóstico. Meios: no ID do pedido de registro (requestId) (mapa), que pode ser posicionado como uma palavra-chave (de diagnóstico) problema (contexto).

  Com a ferramenta MDC, enquanto os implantes de colocar ou remover o código ou a secção de interface, quando o problema de posicionamento pode, de acordo com o mapeamento única RequestID rapidamente filtrar todos registrar um pedido particular.

  MDC slf4j de seu mecanismo interno com base na implementação ThreadLocal, consulte este blog em base Java ThreadLocal, https://www.cnblogs.com/yangyongjie/p/10574591.html .

 1, sem os fios criança implementos código de pedido:

  1) pedido Use interceptação Aop

/ ** 
 * pedido para adicionar um número de segmento para cada do HTTP 
 * 
 * @author yangyongjie 
 * @date 2019/09/02 
 * @desc 
 * / 
@Aspect 
@Component 
pública  classe LogAspect { 

    Privada  estática  final de Cordas STR_THREAD_ID = "O tópico" ; 

    @ pointcut (valor = "@annotation (org.springframework.web.bind.annotation.RequestMapping)" )
     privado  vazio webPointcut () {
         // DoNothing 
    } 

    / ** 
     * para todas as solicitações HTTP para adicionar o número de rosca 
     * 
     * @ param Joinpoint 
     *@throws o Throwable
      * / 
    @Around (valor = "webPointcut ()" )
     público  vazio ao redor (ProceedingJoinPoint Joinpoint) lança o Throwable {
         // método anterior realizada mais o número fio 
        MDC.put (STR_THREAD_ID, UUID.randomUUID (). toString () .replaceAll ( "-", "" ));
         // executar método de intercepção 
        joinPoint.proceed ();
         // método tiver terminado a execução remover o número do segmento 
        MDC.remove (STR_THREAD_ID); 
    } 
}

  2) registo de configuração log4j

log4j.appender.stdout.layout.ConversionPattern = [% - 5p]% d {aaaa-MM-dd HH: MM: ss.SSS} [% T] % X {} ThreadID [% C:% G] - m% % N

  Deve-se notar no log corda vermelha ThreadID necessidade de interceptar e log em MDC colocar a chave é a mesma.

 

 2, quando há um pedido criança threads.

  MDC slf4j de seu mecanismo interno com base na implementação ThreadLocal, consulte este blog em base Java ThreadLocal, https: //www.cnblogs.com/yangyongjie/p/10574591.html. Então chamamos MDC.put () passar método

  O ID do pedido é válido apenas no segmento atual. Então, MDC principal conjunto de dados segmento, em que não é obtida sub-thread (o pool de threads). Então como é que o segmento principal MDC dados para o sub-thread? 

  recomendações oficiais

    1) antes de o segmento pai Nova rosca do método chamada MDC.getCopyOfContextMap () para passar o conteúdo é retirado MDC sub-segmento

    2) o segmento de criança antes de prosseguir para chamar o método MDC.setContextMap () do teor de MDC do segmento pai ao conjunto segmento de criança 

    

  implementação de código

  1) O uso Aop intercepta o pedido, o mesmo que acima

  2) de configuração de log log4j mesmo que acima

  3) Rosca decorador decorador, existem duas maneiras:

    Método 1: Usando o padrão de decorador, a camada decorativa na interface Runnable, a criação de classes MDCRunnable Runnable ser decorados interfaces de camada.

valor Salvar MDC atual do segmento ao criar classe MDCRunnable, e em seguida, executar o método run ()

    Decorator MDCRunnable decoração Runnable:

Import org.slf4j.MDC; 

Import um java.util.Map; 

/ ** 
 * padrão decorador decorativo Runnable, segmento pai número fio passando 
 * 
 * @author yangyongjie 
 * @date 2020/03/09 
 * @desc 
 * / 
público  classe MDCRunnable os implementos do Runnable { 

    privada do Runnable Runnable; 

    / ** 
     * MDC salvar o valor atual do thread principal 
     * / 
    privado  final do Map <string, string> mainMdcMap; 

    pública MDCRunnable (o Runnable Runnable) {
         a este .runnable = Runnable;
         a este .mainMdcMap =  MDC. getCopyOfContextMap ();
    } 

    @ override
    pública  vazio run () {
         // os valores MDC atribuídos para o segmento segmento pai da criança 
        para (de Map.Entry <String, String> entrada: mainMdcMap.entrySet ()) { 
            MDC.put (entry.getKey (), entry.getValue ()); 
        } 
        // executa decorativo método segmento run 
        Runnable.run ();
         // execução de remoção de conclusão valores MDC 
        para (de Map.Entry <string, string> entrada: mainMdcMap.entrySet ()) { 
            MDC.put (entry.getKey (), entry.getValue ()); 
        } 
    } 

}

  Use MDCRunnable vez de Runnable:

        // log impressão segmento assíncrono, decorado com MDCRunnable o Runnable 
        novo novo a Thread ( new new MDCRunnable ( nova novo o Runnable () { 
            @Override 
            pública  vazio run () { 
                logger.debug ( "OUTRAS log in thread" ); 
            } 
        })) Iniciar (). ; 

        // log impressão pool de thread assíncrono, com MDCRunnable decorativo do Runnable 
        executor.execute ( nova nova MDCRunnable ( nova novo o Runnable () { 
            @Override 
            pública  vazio run () { 
                logger.debug ( "log segmento diferente na piscina" ); 
            } 
        })) ;
        EXECUTOR.shutdown ();

 

    A segunda maneira: decorativo pool de threads

/ ** 
 * ThreadPoolExecutor decorativo, o conteúdo do segmento pai passar MDC segmento infantil 
 * @author yangyongjie 
 * @date 2020/03/19 
 * @desc 
 * / 
público  classe MDCThreadPoolExecutor o estende a ThreadPoolExecutor { 

    Privada  estática  final Logger Logger LoggerFactory.getLogger = ( . MDCThreadPoolExecutor classe ); 

    pública MDCThreadPoolExecutor ( int corePoolSize, int maximumPoolSize, longo KeepAliveTime, TimeUnit Unit, BlockingQueue <o Runnable> WorkQueue, um ThreadFactory ThreadFactory, RejectedExecutionHandler Handler) {
         Super(CorePoolSize, maximumPoolSize, KeepAliveTime, Unit, WorkQueue, ThreadFactory, Handler); 
    } 

    @Override 
    pública  vazio Executar ( final do Runnable Runnable) {
         // obter conteúdo em MDC segmento pai, o método deve ser executado antes ou outra thread assíncrono de execução quando o valor do qual é possível MDC foi esvaziado, e desta vez vai retornar nulo 
        final do Map <string, string> context = MDC.getCopyOfContextMap ();
         Super .Execute ( nova novo o Runnable () { 
            @Override 
            pública  vazio run () {
                 // o conteúdo MDC passado para o segmento segmento pai criança 
                MDC.setContextMap (contexto);
                 o try {
                     //Realizando operação assíncrona 
                    Runnable.run (); 
                } o finalmente {
                     // conteúdo claro MDC 
                    MDC.clear (); 
                } 
            } 
        }); 
    } 
}

  用 MDCThreadPoolExecutor 代替 ThreadPoolExecutor:

Privado  estática  final MDCThreadPoolExecutor MDCEXECUTORS = new new MDCThreadPoolExecutor (1,10,60, TimeUnit.SECONDS, nova novo um LinkedBlockingQueue <o Runnable> (600), nova novo CustomThreadFactory ( "mdcThreadPoolTest"), nova novo RejectedExecutionHandler () { 
            @Override 
            pública  vazio rejectedExecution (R & lt o Runnable, executor do ThreadPoolExecutor) {
                 // imprimir log, e reiniciar um fio de execução da tarefa rejeitado 
                LOGGER.error ( "a tarefa: {}, rejeitou a partir de: {}" , r.toString (), executor.toString ());
                 // execução direta da tarefa for rejeitado, JVM de outro segmento de execução 
                r.run (); 
            }
        }); 

        Logger.info ( "log segmento pai" ); 
        MDCEXECUTORS.execute ( nova novo o Runnable () { 
            @Override 
            pública  vazio run () { 
                logger.info ( "log criança thread" ); 
            } 
        });

 

Dois, maneira ThreadLocal

ThreadLocal pode ser utilizado no mesmo segmento, de cross-classe, o método de comunicação de dados através de. Ele pode ser usado para o contexto transparente de transmissão mundial

1, não há nenhum caso de fio de criança

FIM

Acho que você gosta

Origin www.cnblogs.com/yangyongjie/p/12523567.html
Recomendado
Clasificación