我使用Netty Bootstrap(v3)作为服务器套接字。但是在使用一段时间后,我得到了这个GC日志:
2018-06-12T10:51:18.219-0400: 331664.849: [Full GC (Ergonomics) [PSYoungGen: 129024K->118028K(144896K)] [ParOldGen: 2723411K->2723411K(2723840K)] 2852435K->2841439K(2868736K), [Metaspace: 17983K->17983K(1064960K)], 19.7892397 secs] [Times: user=256.57 sys=0.00, real=19.78 secs]
2018-06-12T10:51:38.014-0400: 331684.645: [Full GC (Ergonomics) [PSYoungGen: 129024K->118091K(144896K)] [ParOldGen: 2723411K->2723411K(2723840K)] 2852435K->2841503K(2868736K), [Metaspace: 17983K->17983K(1064960K)], 19.6915664 secs] [Times: user=255.44 sys=0.00, real=19.69 secs]
2018-06-12T10:51:57.716-0400: 331704.347: [Full GC (Ergonomics) [PSYoungGen: 129024K->118166K(144896K)] [ParOldGen: 2723411K->2723411K(2723840K)] 2852435K->2841577K(2868736K), [Metaspace: 17983K->17983K(1064960K)], 23.3087463 secs] [Times: user=300.78 sys=0.00, real=23.30 secs]
2018-06-12T10:52:21.036-0400: 331727.667: [Full GC (Ergonomics) [PSYoungGen: 129024K->118197K(144896K)] [ParOldGen: 2723411K->2723411K(2723840K)] 2852435K->2841608K(2868736K), [Metaspace: 17983K->17983K(1064960K)], 19.5556922 secs] [Times: user=253.78 sys=0.00, real=19.56 secs]
2018-06-12T10:52:40.598-0400: 331747.229: [Full GC (Ergonomics) [PSYoungGen: 129024K->118252K(144896K)] [ParOldGen: 2723411K->2723411K(2723840K)] 2852435K->2841664K(2868736K), [Metaspace: 17983K->17983K(1064960K)], 18.9957031 secs] [Times: user=246.53 sys=0.00, real=19.00 secs]
2018-06-12T10:52:59.601-0400: 331766.232: [Full GC (Ergonomics) [PSYoungGen: 128996K->118259K(144896K)] [ParOldGen: 2723411K->2723411K(2723840K)] 2852408K->2841671K(2868736K), [Metaspace: 17983K->17983K(1064960K)], 19.6780211 secs] [Times: user=255.45 sys=0.00, real=19.68 secs]
现在,我没有在JVM中设置任何Xms和Xmx参数。
任何人都可以为我分析一下吗?如何优化这种情况?感谢。
更多信息:
我正在使用java:
java版本" 1.8.0_152"
库:
的pom.xml
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
<version>${bonecp.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
<version>3.10.5.Final</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
MessageDecoder
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
Message message = null;
buffer.markReaderIndex();
ChannelBuffer rawMessage = buffer.copy();
try {
loadConfiguration();
// skip for message start character (#)
buffer.skipBytes(1);
byte[] data = null;
String messageRef;
// message reference
ChannelBuffer msgData = readFrame(buffer, messageRefDelimiter);
messageRef = new String(msgData.array());
// get data
msgData = readFrame(buffer, messageDelimiter);
data = msgData.array();
message = new Message();
message.setMessageType(MessageType.Yyyy);
message.setMessageReference(Long.parseLong(messageRef));
message.setData(data);
} catch (Exception e) {
String msg = new String(rawMessage.array());
logger.error("Error when decode message {}", msg, e);
message = null;
}
return message;
}
任务管理
static {
try {
PropertiesConfiguration config = AppConfig.getPropertiesConfiguration();
int poolSize = config.getInt(AppEnv.TASK_POOL_SIZE, AppEnv.TASK_POOL_SIZE_DEFAULT_VALUE);
int runningTask = config.getInt(AppEnv.TASK_RUNNING, AppEnv.TASK_RUNNING_DEFAULT_VALUE);
worksQueue = new ArrayBlockingQueue<Runnable>(poolSize);
executor = new ThreadPoolExecutor(runningTask, runningTask * 2, 10, TimeUnit.SECONDS, worksQueue, executionHandler);
executor.allowCoreThreadTimeOut(true);
logger.info("Init TaskManager: poolSize={}, runningTask={}", poolSize, runningTask);
} catch (AppConfigException e) {
logger.error("Init TaskManager error", e);
}
}
/**
* execute message
*
* @param message
*/
public static void execute(Message message) {
MessageProcessing messageProcessing = new MessageProcessing(message);
executor.execute(messageProcessing);
}
MessageProcessing
public void processMessage(Message message) {
DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
String[] data;
String mes = null;
try {
loadConfiguration();
} catch (Exception e) {
logger.error("error load configuration", e);
}
try {
mes = new String(message.getData());
data = mes.split(fieldDelimiter);
if (data[2].equals("10")) {
Yyyy10 Yyyy = new Yyyy10();
Yyyy.message = message.getMessageReference() + "," + mes;
Yyyy.messageReference = message.getMessageReference();
Yyyy.imsi = data[0];
Yyyy.isdn = StringUtil.formatIsdn(data[1]);
Yyyy.YyyyInformation = Integer.parseInt(data[2]);
Yyyy.accountProfile = data[3];
Yyyy.timestamp = df.parse(data[4]);
Yyyy.refillCount = Integer.parseInt(data[5]);
Yyyy.mainAmount = Long.parseLong(data[6]);
Yyyy.bonusAmount = Long.parseLong(data[7]);
Yyyy.scratchCardNumber = data[8];
Yyyy.scratchCardProfile = data[9];
Yyyy.tac = df.parse(data[10] + " 00:00:00");
//logger.info(Yyyy.toString());
DbUtil.insertYyyy10(Yyyy);
}
else if(data[2].equals("11")) {
Yyyy11 Yyyy = new Yyyy11();
Yyyy.message = message.getMessageReference() + "," + mes;
Yyyy.messageReference = message.getMessageReference();
Yyyy.imsi = data[0];
Yyyy.isdn = StringUtil.formatIsdn(data[1]);
Yyyy.YyyyInformation = Integer.parseInt(data[2]);
Yyyy.accountProfile = data[3];
Yyyy.timestamp = df.parse(data[4]);
//logger.info(Yyyy.toString());
DbUtil.insertYyyy11(Yyyy);
} else {
logger.error("not match Yyyy(10, 11)", message);
}
} catch (SQLException e) {
} catch (Exception e) {
logger.error("error parse message: {}", message, e);
} finally {
try {
data = null;
mes = null;
} catch (Exception e) {}
}
}
DbUtil
public static void insertYyyy11(Yyyy11 Yyyy) throws SQLException {
String insertQuery = "INSERT INTO TBL_Yyyy_11(ISDN,MESSAGE_REFERENCE,IMSI,ACCOUNT_PROFILE,TIMESTAMP,MSG_CONTENT) VALUES(?,?,?,?,?,?)";
try (Connection connection = getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(insertQuery);) {
preparedStatement.setQueryTimeout(queryTimeout);
preparedStatement.setString(1, Yyyy.isdn);
preparedStatement.setLong(2, Yyyy.messageReference);
preparedStatement.setString(3, Yyyy.imsi);
preparedStatement.setString(4, Yyyy.accountProfile);
preparedStatement.setTimestamp(5, DateUtil.toSqlTimestamp(Yyyy.timestamp));
preparedStatement.setString(6, Yyyy.message);
preparedStatement.executeUpdate();
} catch (SQLException e) {
logger.error("insertYyyy11 error, message: {}", Yyyy, e);
throw e;
}
}
线程转储:
有很多RUNNABLE线程
"pool-5-thread-22" #92 prio=5 os_prio=0 tid=0x00007ff5e0044800 nid=0x55ba runnable [0x00007ff6b30ef000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at oracle.net.ns.Packet.receive(Packet.java:308)
at oracle.net.ns.DataPacket.receive(DataPacket.java:106)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:324)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:268)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:190)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:107)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:124)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:80)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1137)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:350)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1046)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1336)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3694)
- locked <0x00000006c6b5b0d0> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1354)
at com.jolbox.bonecp.PreparedStatementHandle.executeUpdate(PreparedStatementHandle.java:205)
at vn.xxx.util.DbUtil.insertYyyy11(DbUtil.java:128)
at vn.xxx.service.YyyyMessageServiceImpl.processMessage(XXXMessageServiceImpl.java:109)
at vn.xxx.task.MessageProcessing.run(MessageProcessing.java:33)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
答案 0 :(得分:0)
最可能的解释是堆几乎已满。如果堆太满,JVM将越来越频繁地运行GC。
鉴于服务器在运行一段时间后才开始执行此操作,最可能的原因是您的应用程序或正在使用的某个库中存在内存泄漏。
假设我的假设是正确的,那么解决问题的方法是使用jhat
和内存分析器来尝试识别内存泄漏的来源。
另外几种可能性是你的池中有太多的工作线程(使用太多内存)或你的工作队列严重积压(使用太多内存)或(可能)你使用阻塞队列实际上是在你的(异步?)请求处理中导致积压。
如果您的服务器无法跟上请求率,那么唯一可行的策略就是尽早拒绝......或删除...请求。允许他们积压最终会导致问题。