项目中引入了RocketMQ作为消息中间件使用,在使用过程中,发现rmq会定期的往INFO日志中输出大量日志(对于web项目,会输出到catalina.out),如下:
13:00:02.612 INFO RocketmqClient[128]-[persistAll] Group: paopao_activityInfo_circle_all_%%qQEl6AGy ClientId: 10.49.16.12@bc8e79e56ebd48a08086fa66279f958e updateConsumeOffsetToBroker MessageQueue [topic=Qipu_Te
st_EntityNotification_Low_Topic_16, brokerName=broker-1, queueId=2] 3700772
13:00:02.612 INFO RocketmqClient[128]-[persistAll] Group: paopao_activityInfo_circle_all_%%qQEl6AGy ClientId: 10.49.16.12@bc8e79e56ebd48a08086fa66279f958e updateConsumeOffsetToBroker MessageQueue [topic=Qipu_Te
st_EntityNotification_Trivial_Topic_16, brokerName=broker-3, queueId=9] 2
13:00:02.612 INFO RocketmqClient[128]-[persistAll] Group: paopao_activityInfo_circle_all_%%qQEl6AGy ClientId: 10.49.16.12@bc8e79e56ebd48a08086fa66279f958e updateConsumeOffsetToBroker MessageQueue [topic=Qipu_Te
st_EntityNotification_Medium_Topic_16, brokerName=broker-1, queueId=0] 3518429
13:00:02.613 INFO RocketmqClient[128]-[persistAll] Group: paopao_activityInfo_circle_all_%%qQEl6AGy ClientId: 10.49.16.12@bc8e79e56ebd48a08086fa66279f958e updateConsumeOffsetToBroker MessageQueue [topic=Qipu_Te
st_EntityNotification_Low_Topic_16, brokerName=broker-1, queueId=3] 3698935
13:00:02.613 INFO RocketmqClient[128]-[persistAll] Group: paopao_activityInfo_circle_all_%%qQEl6AGy ClientId: 10.49.16.12@bc8e79e56ebd48a08086fa66279f958e updateConsumeOffsetToBroker MessageQueue [topic=Qipu_Te
st_EntityNotification_Low_Topic_16, brokerName=broker-1, queueId=1] 3697798
13:00:02.613 INFO RocketmqClient[128]-[persistAll] Group: paopao_activityInfo_circle_all_%%qQEl6AGy ClientId: 10.49.16.12@bc8e79e56ebd48a08086fa66279f958e updateConsumeOffsetToBroker MessageQueue [topic=Qipu_Te
st_EntityNotification_Low_Topic_16, brokerName=broker-2, queueId=14] 3694691
这样的日志一方面会给系统io带来负担,另一方面会淹没其他日志信息,那该如何禁用掉该日志呢?
RocketMQ client的源码中,关于日志的类如下:
import java.lang.reflect.Method;
import java.net.URL;
import org.apache.rocketmq.common.constant.LoggerName;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClientLogger {
public static final String CLIENT_LOG_ROOT = "rocketmq.client.logRoot";
public static final String CLIENT_LOG_MAXINDEX = "rocketmq.client.logFileMaxIndex";
public static final String CLIENT_LOG_LEVEL = "rocketmq.client.logLevel";
private static Logger log;
static {
log = createLogger(LoggerName.CLIENT_LOGGER_NAME);
}
private static Logger createLogger(final String loggerName) {
String logConfigFilePath =
System.getProperty("rocketmq.client.log.configFile",
System.getenv("ROCKETMQ_CLIENT_LOG_CONFIGFILE"));
Boolean isloadconfig =
Boolean.parseBoolean(System.getProperty("rocketmq.client.log.loadconfig", "true"));
final String log4JResourceFile =
System.getProperty("rocketmq.client.log4j.resource.fileName", "log4j_rocketmq_client.xml");
final String logbackResourceFile =
System.getProperty("rocketmq.client.logback.resource.fileName", "logback_rocketmq_client.xml");
String clientLogRoot = System.getProperty(CLIENT_LOG_ROOT, "${user.home}/logs/rocketmqlogs");
System.setProperty("client.logRoot", clientLogRoot);
String clientLogLevel = System.getProperty(CLIENT_LOG_LEVEL, "INFO");
System.setProperty("client.logLevel", clientLogLevel);
String clientLogMaxIndex = System.getProperty(CLIENT_LOG_MAXINDEX, "10");
System.setProperty("client.logFileMaxIndex", clientLogMaxIndex);
if (isloadconfig) {
try {
ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory();
Class classType = iLoggerFactory.getClass();
if (classType.getName().equals("org.slf4j.impl.Log4jLoggerFactory")) {
Class> domconfigurator;
Object domconfiguratorobj;
domconfigurator = Class.forName("org.apache.log4j.xml.DOMConfigurator");
domconfiguratorobj = domconfigurator.newInstance();
if (null == logConfigFilePath) {
Method configure = domconfiguratorobj.getClass().getMethod("configure", URL.class);
URL url = ClientLogger.class.getClassLoader().getResource(log4JResourceFile);
configure.invoke(domconfiguratorobj, url);
} else {
Method configure = domconfiguratorobj.getClass().getMethod("configure", String.class);
configure.invoke(domconfiguratorobj, logConfigFilePath);
}
} else if (classType.getName().equals("ch.qos.logback.classic.LoggerContext")) {
Class> joranConfigurator;
Class> context = Class.forName("ch.qos.logback.core.Context");
Object joranConfiguratoroObj;
joranConfigurator = Class.forName("ch.qos.logback.classic.joran.JoranConfigurator");
joranConfiguratoroObj = joranConfigurator.newInstance();
Method setContext = joranConfiguratoroObj.getClass().getMethod("setContext", context);
setContext.invoke(joranConfiguratoroObj, iLoggerFactory);
if (null == logConfigFilePath) {
URL url = ClientLogger.class.getClassLoader().getResource(logbackResourceFile);
Method doConfigure =
joranConfiguratoroObj.getClass().getMethod("doConfigure", URL.class);
doConfigure.invoke(joranConfiguratoroObj, url);
} else {
Method doConfigure =
joranConfiguratoroObj.getClass().getMethod("doConfigure", String.class);
doConfigure.invoke(joranConfiguratoroObj, logConfigFilePath);
}
}
} catch (Exception e) {
System.err.println(e);
}
}
return LoggerFactory.getLogger(LoggerName.CLIENT_LOGGER_NAME);
}
1、rmq日志相关的配置:
rocketmq.client.log.loadconfig
rocketmq.client.log4j.resource.fileName
、rocketmq.client.logback.resource.fileName
、 rocketmq.client.log4j2.resource.fileName
rocketmq.client.log.configFile
rocketmq.client.logRoot
rocketmq.client.logLevel
rocketmq.client.logFileMaxIndex
上面的这些参数,可以通过以下三种方式来配置:
ROCKETMQ_CLIENT_LOG_CONFIGFILE=
rocketmq.client.log.configFile=
,作为 JVM 变量,启动时时需要增加 -D 标识,优先级也比环境变量更高System.setProperty(“rocketmq.client.log.configFile”, customer_file)
来配置2、rmq支持log4j、logback两种日志框架:
源码中可以看到,有通过反射来获取日志实现类,通过这两个类名可以得出rmq支持log4j和logback框架。
//log4j
if (classType.getName().equals("org.slf4j.impl.Log4jLoggerFactory")) {
//logback
else if (classType.getName().equals("ch.qos.logback.classic.LoggerContext")) {
1、工程使用的是slf4j+log4j日志框架:
可以通过添加JVM启动参数,指定RocketMQ的日志输出等级,将其设置为ERROR即可。对于部署到tomcat的web应用,修改catalina.sh文件,找到elif [ "$1" = "start" ] ; then代码处,添加如下内容:
-Drocketmq.client.logLevel=\"ERROR\" \
2、工程使用的是slf4j+log4j2日志框架:
添加RocketmqClient logger配置,如下:
logger的名字为什么是RocketmqClient呢?可以通过rmq源码中return LoggerFactory.getLogger(LoggerName.CLIENT_LOGGER_NAME); 来得出,
public class LoggerName {
public static final String FILTERSRV_LOGGER_NAME = "RocketmqFiltersrv";
public static final String NAMESRV_LOGGER_NAME = "RocketmqNamesrv";
public static final String BROKER_LOGGER_NAME = "RocketmqBroker";
public static final String BROKER_CONSOLE_NAME = "RocketmqConsole";
public static final String CLIENT_LOGGER_NAME = "RocketmqClient";
public static final String TOOLS_LOGGER_NAME = "RocketmqTools";
public static final String COMMON_LOGGER_NAME = "RocketmqCommon";
public static final String STORE_LOGGER_NAME = "RocketmqStore";
public static final String STORE_ERROR_LOGGER_NAME = "RocketmqStoreError";
public static final String TRANSACTION_LOGGER_NAME = "RocketmqTransaction";
public static final String REBALANCE_LOCK_LOGGER_NAME = "RocketmqRebalanceLock";
public static final String ROCKETMQ_STATS_LOGGER_NAME = "RocketmqStats";
public static final String COMMERCIAL_LOGGER_NAME = "RocketmqCommercial";
public static final String FLOW_CONTROL_LOGGER_NAME = "RocketmqFlowControl";
public static final String ROCKETMQ_AUTHORIZE_LOGGER_NAME = "RocketmqAuthorize";
public static final String DUPLICATION_LOGGER_NAME = "RocketmqDuplication";
public static final String PROTECTION_LOGGER_NAME = "RocketmqProtection";
public static final String WATER_MARK_LOGGER_NAME = "RocketmqWaterMark";
public static final String FILTER_LOGGER_NAME = "RocketmqFilter";
}