看了《Netty权威指南》,真实枯燥,完全看不下去,打算这么学习下Netty。
前:预备知识
tcp/ip协议
摘自:TCP/IP协议分层模型
应用层是啥?
你想用java写一个网络程序,你写的这个程序就是应用层
所以QQ、微信、以及你正在使用的浏览器,都是应用层
应用层数据是啥?
你想通过你前面写的这个网络程序发一个字符串”are you ok”到对方,这个字符串”are you ok”就是应用层数据
对方回你一句”yes, I am fine”,这个”yes, I am fine”也是应用层数据
传输层是啥
传输层要么走TCP协议,要么走UDP协议,没有第三种协议
TCP协议的通信双方,需要知道彼此都在家呆着,且由客户端主动发起连接
UDP协议,客户端知道服务器家住在哪,但并不知道服务器在不在家,扔条消息去服务器家,如果服务器不在家这条消息就被丢了
应用层把数据丢给传输层后,传输层把数据进行一下包装,包装纸上面写着“源端口、目的端口、序号、确认序号、检验和等TCP自身的数据”
传输层把数据给应用层时,会拆开对方的包装纸,应用层只看得到对方应用层发的数据
传输层数据是啥
就是应用层的数据带上一张包装纸后的数据
这层包装纸就是传输层的元数据或叫头部数据
为什么要带包装纸?因为要实名呀,现在快递都要实名了^_^
1 Netty架构
2 基本概念
Buffer: ByteBuffer
3 实战项目
3.1 IM聊天类
Netty 入门与实战:仿写微信 IM 即时通讯系统
来自lightningMan大佬的:
https://github.com/lightningMan
Netty 入门与实战:仿写微信 IM 即时通讯系统
使用Netty实现了单聊和群聊,将Netty从基础到项目一体化,可以说是入门Netty不错的选择。
3.2 RPC类
SOFABolt
蚂蚁金融服务集团开发的一套基于 Netty 实现的网络通信框架。
地址:https://github.com/sofastack/sofa-bolt
SOFABolt 是蚂蚁金融服务集团开发的一套基于 Netty 实现的网络通信框架。
为了让 Java 程序员能将更多的精力放在基于网络通信的业务逻辑实现上,而不是过多的纠结于网络底层 NIO 的实现以及处理难以调试的网络问题,Netty 应运而生。
为了让中间件开发者能将更多的精力放在产品功能特性实现上,而不是重复地一遍遍制造通信框架的轮子,SOFABolt 应运而生。
目前该产品已经运用在了蚂蚁中间件的微服务 (SOFARPC)、消息中心、分布式事务、分布式开关、以及配置中心等众多产品上。
大厨小鲜——基于Netty自己动手实现RPC框架
3.3 MQTT类
陆陆大神的:https://github.com/1ssqq1lxr/iot_push
MQTT 协议是 IBM 开发的即时通讯协议,相对于 IM 的实际上的准标准协议 XMPP 来说,MQTT 更小,更快,更轻量。MQTT 适合于任何计算能力有限,工作在低带宽、不可靠的网络中的设备,包括手机,传感器等等。
3.4 Web框架
4 理解Netty
转自:https://www.zhihu.com/question/24322387/answer/2302486578
这玩意其实用的地方非常普遍,可以说,一般基于 Java 的中间件,凡是需要用到底层通信能力, 都会基于 Netty 来构建。毕竟已经有了优秀的轮子何必自己再造一个可能都是bug的轮子呢?
所以 Netty 是一个底层通信框架,那何为底层通信框架?不就是通信嘛, 主要功能就是让服务端和客户端之间得以“交流”。
在有一定的基础下,我们可以闭上眼睛思考这样的框架应该需要哪些核心要点。 拿 Netty 举例,可以假设老板给我个任务,要我写一个底层通信框架,我要怎么写? 都有哪些方面需要考虑?
通过这种驱动式自我提问,来推动自己不得不去思考, 被动让脑子转!这样会让你理解地更深刻。下面我们一起来思考下这个问题。
写一个底层通信框架需要考虑哪些?
关于通信,我第一个想到的就是网络协议,
好在一些协议底层都已经帮我们实现,但是要通信还是避免不了和底层打交道。
比如,要调用操作系统的接口来发送数据给远程,如果要我们去实现还得去了解操作系统的各种接口,感觉有点麻烦。
但好在,这样底层的交互,身为一门语言肯定是已经提供了封装的,对于 Java 而言提供了 NIO。
所以,通信的一些基本操作,包括创建 socket、建立连接、发送消息、接收消息等等,这些 NIO 都提供了。这样岂不是直接用 Java NIO 就行了?
用肯定是要用的,但是这种语言类库提供的接口,需要给予上层更多自由的配置,也就是它能提供精细化地调用,但是对于通常的使用而言过于复杂。
就好下面这张图,对于已经深耕的专业人员来说,可能极好。
但是对于普通使用者而言,上手成本就太高了。
简而言之,就是封装的不够完美,不够简单。我们追求的是仪表盘只需暴露几个键,只要按几个键应用即可成功的运行,
所以我们需要基于 Java NIO 做封装,把一些复杂的配置隐藏起来,对外暴露出更加易用的接口。
所以,我们的第一个目标已经明确了,利用 Java NIO 提供的能力并基于它做封装,尽量简化配置,易于使用。(其实框架都这样,例如 Mybatis 之类的,还是得基于 JDBC 的能力,在此之上封装)
大体目标有了,然后得丰富一下功能性。由于网络通信都是字节流,所以我们还要提供编解码的支持,且需要支持各种协议,毕竟身为一个框架需要供各种团队使用,每个团队涉及的通信协议可能有所不同,
因此框架需要尽可能的支持市面上常见的应用层协议,比如 HTTP、DNS 等等,当然也要方便的定制自定义协议。
对了,还需要考虑粘包和拆包等问题,支持分隔符切分、固定长度等等,给予“客户”更多方便的选择!
实现上面这些,一些基本的通信需求满足了,
然后再考虑性能。身为一个网络通信框架,我们需要考虑连接的管理,毕竟资源是有限的,所以合理的连接数很重要,
因此我们需要提供心跳、检查空闲连接等功能来管理连接。
还有 I/O 模型,现在这个“行情”不说了,直接多路复用,用更少的线程处理更多的请求, hold 住海量连接。
等啥时候 Linux 完美支持 AIO 了再上个 AIO,不过 Linux 提供了 epoll ,
所以如果服务是跑在 Linux 上的就用 epoll,反之用 select。
对了,网上经常还会提到零拷贝,这个肯定是要的,比如发送一些文件的时候直接利用零拷贝减少拷贝次数,
并且还能用 DirectBuffer 将数据放置堆外,省去了堆内外的一次拷贝,提升性能。
当然对应的还得需要做好内存管理,这个我想可以参考参考 Linux 的伙伴系统。
关于线程模型,也得研究研究,例如 accept 线程与 reactor 线程(I/O线程)与业务处理线程的编排等等,在大流量下合理的线程模型会减少线程切换次数,提高性能,这很关键。
然后一个框架想要易用,不仅要适配不同团队的不同需求,还需方便适配同一团队的需求变更。这就需要框架必须要提供十分方便的定制化、插件化功能,这又该怎么设计?
责任链模式就适合这个,配合事件驱动,好像挺完美的。我个人认为,身为一个框架,提供诸多开箱即用的功能、接口易用、性能好、易扩展,那简直就是完美!
总之,通信框架的思考可以从功能出发:配置启动服务、建立连接、接收数据、处理业务、发送数据、关闭连接、关闭服务。从这条主线入手,
分别考虑上述说的,易用的接口、I/O 模型、编解码、开箱即用的协议支持、线程模型、连接管理、内存管理等。
综上,这就是我个人认为实现一个底层通信框架要思考的一些核心点,当然还有很多细节和一些锦上添花的功能,这还得再细细的盘一盘。
可以看到,要做一款通信框架,并没有那么简单,有很多需要考虑,这也是为什么那么多中间件底层通信框架不自己实现,而是都利用 Netty 的原因。
因为 Netty 将这些都实现了。
什么是Netty?
它是高性能 Java 网络通信的底层框架,可能你听过的很多中间件底层通信框架用的都是它,例如 RocketMQ、Dubbo、Elasticsearch、Cassandra等。
它为什么这么流行?为什么这么多中间件都在它之上构建?
易用
对 Java 的 NIO 进行了封装,屏蔽了 NIO 使用的复杂性,简化了网络通信的开发。且支持众多协议,不仅仅 HTTP、HTTP2、DNS、Redis 协议等等。
网络编程需要考虑粘包和拆包问题,连接的管理,编解码的处理,Netty都为你定制好了,开箱即用。还提供的内存泄漏检测,IP过滤、流量整型等高级功能。
性能
良好的I/O模型。
Netty 基于 Java NIO 封装实现了 I/O 多路复用,可由一个线程轮询多个底层 channel,减少了线程资源,也减少了多线程切换带来的开销,能更好的处理海量连接,提升系统的性能。
在 Linux 环境下也会用更优的 epoll 模型。运用零拷贝技术。不仅利用操作系统提供的零拷贝,也基于堆外内存省了一次 JVM 堆内外之间的拷贝。对象池技术,通过对象的复用,避免频繁创建和销毁带来的开销。
扩展性
基于事件驱动模型,将业务实现剥离成一个个 ChannelHandler ,利用责任链模式,可以很好的根据不同业务进行扩展,使用者只需要实现相关的 ChannelHandler 即可,框架与业务隔离。
可以根据情况配置线程模型,例如主从 Reactor ,主多从 Reactor 等等。
最后
这篇,只是从一个很高的纬度来谈谈一个底层网络通信框架的实现需要包含哪些核心点,以及 Netty 的一个很粗的概况,如果你 Netty 有深入的兴趣,可以看我这一系列的文章,已经写了 7 篇了。
链接:干翻Netty
竭尽全力、专心致志、全神贯注的做好分内之事;分享,成长,拒绝浅尝辄止。