Dalam perangkat lunak kami, kami secara luas menggunakan MDC untuk melacak hal-hal seperti ID sesi dan nama pengguna untuk permintaan web. Ini berfungsi dengan baik saat berjalan di utas asli. Namun, ada banyak hal yang perlu diproses di latar belakang. Untuk itu kami menggunakan java.concurrent.ThreadPoolExecutor
dan java.util.Timer
kelas bersama dengan beberapa layanan eksekusi async self-rolled. Semua layanan ini mengelola kumpulan utas mereka sendiri.
Ini adalah apa yang dikatakan oleh manual Logback tentang penggunaan MDC dalam lingkungan seperti itu:
Salinan konteks diagnostik yang dipetakan tidak selalu dapat diwarisi oleh utas pekerja dari utas inisiasi. Ini adalah kasus ketika java.util.concurrent.Executors digunakan untuk manajemen utas. Sebagai contoh, metode newCachedThreadPool menciptakan ThreadPoolExecutor dan seperti kode pooling thread lainnya, ia memiliki logika pembuatan thread yang rumit.
Dalam kasus seperti itu, disarankan agar MDC.getCopyOfContextMap () dipanggil pada utas (master) asli sebelum mengirimkan tugas ke pelaksana. Ketika tugas berjalan, sebagai tindakan pertama, ia harus memanggil MDC.setContextMapValues () untuk mengaitkan salinan nilai MDC yang tersimpan dengan utas baru yang dikelola Pelaksana.
Ini akan baik-baik saja, tetapi sangat mudah untuk lupa menambahkan panggilan-panggilan itu, dan tidak ada cara mudah untuk mengenali masalahnya sampai semuanya terlambat. Satu-satunya tanda dengan Log4j adalah bahwa Anda mendapatkan info MDC yang hilang di log, dan dengan Logback Anda mendapatkan info MDC basi (karena utas di kumpulan tapak mewarisi MDC-nya dari tugas pertama yang dijalankan di dalamnya). Keduanya merupakan masalah serius dalam sistem produksi.
Saya tidak melihat situasi kami istimewa dengan cara apa pun, namun saya tidak dapat menemukan banyak tentang masalah ini di web. Rupanya, ini bukan sesuatu yang banyak orang lawan, jadi harus ada cara untuk menghindarinya. Apa yang kita lakukan salah di sini?