Some Netty optimizations

This commit is contained in:
Nanit 2020-11-29 15:00:17 +02:00
parent b4b40d36e0
commit 7ba831d1a6
10 changed files with 905 additions and 849 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
gradlew gradlew
gradlew.bat gradlew.bat
build/ build/
settings.yml

View File

@ -14,7 +14,7 @@ dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12' testCompile group: 'junit', name: 'junit', version: '4.12'
compile files('libs/napi-configurate-yaml-1.0.jar') compile files('libs/napi-configurate-yaml-1.0.jar')
compile group: 'org.yaml', name: 'snakeyaml', version: '1.27' compile group: 'org.yaml', name: 'snakeyaml', version: '1.27'
compile group: 'io.netty', name: 'netty-handler', version: '4.1.54.Final' compile group: 'io.netty', name: 'netty-all', version: '4.1.54.Final'
compile group: 'net.kyori', name: 'adventure-nbt', version: '4.1.1' compile group: 'net.kyori', name: 'adventure-nbt', version: '4.1.1'
} }

View File

@ -182,23 +182,23 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
return; return;
} }
sendPacket(PACKET_LOGIN_SUCCESS); writePacket(PACKET_LOGIN_SUCCESS);
updateState(State.PLAY); updateState(State.PLAY);
server.getConnections().addConnection(this); server.getConnections().addConnection(this);
sendPacket(PACKET_JOIN_GAME); writePacket(PACKET_JOIN_GAME);
sendPacket(PACKET_PLAYER_ABILITIES); writePacket(PACKET_PLAYER_ABILITIES);
sendPacket(PACKET_PLAYER_POS); writePacket(PACKET_PLAYER_POS);
sendPacket(PACKET_PLAYER_INFO); writePacket(PACKET_PLAYER_INFO);
sendKeepAlive();
if (PACKET_BOSS_BAR != null) if (PACKET_BOSS_BAR != null)
sendPacket(PACKET_BOSS_BAR); writePacket(PACKET_BOSS_BAR);
if (PACKET_JOIN_MESSAGE != null) if (PACKET_JOIN_MESSAGE != null)
sendPacket(PACKET_JOIN_MESSAGE); writePacket(PACKET_JOIN_MESSAGE);
sendKeepAlive();
} }
public void disconnectLogin(String reason){ public void disconnectLogin(String reason){
@ -227,6 +227,14 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
channel.writeAndFlush(packet).addListener(ChannelFutureListener.CLOSE); channel.writeAndFlush(packet).addListener(ChannelFutureListener.CLOSE);
} }
public void writePacket(Object packet){
if (isConnected()) channel.write(packet, channel.voidPromise());
}
public void flushPackets(){
if (isConnected()) channel.flush();
}
public boolean isConnected(){ public boolean isConnected(){
return channel.isActive(); return channel.isActive();
} }

View File

@ -17,6 +17,7 @@ public class PreRenderedPacket implements PacketOut {
ByteMessage renderedMessage = ByteMessage.create(); ByteMessage renderedMessage = ByteMessage.create();
packet.encode(renderedMessage); packet.encode(renderedMessage);
this.message = renderedMessage.toByteArray(); this.message = renderedMessage.toByteArray();
renderedMessage.release();
return this; return this;
} }

View File

@ -1,8 +1,15 @@
package ru.nanit.limbo.server; package ru.nanit.limbo.server;
import io.netty.bootstrap.ServerBootstrap; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.ResourceLeakDetector;
import napi.configurate.serializing.NodeSerializers; import napi.configurate.serializing.NodeSerializers;
import ru.nanit.limbo.configuration.LimboConfig; import ru.nanit.limbo.configuration.LimboConfig;
import ru.nanit.limbo.configuration.SocketAddressSerializer; import ru.nanit.limbo.configuration.SocketAddressSerializer;
@ -14,8 +21,7 @@ import ru.nanit.limbo.world.DimensionRegistry;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public final class LimboServer { public final class LimboServer {
@ -23,6 +29,10 @@ public final class LimboServer {
private LimboConfig config; private LimboConfig config;
private Connections connections; private Connections connections;
private DimensionRegistry dimensionRegistry; private DimensionRegistry dimensionRegistry;
private ScheduledFuture<?> keepAliveTask;
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
public LimboConfig getConfig(){ public LimboConfig getConfig(){
return config; return config;
@ -39,6 +49,8 @@ public final class LimboServer {
public void start() throws Exception { public void start() throws Exception {
Logger.info("Starting server..."); Logger.info("Starting server...");
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
NodeSerializers.register(SocketAddress.class, new SocketAddressSerializer()); NodeSerializers.register(SocketAddress.class, new SocketAddressSerializer());
NodeSerializers.register(InfoForwarding.class, new InfoForwarding.Serializer()); NodeSerializers.register(InfoForwarding.class, new InfoForwarding.Serializer());
NodeSerializers.register(PingData.class, new PingData.Serializer()); NodeSerializers.register(PingData.class, new PingData.Serializer());
@ -56,21 +68,55 @@ public final class LimboServer {
ClientConnection.preInitPackets(this); ClientConnection.preInitPackets(this);
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); startBootstrap();
executor.scheduleAtFixedRate(this::broadcastKeepAlive, 0L, 5L, TimeUnit.SECONDS);
new ServerBootstrap() keepAliveTask = workerGroup.scheduleAtFixedRate(this::broadcastKeepAlive, 0L, 5L, TimeUnit.SECONDS);
.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(NioServerSocketChannel.class) Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "NanoLimbo shutdown thread"));
.childHandler(new ClientChannelInitializer(this))
.localAddress(config.getAddress())
.bind();
Logger.info("Server started on %s", config.getAddress()); Logger.info("Server started on %s", config.getAddress());
} }
private void startBootstrap(){
Class<? extends ServerChannel> channelClass;
if (Epoll.isAvailable()){
bossGroup = new EpollEventLoopGroup(1);
workerGroup = new EpollEventLoopGroup(4);
channelClass = EpollServerSocketChannel.class;
Logger.debug("Using Epoll transport type");
} else {
bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup(4);
channelClass = NioServerSocketChannel.class;
Logger.debug("Using Java NIO transport type");
}
new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(channelClass)
.childHandler(new ClientChannelInitializer(this))
.childOption(ChannelOption.TCP_NODELAY, true)
.localAddress(config.getAddress())
.bind();
}
private void broadcastKeepAlive(){ private void broadcastKeepAlive(){
connections.getAllConnections().forEach(ClientConnection::sendKeepAlive); connections.getAllConnections().forEach(ClientConnection::sendKeepAlive);
} }
private void stop(){
if (keepAliveTask != null){
keepAliveTask.cancel(true);
}
if (bossGroup != null){
bossGroup.shutdownGracefully();
}
if (workerGroup != null){
workerGroup.shutdownGracefully();
}
}
} }

View File

@ -19,7 +19,7 @@ public final class Logger {
} }
public static void debug(Object msg, Object... args){ public static void debug(Object msg, Object... args){
print(Level.INFO, msg, null, args); print(Level.DEBUG, msg, null, args);
} }
public static void warning(Object msg, Object... args){ public static void warning(Object msg, Object... args){