首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

第3期:Java NIO框架——Netty介绍(一)

Netty是什么Netty是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的、高性能的、可伸缩的协议服务器和客户端。Netty是完全基于NIO实现的,其内部实现非常复杂,但是它为我们提供了简单易用的API,我们不必再去编写复杂的逻辑代码实现通信,也不再需要去考虑编码问题,半包读写问题。下图展示了netty的总体架构:

安装

netty不强制依赖特定的外部环境,只需要jdk版本在1.5以上就可以,使用前,我们只需要在pom文件中添加相应版本的netty依赖。

具体的版本可以在https://bintray.com/netty/downloads/netty/中找到本文使用的版本为1.1.19,pom文件中依赖如下:

第一个netty应用

还是老套路,先演示个小demo,再讲原理。接下来,我们将写一个Print Server,即:客户端发送什么内容,服务器就在控制台打印什么内容。

首先,我们来实现一个消息处理的Handler,姑且叫做PrintServerHandler,代码如下:

在这里,我们继承了一个类ChannelInboundHandlerAdapter,可以看看它的源码:

这个类是ChannelInboundHandler的实现,ChannelInboundHandler接口定义了channel的各种事件处理方法。ChannelInboundHandlerAdapter对各个方法的默认实现就是简单触发ChannelHandlerContext中各个事件的回调方法。

在这里我们只需要简单打印内容,而不需要实现所有接口方法。因此,继承ChannelInboundHandlerAdapter实现我们所关心的方法就足够了。

channelRead():接收到消息时,就会调用此方法

exceptionCaught():当处理事件或者IO发生异常时,调用此方法

ByteBuf:netty自定义的字节缓冲数据结构,类比于Java的ByteBuffer,不同于我们平时基于HTTP的应用,netty是直接操作TCP或者UDP传输的数据包,所有的数据最终都是以字节流的方式传输,开发者需要自定义数据编码解码协议,如我们之前介绍的Protobuf就可以作为一种编码解码协议。

ReferenceCountUtil.release(msg):netty中对象的生命周期由它们的引用计数来管理,当引用计数为零时,netty会将资源归还到对象池(netty通过对象池来给对象分配内存),引用计数的对象需要自己在最后一次使用后释放,否则当引用计数对象不可达导致JVM将它们GC掉,而被GC后就不能再访问,也就不能释放引用,最终无法归还到对象池,导致内存泄露。

写完PrintServerHandler后,接下来我们就需要实现服务器代码,并将PrintServerHandler添加到Channel的处理链中。代码如下:

NioEventLoopGroup处理IO操作的事件循环,对于不同的IO类型,netty提供了不同的事件循环实现。

ServerBootstrap启动服务器的helper类。

NioServerSocketChannel指定通道类型,这个类指定NIO通道,相应的还有阻塞式IO通道类型 OioServerSocketChannel和epoll类型通道EpollServerSocketChannel等。

ChannelInitializer配置通道的类,例如这个例子中,我们通过ch.pipeline().addLast()向通道的处理链中添加Handler,我们可以为一个通道添加一系列的Handler(类似于tomcat中的阀)

option(ChannelOption.SO_BACKLOG, 128)配置NioServerSocketChannel的连接队列大小为128.

childOption(ChannelOption.SO_KEEPALIVE, true)设置子通道的连接属性,当设置该选项以后,如果在两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文.

bind()绑定端口,该方法是异步的,它会立即返回的一个Future,但是绑定不一定已经完成,此处我们绑定8090端口。

讲到这里,可能大家还是雾里看花,作者当时也是,官网文档实在是太简洁了。netty是典型的Reactor结构,为了方便理解,我们可以看看下面这种Reactor实现方式。

这种结构,将Reactor分为两个部分,mainReactor负责监听server socket,accept新连接,并将建立的socket分派给subReactor,subReactor负责多路分离已连接的socket,读写网络数据。netty NIO的默认模式就是相当于这种Reactor结构去掉线程池的变种。bossGroup相当于mainReactor,workerGroup相当于subReactor。

最后,我们在main方法里面启动这个服务器就可以了。

下面,我们来测试下服务器,作者在控制台使用telnet来测试我们Print Server。命令如下:

windows下telnet功能默认没有开启,可以通过控制面板->程序和功能->打开或关闭Windows功能->Telnet客户端勾选上并确定即可开启。

如果控制台的输入都是横线,可以通过ctrl+]切换到人类可以理解的自然语言的控制台。

例如:我们通过sen命令发送:hello i am netty

服务器端输出如下:

是不是很简单。

好了,今天的介绍到这里就结束了,demo总是那么简单。下一期我们将深入介绍netty的原理。ps:最近我们厂给新员工布置了份入职前的mini项目,加上毕业前导师要求写几篇专利小论文,更新的可能有点慢了。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180120G0PFO800?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券