物联网 基于netty入门与线程模型探秘简述

物联网 基于netty入门与线程模型探秘

简述

理解 Netty 的核心组件(Channel、ChannelHandler、ChannelPipeline),掌握其高性能的 Reactor 线程模型,并通过一个完整的 Echo 示例快速入门

源码

netty-sample-00https://gitee.com/kcnf-webrtc/iot-sample/tree/master/netty/netty-sample-00

Netty 核心组件

组件 作用
Channel 代表一个网络连接(如 NIO SocketChannel),负责读写数据。
ChannelHandler 处理 I/O 事件或拦截数据(如解码、业务逻辑)。可分为入站(Inbound)和出站(Outbound)。
ChannelPipeline 管理 ChannelHandler 的链表,数据流经 Pipeline 依次被各 Handler 处理。
EventLoopGroup 一组 EventLoop,每个 EventLoop 绑定一个线程,负责处理多个 Channel 的 I/O 事件。
Bootstrap / ServerBootstrap 引导类,配置并启动 Netty 客户端/服务器。

Reactor 线程模型

  • 三种典型 Reactor 模型
模型 描述 Netty 对应配置
单线程 一个 Reactor 线程同时处理连接、读、写。 EventLoopGroup 大小为 1。
多线程 一个 Reactor 线程处理连接,多个工作线程处理读写。 bossGroup 大小为 1,workerGroup 大小为 CPU*2。
主从多线程 多线程 Reactor 处理连接,多线程 Reactor 处理读写(用于更高并发)。 bossGroup 大小 >1,workerGroup 大小 >1。
  • Netty 默认实现(主从多线程变种)

BossGroup:监听端口,接收新连接,将 SocketChannel 注册到 WorkerGroup
WorkerGroup:负责已连接的读写 I/O 及业务处理(通常业务 Handler 可再异步执行)

复制代码
// 典型配置
EventLoopGroup bossGroup = new NioEventLoopGroup(1);   // 单线程处理连接
EventLoopGroup workerGroup = new NioEventLoopGroup();  // 默认 CPU 核数 * 2

每个 EventLoop 内部有一个 Selector 和任务队列,一个 EventLoop 服务于多个 Channel,保证同一 Channel 的事件串行执行

添加pom依赖

复制代码
 <dependencies>
        <!-- Netty 核心依赖 -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

server 代码

复制代码
package com.jysemel.iot;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.nio.charset.StandardCharsets;

public class EchoServer {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建线程组:boss 接受连接,worker 处理 I/O
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)      // 指定 NIO 传输
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 添加编解码器(处理粘包/拆包可用 LengthFieldBasedFrameDecoder,这里简单演示)
                            pipeline.addLast(new StringDecoder(StandardCharsets.UTF_8));
                            pipeline.addLast(new StringEncoder(StandardCharsets.UTF_8));
                            // 添加业务 Handler
                            pipeline.addLast(new EchoServerHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)      // 连接队列大小
                    .childOption(ChannelOption.SO_KEEPALIVE, true); // 长连接

            // 2. 绑定端口并启动
            ChannelFuture future = bootstrap.bind(8181).sync();
            System.out.println("Echo 服务器启动,端口 8181");
            future.channel().closeFuture().sync();  // 等待直到服务器关闭
        } finally {
            // 3. 优雅关闭
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

client 代码

复制代码
package com.jysemel.iot;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.nio.charset.StandardCharsets;

public class EchoClient {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new StringDecoder(StandardCharsets.UTF_8));
                            pipeline.addLast(new StringEncoder(StandardCharsets.UTF_8));
                            pipeline.addLast(new EchoClientHandler());
                        }
                    });

            ChannelFuture future = bootstrap.connect("127.0.0.1", 8181).sync();
            future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

运行与验证

复制代码
先启动 EchoServer,再启动 EchoClient。
控制台输出:
服务端返回: Hello, Netty!
服务器输出:收到: Hello, Netty!
相关推荐
摇滚侠6 分钟前
JDBC 基础到高级一套通关!高级篇 28-40
java
Smoothcloud润云1 小时前
5大功能精修,重构AI算力使用体验!
java·人工智能·windows·算法·重构·编辑器·sublime text
我是唐青枫1 小时前
Java MyBatis-Flex 实战指南:从 BaseMapper 到 QueryWrapper 的轻量 ORM 用法
java·开发语言·mybatis
顺风尿一寸1 小时前
Java Native 方法底层原理深度解析:从 JNI 注册到 Native Wrapper 生成
java
极客先躯1 小时前
高级java每日一道面试题-2026年01月18日-实战篇[Docker]-如何清理仓库中的旧镜像?
java·运维·docker·容器
iiiiyu2 小时前
IO流(二)
java·开发语言·数据结构·编程语言
白露与泡影2 小时前
牛客网大厂Java面试题全集(2026版,附答案)
java·开发语言
_Evan_Yao2 小时前
一文搞懂:Git分支管理与团队协作规范——从GitFlow到GitHub Flow,从rebase到merge,打造高效协作流
java·git·后端·github
未若君雅裁2 小时前
AQS 与 ReentrantLock:队列同步器与可重入锁
java
码语智行2 小时前
系统启动时初始化数据功能分析
java·spring boot