SORU
20 Mayıs 2011, Cuma


Nasıl bir iş parçacığı havuzu ile MDC kullanılır?

Bizim yazılım kapsamlı MDC web istekleri için oturum Kimlikleri ve kullanıcı adları gibi şeyler izlemek için kullanın. Bu özgün iş parçacığı çalışırken gayet iyi çalışıyor. Ancak, arka planda işlenmesi gereken bir çok şey var. Bunun için kendini devirdi yürütme hizmetleri uyumsuz ile birlikte java.concurrent.ThreadPoolExecutor java.util.Timer sınıfları kullanırız. Tüm bu hizmetleri kendi iş parçacığı havuzu yönetir.

Bu Logback's manual böyle bir ortamda MDC kullanma hakkında ne diyor:

Eşlenen tanı içeriğinin bir kopyasını her zaman başlatan iş parçacığı, işçi iş parçacığı tarafından devralınan değil. Bu java durumda.açıklama.eşzamanlı.Uygulayıcıların iş parçacığı yönetimi için kullanılır. Örneğin, newCachedThreadPool yöntemi ThreadPoolExecutor oluşturur ve diğer iplik kodu havuzu gibi, karmaşık bir iş parçacığı oluşturma mantığı vardır.

Bu gibi durumlarda, MDC tavsiye edilir.() getCopyOfContextMap uygulamakla. görev vermeden önce (ana) özgün iş parçacığı üzerinde çağrılır Görev çalıştırıldığında, ilk iş olarak, MDC çağırmak gerekir.() setContextMapValues için yeni Vasi yönetilen iş parçacığı ile özgün MDC değerleri saklı kopya ilişkilendirmek.

Bu iyi olurdu, ama çok bu aramalar eklemeyi unutmayın, ve çok geç olana kadar sorunu tanımak için kolay bir yolu yoktur. Tek işareti ile Log4j o olsun eksik MDC ınfo günlükleri ve model alınarak elde bayat MDC ınfo (beri iplik sırt havuzu devralır onun MDC ilk görev oldu koştu. Her iki üretim sisteminde ciddi sorunlar bulunmaktadır.

Herhangi bir şekilde durum bizim özel görmüyorum, henüz web üzerinde bu sorun hakkında pek bir şey bulamadım. Görünüşe göre, bu birçok kişi bunları önlemek için bir yolu olmalı yani karşılaşmanızı, bir şey değil. Yanlış burada ne yapıyoruz?

CEVAP
12 EKİM 2013, CUMARTESİ


Evet, bu da karşılaştığım yaygın bir sorundur. Birkaç geçici çözüm vardır (el ile açıklandığı gibi ayarlanması gibi), ama ideal bir çözüm istiyorum

  • Ayarlar MDC sürekli;
  • MAŞ yanlıştır Ama nerede bilmiyorum, zımni hataları önler
  • En aza indirir, iş parçacığı havuzu kullanın nasıl değişiklikler (örneğin MyCallable her yerde Callable veya benzeri çirkinlik sınıflara).

İşte bu üç ihtiyaçlarını karşılayan kullandığım bir çözüm. Kod kendi kendini açıklayıcı olabilir.

(Bir yan not olarak, bu vasi ve MoreExecutors.listeningDecorator(), Eğer Guava için oluşturulan beslenebilir *.* 6 Guava) kullanın

import org.slf4j.MDC;

import java.util.Map;
import java.util.concurrent.*;

/**
 * A SLF4J MDC-compatible {@link ThreadPoolExecutor}.
 * <p/>
 * In general, MDC is used to store diagnostic information (e.g. a user's session id) in per-thread variables, to facilitate
 * logging. However, although MDC data is passed to thread children, this doesn't work when threads are reused in a
 * thread pool. This is a drop-in replacement for {@link ThreadPoolExecutor} sets MDC data before each task appropriately.
 * <p/>
 * Created by jlevy.
 * Date: 6/14/13
 */
public class MdcThreadPoolExecutor extends ThreadPoolExecutor {

    final private boolean useFixedContext;
    final private Map<String, Object> fixedContext;

    /**
     * Pool where task threads take MDC from the submitting thread.
     */
    public static MdcThreadPoolExecutor newWithInheritedMdc(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                                                            TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        return new MdcThreadPoolExecutor(null, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    /**
     * Pool where task threads take fixed MDC from the thread that creates the pool.
     */
    @SuppressWarnings("unchecked")
    public static MdcThreadPoolExecutor newWithCurrentMdc(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                                                          TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        return new MdcThreadPoolExecutor(MDC.getCopyOfContextMap(), corePoolSize, maximumPoolSize, keepAliveTime, unit,
                workQueue);
    }

    /**
     * Pool where task threads always have a specified, fixed MDC.
     */
    public static MdcThreadPoolExecutor newWithFixedMdc(Map<String, Object> fixedContext, int corePoolSize,
                                                        int maximumPoolSize, long keepAliveTime, TimeUnit unit,
                                                        BlockingQueue<Runnable> workQueue) {
        return new MdcThreadPoolExecutor(fixedContext, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    private MdcThreadPoolExecutor(Map<String, Object> fixedContext, int corePoolSize, int maximumPoolSize,
                                  long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        this.fixedContext = fixedContext;
        useFixedContext = (fixedContext != null);
    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> getContextForTask() {
        return useFixedContext ? fixedContext : MDC.getCopyOfContextMap();
    }

    /**
     * All executions will have MDC injected. {@code ThreadPoolExecutor}'s submission methods ({@code submit()} etc.)
     * all delegate to this.
     */
    @Override
    public void execute(Runnable command) {
        super.execute(wrap(command, getContextForTask()));
    }

    public static Runnable wrap(final Runnable runnable, final Map<String, Object> context) {
        return new Runnable() {
            @Override
            public void run() {
                Map previous = MDC.getCopyOfContextMap();
                if (context == null) {
                    MDC.clear();
                } else {
                    MDC.setContextMap(context);
                }
                try {
                    runnable.run();
                } finally {
                    if (previous == null) {
                        MDC.clear();
                    } else {
                        MDC.setContextMap(previous);
                    }
                }
            }
        };
    }
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • BachelorsPadTv

    BachelorsPad

    17 Ocak 2012
  • ETrade Supply

    ETrade Suppl

    23 Temmuz 2011
  • The Verge

    The Verge

    8 AĞUSTOS 2006