Spark为何使用Netty通信框架替代Akka

xiaoxiao2021-02-28  16

解决方案

一直以来,基于Akka实现的RPC通信框架是Spark引以为豪的主要特性,也是与Hadoop等分布式计算框架对比过程中一大亮点,但是时代和技术都在演化,从Spark1.3.1版本开始,为了解决大数据块(如shuffle)的传输问题,Spark引入了Netty通信框架,到了1.6.0版本,Netty居然完全取代了Akka,承担Spark内部所有的RPC通信以及数据流传输。

网络IO扫盲贴

在Linux操作系统层面,网络操作即未IO操作,总共有:阻塞式,非阻塞式,复用模型,信号驱动和异步五中IO模型。其中

阻塞式IO操作请求发起以后,从网卡等待/读取数据,内核/到用户态的拷贝,整个IO过程,用户的线程都是出于阻塞状态。非阻塞与阻塞的区别在于应用层不会等待网卡接收数据,即在内核数据未准备好之前,IO将返回EWOULDBLOCK,用户端通过主动轮询,知道内核态数据准备好,然后再主动发起内核态数据到用户拷贝读操作(阻塞)。在非阻塞IO中,每个IO的应用层代码都需要主动地去内核态轮询知道数据OK,在IO复用模型中,将“轮询/事件驱动”的工作交给一个单独的select/epoll的IO句柄去做,即所谓的IO复用。信号驱动IO是向内核注册信号回调函数,在数据OK的时候自动触发回调函数,进而可以在回调函数中启用数据的读取,即由内核告诉我们合适可以开始IO操作异步IO是将IO数据读取到用户内存的函数注册到系统中,在内核数据OK的时候,自动完成内核态到用户态的拷贝,并通知应用态数据已经读取完成,即由内核告诉我们何时IO操作已经完成。

JAVA IO也经历了上面几次演化,从最早的BIO(非阻塞式/非阻塞IO),到1.4版本的NIO(IO复用),到1.7版本的NIO2.0/AIO(异步IO);基于早期BIO来实现高并发网络服务器都是依赖多线程来实现,但是线程开销大,BIO的瓶颈明显,NIO的出现解决了这一大难题,基于IO复用解决了IO高并发;但是NIO也有几个缺点:

API可用性较低(拿ByteBuffer来说,共用一个current指针,读写切换需要进行flip和rewind,相当麻烦);仅仅是API,如果想在NIO上实现一个网络模型,还需要自己写很多比如线程池,解码,半包/粘包,限流等逻辑;最后就是著名的NIO-Epoll死循环的BUG,因为这几个原因,促使了很多JAVA-IO通信框架的出现,Netty就是其中一员,他也因为高度的稳定性,功能性,性能等特性,成为首选。

那么Netty和JDK-NIO之间到底是什么关系?是JDK-NIO的封装还是重写?首先是NIO的上层封装,Netty提供了NioEventLoopGroup/NioSocketChannel/NioServerSocketChannel的组合来完成实际IO操作,继而在此之上实现数据流Pipeline以及EventLoop线程池等功能。另外他有重写了NIO,JDK-NIO底层是基于Epoll的LT模式来实现,而Netty是基于Epoll的ET模式实现的一组IO操作EpollEventLoopGroup/EpollSocketChannel/EpollServerSocketChannel;Netty对两种实现进行完美的封装,可以根据业务的需求来选择不同的实现(Epoll的ET和LT模式真的有很大的性能差别吗?但从Epoll的角度来看,ET肯定是比LT要性能好那么一点。但是如果为了编码简洁性,LT还是首选,ET如果用户层逻辑实现不够优美,相比ET还会带来更大的性能开销;不过Netty这么大的开源团队,相信ET模式应该实现的不错吧!!纯属猜测!!)。

那么Akka又是什么东西?从Akka出现背景来说,它是基于Actor的RPC通信系统,它的核心概念也是Message,它是基于协程的,性能不容置疑;基于scala的偏函数,易用性也没有话说,但是它毕竟只是RPC通信,无法适用大的package/stream的数据传输,这也是Spark早期引入Netty的原因。

那么Netty为什么可以取代Akka?首先不容置疑的是Akka可以做到的,Netty也可以做到,但是Netty可以做到,Akka却无法做到,原因是啥?在软件栈中,Akka相比Netty要Higher一点,它专门针对RPC做了很多事情,而Netty相比更加基础一点,可以为不同的应用层通信协议(RPC,FTP,HTTP等)提供支持,在早期的Akka版本,底层的NIO通信就是用的Netty;其次一个优雅的工程师是不会允许一个系统中容纳两套通信框架,恶心!最后,虽然Netty没有Akka协程级的性能优势,但是Netty内部高效的Reactor线程模型,无锁化的串行设计,高效的序列化,零拷贝,内存池等特性也保证了Netty不会存在性能问题。

那么Spark是怎么用Netty来取代Akka呢?一句话,利用偏函数的特性,基于Netty“仿造”出一个简约版本的Actor模型!!

转载请注明原文地址: https://www.6miu.com/read-1950013.html

最新回复(0)