1 Netty模型
网络异常,图片无法展示
|
- Netty抽象出两组线程池 BossGroup 专门负责接收客户端的连接, WorkerGroup 专门负责网络的读写
- BossGroup 和 WorkerGroup 类型都是 NioEventLoopGroup
- NioEventLoopGroup 相当于一个事件循环组, 这个组中含有多个事件循环 ,每一个事件循环是 NioEventLoop4) NioEventLoop 表示一个不断循环的执行处理任务的线程,每个 NioEventLoop 都有一个 selector , 用于监听绑定在其上的 socket的网络通讯
- NioEventLoopGroup 可以有多个线程, 即可以含有多个 NioEventLoop
- 每个 Boss NioEventLoop 循环执行的步骤有 3步
- 轮询 accept 事件
- 处理 accept 事件 , 与 client建立连接 , 生成 NioScocketChannel , 并将其注册到某个 worker NIOEventLoop 上的 selector
- 处理任务队列的任务 , 即 runAllTasks
- 每个 Worker NIOEventLoop 循环执行的步骤
- 轮询 read, write 事件
- 处理 i/o事件,即 read , write 事件,在对应 NioScocketChannel 处理
- 处理任务队列的任务 , 即 runAllTasks
- 每个Worker NIOEventLoop 处理业务时,会使用pipeline(管道), pipeline 中包含了 channel , 即通过pipeline可以获取到对应通道, 管道中维护了很多的处理器
2 Netty实现HTTP服务的基本流程
网络异常,图片无法展示
|
3 代码实现
依赖:
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.65.Final</version> </dependency> 复制代码
HttpServer.java
/** * @desc: Http服务端 * @author: YanMingXin * @create: 2021/8/11-10:10 **/ public class HttpServer extends ChannelInitializer<SocketChannel> { /** * 初始化管道,向管道加入处理器 * * @param ch */ @Override protected void initChannel(SocketChannel ch) { //得到管道 ChannelPipeline pipeline = ch.pipeline(); //HttpServerCodec是 netty 默认提供的处理http的编解码器 作用:codec =>[coder - decoder] pipeline.addLast("MyHttpServerCodec", new HttpServerCodec()); //增加一个自定义的 handler pipeline.addLast("MyTestHttpServerHandler", new HttpServerHandler()); } } 复制代码
HttpServerHandler.java
/** * @desc: Http请求处理器 * 1. SimpleChannelInboundHandler 是 ChannelInboundHandlerAdapter * 2. HttpObject 客户端和服务器端相互通讯的数据被封装成 HttpObject * @author: YanMingXin * @create: 2021/8/11-10:11 **/ public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject> { /** * channelRead0 读取客户端数据 * * @param ctx * @param msg */ @Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) { //判断 msg 是不是 HttpRequest请求 if (msg instanceof HttpRequest) { System.out.println("当前管道:" + ctx.pipeline().hashCode() + " 当前HTTP处理器:" + this.hashCode()); System.out.println("msg 类型:" + msg.getClass()); System.out.println("客户端IP:" + ctx.channel().remoteAddress()); //回复信息给浏览器 ByteBuf content = Unpooled.copiedBuffer("Hello, I am Netty Http Server!", CharsetUtil.UTF_8); //构造一个 http的相应,即 HttpResponse FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain"); response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); //将构建好 response返回 ctx.writeAndFlush(response); } } } 复制代码
TestServer.java
/** * @desc: 开启HTTP服务 * @author: YanMingXin * @create: 2021/8/11-10:11 **/ public class TestServer { public static void main(String[] args) throws Exception { //实例化BoosGroup,初始线程为1 EventLoopGroup bossGroup = new NioEventLoopGroup(1); //实例化NioEventGroup EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //实例化ServerBootstrap ServerBootstrap serverBootstrap = new ServerBootstrap(); //加入Selector serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new HttpServer()); //获取Channel并绑定8888端口开启异步 ChannelFuture channelFuture = serverBootstrap.bind(8888).sync(); channelFuture.channel().closeFuture().sync(); } finally { //关闭操作 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } 复制代码
测试:
网络异常,图片无法展示
|