上周有个后端同事接了个推送服务,三万长连接同时在线,他上来就用 SpringBoot 写了个接口循环推,结果内存直接飙到 90%,被组长叫去重写。这类问题根子上就是没分清 Netty 和 Spring 各自干啥的。
一句话说透,Spring 是帮你搭业务架子的,Netty 是帮你管网络连接的。一个管业务分层,一个管字节怎么收发,压根不是二选一的关系。
一个管请求进来之后,一个管请求怎么进来
SpringMVC 跑在 Tomcat 或者 Jetty 上面,走的是一请求一线程模型,请求进来分配个线程,查库调接口,最后返回。这个模型写 CRUD 爽到飞起,代码按 Controller 加 Service 加 Mapper 一摆就完事。但连接数一到几万,线程切换开销直接把机器拖死。
Netty 走的是 NIO 加事件循环,少量线程就能抱住几万个连接,数据来了回调你的 Handler。它不管什么注解注入,也不管事务,就是纯粹的收字节、切包、回字节。所以做 IM、推送、游戏网关这种长连接,基本都是 Netty 打底。
开发体验差了不止一个量级
Spring 写个接口加两行注解就能跑,参数校验、事务回滚、全局异常全给你包好,新人一天就能上手。Netty 得自己管粘包拆包,心跳断线重连,ByteBuf 用完还得手动释放,漏一次就内存泄漏,半夜被告警短信吵醒都是常事。
粘包这事最典型,TCP 是流,客户端连发两条消息,服务端可能一次全收到。Netty 里得配 LengthFieldBasedFrameDecoder 或者自己定分隔符,Spring 里根本感知不到这层,因为容器全帮你挡了。
实际项目里正确的叠法
常见做法是 Netty 只做接入层,负责把连接抱牢、做编解码和心跳,解出来的业务包扔给 Spring 那边的 Service 处理。下单扣库存这些重逻辑还是 Spring 的事务最靠谱,别用 Netty 重写一遍,纯属找罪受。
- 纯后台管理系统:直接 SpringBoot,别碰 Netty
- 聊天推送行情网关:Netty 做接入,业务调 Spring 的服务
- 想两头兼顾:看看 Spring 里的 WebFlux,底层就是 Netty 扛连接
取舍很实在,连接多、消息碎、延迟敏感就上 Netty,业务重、事务多、人力紧就守住 Spring,别拿锤子去拧螺丝。