perf: 优化连接稳定性
This commit is contained in:
@@ -74,7 +74,6 @@ public abstract class BallAPI {
|
|||||||
bootstrap.group(executors)
|
bootstrap.group(executors)
|
||||||
.channel(NioSocketChannel.class)
|
.channel(NioSocketChannel.class)
|
||||||
.option(ChannelOption.TCP_NODELAY, true)
|
.option(ChannelOption.TCP_NODELAY, true)
|
||||||
.option(ChannelOption.SO_KEEPALIVE, true)
|
|
||||||
.handler(BallChannelInitializer.INSTANCE);
|
.handler(BallChannelInitializer.INSTANCE);
|
||||||
|
|
||||||
addListener(new BallListener() {
|
addListener(new BallListener() {
|
||||||
@@ -248,7 +247,7 @@ public abstract class BallAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void reconnect(int ttl) {
|
public void reconnect(int ttl) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -7,18 +7,26 @@ import cn.hamster3.mc.plugin.ball.common.event.server.ServerOfflineEvent;
|
|||||||
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
|
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
|
||||||
import cn.hamster3.mc.plugin.ball.common.listener.BallListener;
|
import cn.hamster3.mc.plugin.ball.common.listener.BallListener;
|
||||||
import cn.hamster3.mc.plugin.core.common.constant.CoreConstantObjects;
|
import cn.hamster3.mc.plugin.core.common.constant.CoreConstantObjects;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class BallChannelInboundHandler extends SimpleChannelInboundHandler<String> {
|
import java.util.logging.Level;
|
||||||
public static final BallChannelInboundHandler INSTANCE = new BallChannelInboundHandler();
|
|
||||||
|
|
||||||
private BallChannelInboundHandler() {
|
@ChannelHandler.Sharable
|
||||||
|
public class BallChannelHandler extends SimpleChannelInboundHandler<String> {
|
||||||
|
public static final BallChannelHandler INSTANCE = new BallChannelHandler();
|
||||||
|
|
||||||
|
private BallChannelHandler() {
|
||||||
super(true);
|
super(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext context, String message) {
|
protected void channelRead0(ChannelHandlerContext context, String message) {
|
||||||
|
if ("pong".equals(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
BallMessageInfo info = CoreConstantObjects.GSON.fromJson(message, BallMessageInfo.class);
|
BallMessageInfo info = CoreConstantObjects.GSON.fromJson(message, BallMessageInfo.class);
|
||||||
for (BallListener listener : BallAPI.getInstance().getListeners()) {
|
for (BallListener listener : BallAPI.getInstance().getListeners()) {
|
||||||
try {
|
try {
|
||||||
@@ -143,4 +151,36 @@ public class BallChannelInboundHandler extends SimpleChannelInboundHandler<Strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelActive(@NotNull ChannelHandlerContext context) {
|
||||||
|
BallAPI.getInstance().getLogger().warning("与服务器 " + context.channel().remoteAddress() + " 的连接已可用.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelInactive(@NotNull ChannelHandlerContext context) {
|
||||||
|
context.close();
|
||||||
|
BallAPI.getInstance().getLogger().warning("与服务器 " + context.channel().remoteAddress() + " 的连接已断开.");
|
||||||
|
for (BallListener listener : BallAPI.getInstance().getListeners()) {
|
||||||
|
try {
|
||||||
|
listener.onConnectInactive();
|
||||||
|
} catch (Exception | Error e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BallAPI.getInstance().reconnect(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
|
||||||
|
BallAPI.getInstance().getLogger().log(Level.WARNING, "与服务器 " + context.channel().remoteAddress() + " 通信时出现了一个错误: ", cause);
|
||||||
|
for (BallListener listener : BallAPI.getInstance().getListeners()) {
|
||||||
|
try {
|
||||||
|
listener.onConnectException(cause);
|
||||||
|
} catch (Exception | Error e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -1,17 +1,16 @@
|
|||||||
package cn.hamster3.mc.plugin.ball.common.connector;
|
package cn.hamster3.mc.plugin.ball.common.connector;
|
||||||
|
|
||||||
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
|
|
||||||
import cn.hamster3.mc.plugin.ball.common.listener.BallListener;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||||
import io.netty.handler.codec.LengthFieldPrepender;
|
import io.netty.handler.codec.LengthFieldPrepender;
|
||||||
import io.netty.handler.codec.string.StringDecoder;
|
import io.netty.handler.codec.string.StringDecoder;
|
||||||
import io.netty.handler.codec.string.StringEncoder;
|
import io.netty.handler.codec.string.StringEncoder;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class BallChannelInitializer extends ChannelInitializer<NioSocketChannel> {
|
public class BallChannelInitializer extends ChannelInitializer<NioSocketChannel> {
|
||||||
public static final BallChannelInitializer INSTANCE = new BallChannelInitializer();
|
public static final BallChannelInitializer INSTANCE = new BallChannelInitializer();
|
||||||
@@ -22,34 +21,14 @@ public class BallChannelInitializer extends ChannelInitializer<NioSocketChannel>
|
|||||||
@Override
|
@Override
|
||||||
protected void initChannel(@NotNull NioSocketChannel channel) {
|
protected void initChannel(@NotNull NioSocketChannel channel) {
|
||||||
channel.pipeline()
|
channel.pipeline()
|
||||||
|
.addLast(new IdleStateHandler(0, 7, 0, TimeUnit.SECONDS))
|
||||||
|
.addLast(BallKeepAliveHandler.INSTANCE)
|
||||||
.addLast(new LengthFieldPrepender(8))
|
.addLast(new LengthFieldPrepender(8))
|
||||||
.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 8, 0, 8))
|
.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 8, 0, 8))
|
||||||
.addLast(new StringDecoder(StandardCharsets.UTF_8))
|
.addLast(new StringDecoder(StandardCharsets.UTF_8))
|
||||||
.addLast(new StringEncoder(StandardCharsets.UTF_8))
|
.addLast(new StringEncoder(StandardCharsets.UTF_8))
|
||||||
.addLast(BallChannelInboundHandler.INSTANCE)
|
.addLast(BallChannelHandler.INSTANCE);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelInactive(@NotNull ChannelHandlerContext context) {
|
|
||||||
for (BallListener listener : BallAPI.getInstance().getListeners()) {
|
|
||||||
try {
|
|
||||||
listener.onConnectInactive();
|
|
||||||
} catch (Exception | Error e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
|
|
||||||
for (BallListener listener : BallAPI.getInstance().getListeners()) {
|
|
||||||
try {
|
|
||||||
listener.onConnectException(cause);
|
|
||||||
} catch (Exception | Error e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.hamster3.mc.plugin.ball.common.connector;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.SimpleUserEventChannelHandler;
|
||||||
|
import io.netty.handler.timeout.IdleStateEvent;
|
||||||
|
|
||||||
|
@ChannelHandler.Sharable
|
||||||
|
public class BallKeepAliveHandler extends SimpleUserEventChannelHandler<IdleStateEvent> {
|
||||||
|
public static final BallKeepAliveHandler INSTANCE = new BallKeepAliveHandler();
|
||||||
|
|
||||||
|
private BallKeepAliveHandler() {
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void eventReceived(ChannelHandlerContext context, IdleStateEvent event) {
|
||||||
|
context.channel().writeAndFlush("ping");
|
||||||
|
}
|
||||||
|
}
|
@@ -2,7 +2,7 @@ package cn.hamster3.mc.plugin.ball.server;
|
|||||||
|
|
||||||
import cn.hamster3.mc.plugin.ball.server.command.CommandHandler;
|
import cn.hamster3.mc.plugin.ball.server.command.CommandHandler;
|
||||||
import cn.hamster3.mc.plugin.ball.server.config.ServerConfig;
|
import cn.hamster3.mc.plugin.ball.server.config.ServerConfig;
|
||||||
import cn.hamster3.mc.plugin.ball.server.connector.BallChannelInitializer;
|
import cn.hamster3.mc.plugin.ball.server.connector.BallServerChannelInitializer;
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
@@ -33,8 +33,7 @@ public class Bootstrap {
|
|||||||
.group(loopGroup)
|
.group(loopGroup)
|
||||||
.channel(NioServerSocketChannel.class)
|
.channel(NioServerSocketChannel.class)
|
||||||
.childOption(ChannelOption.TCP_NODELAY, true)
|
.childOption(ChannelOption.TCP_NODELAY, true)
|
||||||
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
.childHandler(BallServerChannelInitializer.INSTANCE);
|
||||||
.childHandler(BallChannelInitializer.INSTANCE);
|
|
||||||
ChannelFuture channelFuture = bootstrap.bind(ServerConfig.getHost(), ServerConfig.getPort());
|
ChannelFuture channelFuture = bootstrap.bind(ServerConfig.getHost(), ServerConfig.getPort());
|
||||||
channelFuture.addListener(future -> {
|
channelFuture.addListener(future -> {
|
||||||
if (future.isSuccess()) {
|
if (future.isSuccess()) {
|
||||||
|
@@ -2,33 +2,49 @@ package cn.hamster3.mc.plugin.ball.server.connector;
|
|||||||
|
|
||||||
import cn.hamster3.mc.plugin.ball.common.data.BallMessageInfo;
|
import cn.hamster3.mc.plugin.ball.common.data.BallMessageInfo;
|
||||||
import cn.hamster3.mc.plugin.ball.server.constant.ConstantObjects;
|
import cn.hamster3.mc.plugin.ball.server.constant.ConstantObjects;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class BallChannelHandler extends SimpleChannelInboundHandler<String> {
|
@ChannelHandler.Sharable
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger("ChannelHandler");
|
public class BallServerChannelHandler extends SimpleChannelInboundHandler<String> {
|
||||||
|
public static final BallServerChannelHandler INSTANCE = new BallServerChannelHandler();
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger("BallServerChannelHandler");
|
||||||
|
|
||||||
public BallChannelHandler() {
|
private BallServerChannelHandler() {
|
||||||
super(true);
|
super(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext context, String message) {
|
protected void channelRead0(ChannelHandlerContext context, String message) {
|
||||||
|
if ("ping".equals(message)) {
|
||||||
|
LOGGER.info("从服务器 {} 上收到一条 ping 消息.", context.channel().remoteAddress());
|
||||||
|
context.writeAndFlush("pong");
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
BallMessageInfo messageInfo = ConstantObjects.GSON.fromJson(message, BallMessageInfo.class);
|
BallMessageInfo messageInfo = ConstantObjects.GSON.fromJson(message, BallMessageInfo.class);
|
||||||
LOGGER.info("从服务器 {} 上收到一条消息: \n {}", messageInfo.getSenderID(), messageInfo);
|
LOGGER.info("从服务器 {} 上收到一条消息: {}", context.channel().remoteAddress(), messageInfo);
|
||||||
BallChannelInitializer.broadcastMessage(messageInfo);
|
BallServerChannelInitializer.broadcastMessage(messageInfo);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.error(String.format("处理消息 %s 时出现错误: ", message), e);
|
LOGGER.error(String.format("处理消息 %s 时出现错误: ", message), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelActive(@NotNull ChannelHandlerContext context) {
|
||||||
|
LOGGER.warn("与服务器 {} 的连接已可用.", context.channel().remoteAddress());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelInactive(ChannelHandlerContext context) {
|
public void channelInactive(ChannelHandlerContext context) {
|
||||||
context.close();
|
context.close();
|
||||||
BallChannelInitializer.CHANNELS.remove(context.channel());
|
synchronized (BallServerChannelInitializer.CHANNELS) {
|
||||||
|
BallServerChannelInitializer.CHANNELS.remove(context.channel());
|
||||||
|
}
|
||||||
LOGGER.warn("与服务器 {} 的连接已断开.", context.channel().remoteAddress());
|
LOGGER.warn("与服务器 {} 的连接已断开.", context.channel().remoteAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,4 +52,4 @@ public class BallChannelHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
|
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
|
||||||
LOGGER.warn("与服务器 {} 通信时出现了一个错误: ", context.channel().remoteAddress(), cause);
|
LOGGER.warn("与服务器 {} 通信时出现了一个错误: ", context.channel().remoteAddress(), cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -9,6 +9,7 @@ import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
|||||||
import io.netty.handler.codec.LengthFieldPrepender;
|
import io.netty.handler.codec.LengthFieldPrepender;
|
||||||
import io.netty.handler.codec.string.StringDecoder;
|
import io.netty.handler.codec.string.StringDecoder;
|
||||||
import io.netty.handler.codec.string.StringEncoder;
|
import io.netty.handler.codec.string.StringEncoder;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -16,20 +17,23 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class BallChannelInitializer extends ChannelInitializer<NioSocketChannel> {
|
public class BallServerChannelInitializer extends ChannelInitializer<NioSocketChannel> {
|
||||||
public static final BallChannelInitializer INSTANCE = new BallChannelInitializer();
|
public static final BallServerChannelInitializer INSTANCE = new BallServerChannelInitializer();
|
||||||
public static final List<Channel> CHANNELS = new ArrayList<>();
|
public static final List<Channel> CHANNELS = new ArrayList<>();
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger("BallServerCentre");
|
private static final Logger LOGGER = LoggerFactory.getLogger("BallServerChannelInitializer");
|
||||||
|
|
||||||
private BallChannelInitializer() {
|
private BallServerChannelInitializer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void broadcastMessage(BallMessageInfo messageInfo) {
|
public static void broadcastMessage(BallMessageInfo messageInfo) {
|
||||||
String string = messageInfo.toString();
|
String string = messageInfo.toString();
|
||||||
for (Channel channel : CHANNELS) {
|
synchronized (CHANNELS) {
|
||||||
channel.writeAndFlush(string);
|
for (Channel channel : CHANNELS) {
|
||||||
|
channel.writeAndFlush(string);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,13 +49,16 @@ public class BallChannelInitializer extends ChannelInitializer<NioSocketChannel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
channel.pipeline()
|
channel.pipeline()
|
||||||
|
.addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS))
|
||||||
|
.addLast(BallServerKeepAliveHandler.INSTANCE)
|
||||||
.addLast(new LengthFieldPrepender(8))
|
.addLast(new LengthFieldPrepender(8))
|
||||||
.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 8, 0, 8))
|
.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 8, 0, 8))
|
||||||
.addLast(new StringDecoder(StandardCharsets.UTF_8))
|
.addLast(new StringDecoder(StandardCharsets.UTF_8))
|
||||||
.addLast(new StringEncoder(StandardCharsets.UTF_8))
|
.addLast(new StringEncoder(StandardCharsets.UTF_8))
|
||||||
.addLast(new BallChannelHandler());
|
.addLast(BallServerChannelHandler.INSTANCE);
|
||||||
|
|
||||||
CHANNELS.add(channel);
|
synchronized (CHANNELS) {
|
||||||
|
CHANNELS.add(channel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
package cn.hamster3.mc.plugin.ball.server.connector;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.SimpleUserEventChannelHandler;
|
||||||
|
import io.netty.handler.timeout.IdleStateEvent;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ChannelHandler.Sharable
|
||||||
|
public class BallServerKeepAliveHandler extends SimpleUserEventChannelHandler<IdleStateEvent> {
|
||||||
|
public static final BallServerKeepAliveHandler INSTANCE = new BallServerKeepAliveHandler();
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger("BallServerKeepAliveHandler");
|
||||||
|
|
||||||
|
private BallServerKeepAliveHandler() {
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void eventReceived(ChannelHandlerContext context, IdleStateEvent event) {
|
||||||
|
context.close();
|
||||||
|
synchronized (BallServerChannelInitializer.CHANNELS) {
|
||||||
|
BallServerChannelInitializer.CHANNELS.remove(context.channel());
|
||||||
|
}
|
||||||
|
LOGGER.warn("由于无法验证连接存活,与服务器 {} 的连接已断开.", context.channel().remoteAddress());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,2 @@
|
|||||||
|
log4j2.loggerContextFactory=org.apache.logging.log4j.core.impl.Log4jContextFactory
|
||||||
|
log4j.configurationFile=log4j2.xml
|
@@ -2,10 +2,10 @@
|
|||||||
<Configuration status="WARN" packages="com.mojang.util">
|
<Configuration status="WARN" packages="com.mojang.util">
|
||||||
<Appenders>
|
<Appenders>
|
||||||
<Console name="SysOut" target="SYSTEM_OUT">
|
<Console name="SysOut" target="SYSTEM_OUT">
|
||||||
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n"/>
|
<PatternLayout pattern="[%d{HH:mm:ss}] [%logger/%level]: %msg%n"/>
|
||||||
</Console>
|
</Console>
|
||||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||||
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n"/>
|
<PatternLayout charset="UTF-8" pattern="[%d{HH:mm:ss}] [%logger/%level]: %msg%n"/>
|
||||||
<Policies>
|
<Policies>
|
||||||
<TimeBasedTriggeringPolicy/>
|
<TimeBasedTriggeringPolicy/>
|
||||||
<OnStartupTriggeringPolicy/>
|
<OnStartupTriggeringPolicy/>
|
||||||
|
Reference in New Issue
Block a user