Netty 简介
Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。
可参考 掘金简数书 https://juejin.im/post/5bea1d2e51882523d3163657
netty 官方api:https://netty.io/4.1/api/index.html
(netty 5.0 已被官方弃用, 目前netty 最新的jar保持在4.1版本 本文使用netty-all 4.1)
Netty的特点
Netty的对JDK自带的NIO的API进行封装,解决上述问题,主要特点有:
- 设计优雅 适用于各种传输类型的统一API - 阻塞和非阻塞Socket 基于灵活且可扩展的事件模型,可以清晰地分离关注点 高度可定制的线程模型 - 单线程,一个或多个线程池 真正的无连接数据报套接字支持(自3.1起)
- 使用方便 详细记录的Javadoc,用户指南和示例 没有其他依赖项,JDK 5(Netty 3.x)或6(Netty 4.x)就足够了
- 高性能 吞吐量更高,延迟更低 减少资源消耗 最小化不必要的内存复制
- 安全 完整的SSL / TLS和StartTLS支持
- 社区活跃,不断更新 社区活跃,版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会被加入
Netty常见使用常见
Netty常见的使用场景如下:
- 互联网行业 在分布式系统中,各个节点之间需要远程服务调用,高性能的RPC框架必不可少,Netty作为异步高新能的通信框架,往往作为基础通信组件被这些RPC框架使用。 典型的应用有:阿里分布式服务框架Dubbo的RPC框架使用Dubbo协议进行节点间通信,Dubbo协议默认使用Netty作为基础通信组件,用于实现各进程节点之间的内部通信。
- 游戏行业 无论是手游服务端还是大型的网络游戏,Java语言得到了越来越广泛的应用。Netty作为高性能的基础通信组件,它本身提供了TCP/UDP和HTTP协议栈。 非常方便定制和开发私有协议栈,账号登录服务器,地图服务器之间可以方便的通过Netty进行高性能的通信
- 大数据领域 经典的Hadoop的高性能通信和序列化组件Avro的RPC框架,默认采用Netty进行跨界点通信,它的Netty Service基于Netty框架二次封装实现
有兴趣的读者可以了解一下目前有哪些开源项目使用了 Netty:Related projects
本项目jar包管理工具采用gradle
具体优势参考:https://www.jianshu.com/p/2d887a9b69fb
具体配置:https://www.cnblogs.com/kcher90/p/4881623.html
代码实现:
创建一个netty 工程
这个和maven 一样不在赘述
项目结构
jar
public class TestServer { private static int port=8899; public static void main(String[] args) { // 定义两个线程组 // boss 线程组 接受客户端请求 EventLoopGroup bossGroup = new NioEventLoopGroup(); // boss 会将任务分发给 worke线程组 EventLoopGroup workerGroup = new NioEventLoopGroup(); try { // netty启动器 ServerBootstrap serverBootstrap = new ServerBootstrap (); // 绑定线程组 定义使用Nio 协议 并定义字处理器 serverBootstrap.group(bossGroup,workerGroup) .channel(NioServerSocketChannel.class) .childHandler(null); // 设置启动的端口号 ChannelFuture sync = serverBootstrap.bind(port).sync(); sync.channel().closeFuture().sync(); }catch (InterruptedException e) { // 打堆栈信息 e.printStackTrace(); }finally { //优雅的关闭资源 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
public class TestServerInitializer extends ChannelInitializer<SocketChannel> { private static int IDLE_READE_TIME = 20; private static int IDLE_WIRTER_TIME = 20; private static int IDLE_READE_AND_WIRTER_TIME = 40; @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); // 定义读写消息的时间 处理逻辑可指定名字哦 不指定的话 默认使用传入对象的名字 pipeline.addLast("idleStateHandler", new IdleStateHandler(IDLE_READE_TIME, IDLE_WIRTER_TIME, IDLE_READE_AND_WIRTER_TIME)); // 使用netty 内置 的protibuf编码器解码器 pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); pipeline.addLast(new ProtobufEncoder()); // 自定义处理逻辑 pipeline.addLast(new TestServerhandler()); } }
public class TestServerhandler implements ChannelInboundHandler { @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { } @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { } @Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { } @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { } }
浏览器调用
控制台 打印