Netty在游戏服务器开发中的应用

发表于2018-05-31
评论0 5.3k浏览
一、为什么选择Netty

游戏服务器所处理的数据是面是多客户端的。而且游戏对数据处理的响应速度要求非常高,要不然就会出现服务器卡的现象,影响玩家在游戏中的体验。要处理好游戏数据的响应速度,首先第一步就是解决网络传输这一层,这相当于数据出入服务器的大门,如果这一块出现了慢的问题,那将会直接影响整个游戏服务器的性能。

说到前后端的数据通信,我们首选想的是Socket,没错,这是唯一的选择,就算是http协议,他底层也是封装的SocketTCP/IP协议。SocketTcp/IP协议好的处是一次建立连接,可以多次通信,不用每次都建立通信通道,节省系统资源。但是在Socket设计模式上,有阻塞和非阻塞之分,或者叫Bio或Nio。Java最新的版本目前都支持NIO,它就是为了处理数据并发,提高系统性能而生的。毫无疑问,游戏服务器只能使用NIO来实现。但是Java原生的NIOAPI非常繁琐,它虽然给开发者留足了灵活性,但是也给开发者建立一个高性能,高安全性带来了考验。如果开发者经验不足,自己去开发一套适用的NIO处理框架,可能需要很多测试或者会出现很多意外的了Bug,虽然最后都可以解决,但是延长了开发时间和付出一些额外的代价。

而Netty,做为一个经久考验和实际应用的网络框架,功能都得到了实际测试,安全性高。利用netty,可以为我们开发省去不少的时间和维护精力,至少我们不用时时担心网络层会出现什么大的问题。

二、Netty的异步处理

在IO编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者IO多路复用技术进行处理。IO多路复用技术通过把多个IO的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降低了系统的维护工作量,节省了系统资源。

JDK1.4提供了对非阻塞IO(NIO)的支持,JDK1.5_update10版本使用epoll替代了传统的select/poll,极大的提升了NIO通信的性能。Netty的IO线程NioEventLoop由于聚合了多路复用器Selector,可以同时并发处理成百上千个客户端Channel,由于读写操作都是非阻塞的,这就可以充分提升IO线程的运行效率,避免由于频繁IO阻塞导致的线程挂起。另外,由于Netty采用了异步通信模式,一个IO线程可以并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞IO一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。

三、零拷贝

Netty的“零拷贝”主要体现在如下三个方面:

1、Netty的接收和发送ByteBuffer采用DIRECTBUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAPBUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。

2、Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer。

3、Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。

四、内存池

随着JVM虚拟机和JIT即时编译技术的发展,对象的分配和回收是个非常轻量级的工作。但是对于缓冲区Buffer,情况却稍有不同,特别是对于堆外直接内存的分配和回收,是一件耗时的操作。为了尽量重用缓冲区,Netty提供了基于内存池的缓冲区重用机制

五、高效的Reactor线程模型

常用的Reactor线程模型有三种,分别如下:
1、Reactor单线程模型;
2、Reactor多线程模型;
3、主从Reactor多线程模型

Reactor单线程模型,指的是所有的IO操作都在同一个NIO线程上面完成,NIO线程的职责如下:
1、作为NIO服务端,接收客户端的TCP连接;
2、作为NIO客户端,向服务端发起TCP连接;
3、读取通信对端的请求或者应答消息;
4、向通信对端发送消息请求或者应答消息。
来自:https://blog.csdn.net/y13156556538/article/details/72639346

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引