相对于 java | IO 任务 进行细化。
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.redisc;
import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringEncoder;
import java.io.IOException; import java.net.InetSocketAddress;
public class Client { public static void main(String[] args) throws IOException, InterruptedException { Channel channel = new Bootstrap() .group(new NioEventLoopGroup()) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<NioSocketChannel>() { @Override protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception { nioSocketChannel.pipeline().addLast(new StringEncoder());
} }).connect(new InetSocketAddress("localhost", 8000)) .sync().channel(); channel.writeAndFlush("hello"); } }
|
26 处打断点。
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package com.redisc;
import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.nio.charset.Charset;
import org.slf4j.LoggerFactory; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.Logger;
@Slf4j public class Run {
public static void main(String[] args) throws IOException { LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); Logger rootLogger = loggerContext.getLogger("io.netty"); rootLogger.setLevel(ch.qos.logback.classic.Level.OFF);
new ServerBootstrap() .group(new NioEventLoopGroup(), new NioEventLoopGroup(2)) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception { nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buffer = (ByteBuf) msg; log.debug(buffer.toString(Charset.defaultCharset())); } }); }
}).bind(8000); }
}
|
- 开启服务器
- 开启客户端
- 到断点处,自己发送信息
- 一共开启 3 个独立的客户端「客户端不关闭」
- 重复发送
服务端输出
1 2 3
| 23:16:22.960 [nioEventLoopGroup-3-1] DEBUG com.redisc.Run - hello 23:23:36.518 [nioEventLoopGroup-3-2] DEBUG com.redisc.Run - 123 23:24:04.125 [nioEventLoopGroup-3-1] DEBUG com.redisc.Run - 222
|
因为,worker
线程只有两个,所以,是两个线程分别处理。
但是,这个方式有一个缺陷,就是,当某一个任务处理时常非常长的时候,其他的任务得不到处理。
优化服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| package com.redisc;
import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.nio.charset.Charset;
import org.slf4j.LoggerFactory; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.Logger;
@Slf4j public class Run {
public static void main(String[] args) throws IOException { LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); Logger rootLogger = loggerContext.getLogger("io.netty"); rootLogger.setLevel(ch.qos.logback.classic.Level.OFF);
EventLoopGroup eventLoopGroup = new DefaultEventLoopGroup();
new ServerBootstrap() .group(new NioEventLoopGroup(), new NioEventLoopGroup(2)) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception { nioSocketChannel.pipeline().addLast("handler1",new ChannelInboundHandlerAdapter() { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buffer = (ByteBuf) msg; log.debug(buffer.toString(Charset.defaultCharset())); ctx.fireChannelRead(msg); } }).addLast(eventLoopGroup,"handler2",new ChannelInboundHandlerAdapter(){ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buffer = (ByteBuf) msg; log.debug(buffer.toString(Charset.defaultCharset())); } }); }
}).bind(8000); }
}
|
这里又弄了一个 EventLoopGroup
,并添加到了 pipeline
中,可以专门用来处理耗时时间长的操作。
开启一个客户端,输出如下
1 2
| 23:45:19.310 [nioEventLoopGroup-4-1] DEBUG com.redisc.Run - hello 23:45:19.318 [defaultEventLoopGroup-2-1] DEBUG com.redisc.Run - hello
|