2

java | 分工细化

 1 year ago
source link: https://benpaodewoniu.github.io/2023/01/23/java189/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

java | 分工细化 | 犀牛的博客

姑苏城外一茅屋,万树梅花月满天

相对于 java | IO 任务 进行细化。

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 处打断点。

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 的两个参数
// boss 和 worker
// boss 只负责 ServerSocketChannel 上 accept 事件
// worker 只负责 socketChannel 上读写
// 请参考 https://benpaodewoniu.github.io/2023/01/08/java184/
.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 个独立的客户端「客户端不关闭」

服务端输出

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 线程只有两个,所以,是两个线程分别处理。

但是,这个方式有一个缺陷,就是,当某一个任务处理时常非常长的时候,其他的任务得不到处理。

优化服务器

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 的两个参数
// boss 和 worker
// boss 只负责 ServerSocketChannel 上 accept 事件
// worker 只负责 socketChannel 上读写
// 请参考 https://benpaodewoniu.github.io/2023/01/08/java184/
.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); // 必须加上这句话才能传递给下一个 pipline
}
}).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 中,可以专门用来处理耗时时间长的操作。

开启一个客户端,输出如下

23:45:19.310 [nioEventLoopGroup-4-1] DEBUG com.redisc.Run - hello
23:45:19.318 [defaultEventLoopGroup-2-1] DEBUG com.redisc.Run - hello

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK