code up

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Java] SLF4J + Logback + asynchronousSending = trueで正しくシャットダウンする

SLF4JLogbackの組み合わせでERROR時にメールを飛ばしているが、アプリケーションサーバー(Tomcat)が正しくシャットダウンしないという現象に遭遇。

延々とシャットダウンを待っている間、jps/jstackで確認すると怪しげなThreadPoolExecutorが存在している事に気づいた。

"pool-2-thread-5" prio=6 tid=0x000000000e5fb800 nid=0xf30 waiting on condition [0x00000000123be000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000faa7a118> (a java.util.concurrent.SynchronousQueue$TransferStack)
        at java.util.concurrent.locks.LockSupport.park(Unknown Source)
        at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(Unknown Source)
        at java.util.concurrent.SynchronousQueue$TransferStack.transfer(UnknownSource)
        at java.util.concurrent.SynchronousQueue.take(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

で色々と調べた結果、Logbackでch.qos.logback.classic.net.SMTPAppenderを指定しasynchronousSendingtrue(デフォルトでtrueなので未指定の場合も)の時に、ExecutorServiceを使用していることが分かった。

で、どうにかこのサービスを停止する方法を探していたところ、stackoverflowの記事を発見。

ServletContextListenerに組み込むなら↓こんな感じ。

package foo.bar;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;

@WebListener
public final class MyWebappListener implements ServletContextListener {

	/**
	 * @see ServletContextListener#contextInitialized(ServletContextEvent)
	 */
	@Override
	public void contextInitialized(ServletContextEvent arg0) {
	}

	/**
	 * @see ServletContextListener#contextDestroyed(ServletContextEvent)
	 */
	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		ILoggerFactory f = LoggerFactory.getILoggerFactory();

		if (f instanceof LoggerContext) {
			((LoggerContext) f).stop();
		}
	}
}
関連記事
タグ:SLF4J Logback Java
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。