分布式网络通信Netty框架
复习知识点
田超凡
20191117
转载请注明原作者
1 网络编程模型基础
1.1 OSI七层网络模型的介绍
物理层:客户端数据传输的物理实现,如客户端的内存、硬盘等
数据链路层:客户端内部的数据交换连接机制
网络层:客户端的交换机、通信机、宽带等网络通信设施
传输层:实现客户端和服务器之间的网络传输
会话层:服务器从网络传输通道中接收到消息并建立和客户端的会话
表示层:服务器内部根据端口号定位到对应的应用程序,对网络传输的数据进行解析和格式转换,发送解析后的数据到对应端口号的应用程序(需要被重点关注的层)
应用层:服务器运行的应用程序(需要被我们重点关注的层)
1.2 Socket技术中TCP与UDP区别
TCP是一个严格基于连接状态实现的通信机制,客户端和服务器之间建立TCP连接和关闭TCP连接都必须经过三次握手和四次挥手,数据传输安全,但是连接效率低(因为客户端和服务器不能直接通信,必须通过三次握手和四次挥手),是Socket通信、Netty通信框架默认使用的网络连接协议,Java网络通信机制默认采用的网络通信协议就是TCP协议。
UDP是一个无连接传输协议,客户端只需要知道需要远程访问的服务器地址和端口(服务器防火墙等网络拦截关闭的前提下)就可以建立和服务器的连接,但是由于没有一个机制来标记每次建立连接的客户端和服务器,当网络比较差的时候容易产生数据丢包问题,所以数据传输的安全性和准确性较差,但是连接效率高、速度快(因为UDP协议不需要通过特定机制建立客户端和服务器的连接,直接通过地址访问),适用于实时通讯服务的开发。
1.3 白话文翻译TCP三次握手协议
TCP三次握手用来建立客户端和服务器的TCP连接,主要包括三个阶段:
- .客户端告诉服务器,我要访问你了
- .服务器告诉客户端,你可以访问我了
- .客户端告诉服务器:好的,那我们建立连接吧
1.4 HTTP协议长连接与短连接的区别
HTTP协议长连接表示当客户端和服务器建立连接之后,默认是不会关闭客户端和服务器的连接的,除非某一方出现了故障,导致连接超时自动关闭连接,或者客户端显示指定强制断开连接。
HTTP协议短连接表示客户端请求服务器都会重新建立连接,服务器返回响应到客户端之后连接就会断开。
1.5 HTTP与HTTPS的区别
HTTP协议是一个无状态超文本传输协议,是基于TCP传输协议的二次包装,因此基于HTTP协议建立客户端和服务器的连接也需要通过TCP三次握手和四次挥手实现。
HTTPS协议是一个加入了SSL+证书加密传输机制的无状态超文本传输协议,比HTTP协议更加安全,加入了网络传输安全校验机制
2 深入理解Linux网络通信IO模型
2.1 同步和异步的区别
在请求-响应的角度来看,同步请求表示发送请求到服务器,服务器必须返回相应结果之后才能继续往下执行,否则会一直阻塞。异步请求表示发送请求到服务器之后,不需要等到服务器返回响应结果,程序会正常往下执行,不会阻塞。
在程序执行的角度来看,同步表示执行到某一行方法调用的时候,必须等到方法执行完毕之后才能继续往下执行,否则会一直阻塞等待调用的方法执行完毕。
异步表示执行到某一行方法调用的时候开启一个子线程执行这个方法,不会影响主线程程序继续往下执行,不需要等到调用方法执行完毕,不会线程阻塞。
2.2 BIO模型存在那些缺点
BIO模型表示的是同步阻塞IO模型,默认IO操作都是基于BIO模型实现的,由于是阻塞式的IO操作,当需要进行的IO操作响应时间过长的时候,程序就会一直阻塞,直到当前IO操作执行完毕,不适用于高并发、高性能IO操作。
2.3 阻塞式io与非阻塞式io的区别
同步阻塞模型BIO和同步非阻塞式模型NIO都是采用同步的方式实现IO处理的,区别在于:
BIO是阻塞式的操作,当需要执行的IO操作响应时间过长的时候就会导致线程阻塞,不能继续往下执行,必须等到IO操作执行完毕之后才能继续执行。BIO是面向流实现的数据传输。
NIO是非阻塞式的操作,不会因为需要执行的IO操作响应时间过长而造成线程阻塞,采用轮训的机制,当没有获取到IO操作执行结果的时候就会使用轮询机制不断获取,直到获取到IO操作执行结果之后才会停止轮询,不会因为等待IO操作响应而影响原程序的正常执行,NIO是面向缓冲区实现的数据传输,并且提供了选择器Selector、通道Channel等机制实现多路IO复用。
2.4 使用多线程实现异步io存在那些缺点
AIO异步IO操作模型是采用异步的方式进行IO操作的,当使用多线程实现异步IO操作的时候会开启多个子线程来实现异步操作,这样会占用大量的CPU资源,容易造成线程池溢出,影响IO操作执行性能。
2.5 Linux五种io模型
同步IO模型:
BIO 同步阻塞IO模型
NIO 同步非阻塞IO模型
IO复用 对于多线程IO操作的时候可以实现IO操作复用
信号驱动IO 对于每次IO操作的触发时机是根据信号决定的,当接受到对应IO处理的操作信号时才会进行对应的IO处理
异步IO模型:
AIO 异步IO模型,采用异步的方式开启多个子线程来实现IO操作
3 深入理解NIO多路IO复用机制
3.1 什么是BIO阻塞式io模型
BIO同步阻塞式IO模型使用同步的方式实现IO操作,当需要调用的IO处理操作执行时间过长的时候会一直阻塞,此时必须等到当前IO操作执行完毕之后才能继续往下执行,存在高并发、高性能条件下的IO处理问题,存在IO瓶颈,影响IO执行效率。
3.2 使用多线程实现伪异步io优缺点
使用多线程实现伪异步IO操作的优点是当需要调用的IO处理方法响应时间过长的时候,线程不会阻塞,不会影响程序的正常执行。
缺点是高并发访问背景下,使用多线程实现AIO操作会占用大量CPU资源,影响服务器IO处理效率,因为异步操作会开启多个子线程分别处理,还容易产生线程池溢出的问题。
3.3 NIO与BIO的区别有那些
NIO同步非阻塞IO模型和BIO同步阻塞IO模型都是采用同步处理的机制实现IO操作的,区别在于:
NIO是非阻塞式的IO操作,当需要调用的IO操作方法执行时间过长的时候,会使用循环和轮询来不断获取IO处理结果,直到对应的IO处理操作执行完毕之后才会继续往下执行,不会线程阻塞。NIO数据传输机制采用的是缓冲区,可以高效发送和接收各类网络传输数据并进行格式统一的转换。
NIO同步非阻塞IO操作使用选择器Selector实现了多路IO复用,多线程IO操作的时候实现IO操作资源共享。
BIO是同步阻塞IO模型,当需要调用的IO处理操作执行时间过长的时候,程序会一直等待,造成线程阻塞,直到对应的IO操作执行完毕之后才能继续往下执行。BIO数据传输机制面向的是流,通过流实现各类数据传输,传输效率没有缓冲区高。
3.4 为什么要使用NIO编程
NIO是同步非阻塞式的IO操作,不会产生线程阻塞。
NIO面向缓冲区实现数据传输,可以兼容不同类型的传输数据,提高数据传输效率。
NIO使用选择器实现了多路IO复用
NIO三大核心组件:选择器Selector、通道Channel、缓冲区ByteBuffer
3.5 NIO模式核心设计技术思想
NIO同步非阻塞IO模型使用同步的方式实现IO操作,使用循环和轮询机制不断获取IO处理结果,不会产生线程阻塞。NIO模式使用选择器来存放请求的客户端信息,对于选择器中的请求信息统一使用相同的IO操作处理,实现多路IO复用,即对于多线程执行IO操作的时候,实现IO操作资源的共享
3.6 NIO技术多路IO复用底层实现原理
NIO多路IO复用是基于NIO的选择器实现的,对于多个客户端发送的请求会统一存放到选择器容器中,当需要进行IO操作的时候遍历这个选择器容器,对于每个请求信息都使用相同的IO操作进行处理,实现多路IO复用。
3.7 Redis为什么单线程能够支持高并发
Redis底层就是基于NIO多路IO复用机制实现的,所以在高并发背景下,服务器会使用单线程来处理多线程发过来的的IO操作请求,使用共用的IO操作方法进行处理,从而最终实现多路IO复用,提高服务器IO执行效率
3.8 NIO选择器、缓冲区分别核心的作用
NIO选择器用来存放客户端多次请求服务器的信息,对于服务器而言,在需要批量执行IO操作的时候会遍历这个选择器获取所有请求本次服务的信息,统一使用相同的IO操作进行处理,实现多路IO复用
ByteBuffer缓冲区可以把需要传输的各类型数据和字节之间进行转换,因为TCP连接网络传输数据都是以字节的形式传输的,使用ByteBuffer缓冲区可以提高数据传输和数据解析效率。
4 Netty实战与TCP拆包粘包问题解决方案
4.1 为什么使用Netty,不用NIO
JDK内置的NIO操作API复杂,需要对网络编程模型十分了解才能基于一系列API快速实现高效稳定的NIO操作,需要深入了解选择器、通道、缓冲区操作等各类API,学习成本高。并且NIO内置的选择器Selector有一个Bug,由于NIO版本不太稳定,导致这个问题还是有发生的可能性,这个问题会导致选择器Selector空轮训,最终导致CPU 100%
Netty是一个基于NIO同步非阻塞IO操作模型实现的分布式网络通信框架,Netty对JDK原生NIO相关API重新进行封装,使得现有的API操作更加易用,并且Netty提供了更加强大的编解码器、缓冲区和事件驱动处理,可以快速搭建和实现客户端与服务器之间的高性能网络通信和数据传输,并且Netty还支持UDP和异步文件传输,功能十分强大。
4.2 Netty应用场景有那些
RPC远程服务调用框架的服务器、客户端实现,如Dubbo框架
实时通讯系统服务器和客户端的实现
4.3 什么是TCP粘包和拆包
TCP粘包问题表示的是当客户端多次发送请求数据到服务器,服务器接收到的数据却是客户端所有发送数据的总和,这种情况就是TCP粘包问题。
TCP拆包问题表示的是当客户端多次发送请求数据到服务器后,服务器接收到的数据确是客户端发送数据的拆分再合并格式(第一次完整+第二次不完整)
4.4 TCP粘包和拆包产生的原因
TCP粘包和拆包问题产生的原因是当客户端和服务器建立TCP连接之后,在进行数据传输时可能由于网络不稳定或者缓冲区容量过大过小,导致传输数据在传输通道中发生变化,服务器接收到客户端传输过来的数据格式出现问题,也就造成了TCP拆包和粘包问题。
当传输的数据总大小>缓冲区大小的时候,会产生TCP拆包问题
当传输的数据总大小<=缓冲区大小的时候,会产生TCP粘包问题
4.5 如何解决TCP粘包和拆包问题
- .手动在客户端每次发送数据的地方指定分隔符,在服务器接收到客户端发送的数据之后,再根据分隔符拆分字符串,解决TCP拆包粘包问题。
- .根据客户端传输数据的大小调整服务器缓冲区大小,使得缓冲区大小能够更好地适配客户端发送的网络传输数据。
- .使用Netty编码器和解码器解决TCP拆包粘包问题
5 Netty编解码器、事件驱动和数据传输
5.1 Netty编解码器的作用是什么?如何实现自定义编码解码器?
Netty提供了一系列内置编码解码器实现通信时的数据传输格式转换和解析。
Netty允许自定义编码解码器来实现不同类型的数据传输,解决TCP拆包和粘包问题。
自定义编码器需要实现MessageToByteEncoder接口,重写encode方法进行编码,把需要传输的数据序列化为字节。
自定义解码器需要实现MessageToMessageDecoder接口,重写decode方法进行解码,把接收到的网络传输的字节数据反序列化为对应类型的对象。
5.2 Netty事件驱动模型是怎么实现的?有什么作用?
Netty实现的自定义客户端和服务器都是基于事件驱动处理器实现的事件监听处理,自定义的事件驱动处理器需要继承SimpleChannelInboundHandle类或ChannelInboundHandleAdapter类,重写各类事件监听方法实现事件监听。
常用的channelRead接收客户端发送的消息,channelActive发送消息到服务器
5.3 Netty缓冲区的作用是什么?
Netty缓冲区Buffer的作用是解析和转换各类需要经过TCP网络传输的数据,
TCP协议在进行网络传输数据的时候,数据都是采用字节的形式传输的,因为需要考虑到不同平台、不同语言的数据格式兼容性,所以使用字节的形式传输数据。客户端发送数据到服务器,发送之前需要把对象序列化为字节再发送;服务器接收到客户端发送的数据之后,需要把字节反序列化为对象。Netty缓冲区的作用就是灵活的在客户端和服务器对网络传输数据进行格式转换和解析,提高网络传输数据和数据解析的效率。
6 Netty网络通信序列化机制
6.1 什么是序列化?反序列化
在网络传输序列机制中,序列化指的是客户端把需要传输的数据序列化为字节,反序列化指的是服务器把接收到的客户端发送的数据字节反序列化为对象。
6.2 序列化有那些实现方式
对象持久化序列化模式:把JVM中的对象数据持久化保存到物理设备(对象数据序列化为特定格式数据)、读取物理设备存储的对象数据并反序列化为对象。
网络传输序列化模式:客户端把发送的对象数据转换为字节(序列化),服务器把接收到的字节数据转换为对象(反序列化)。
6.3 网络传输序列化协议有那些
(1). JSON轻量级数据交换格式
- . XML 可扩展标记语言
- . ProtoBuf 谷歌字节缓冲区
- . MessagePack二进制数据交换格式
6.4 MessagePack编码器与json有哪些区别
MessagePack是一个二进制数据交换格式,从结构上来看,MessagePack使用数组的结构存放JSON中的值,序列化和反序列化的属性值是通过索引实现的,而不再同JSON一样使用Key来获取Value,更加轻小,更加灵活。
JSON是轻量级的数据交换格式,采用类似Key-Value键值对的形式对数据进行转换,通过Key获取Value
6.5 网络传输对象为什么需要序列化?
因为TCP网络传输协议在传输数据的时候传输的都是字节数据,这是为了确保不同客户端和服务器传输数据格式的统一性,解决跨平台、跨语言数据传输格式不匹配的问题,从意义上来看,TCP传输数据的方式类似适配器模式(适配不同平台、不同语言的客户端和服务器),能够适配不同类型的数据实现网络数据传输。
由于不同平台、不同语言传输的数据类型都是有差异的。因此,客户端在网络传输之前,需要把传输的数据统一序列化为字节再进行发送,服务器接收到通道中客户端发送的字节数据之后需要把字节数据反序列化为对应类型的对象数据。
综上所述,网络传输对象的序列化机制就是为了满足TCP协议不同平台、不同语言应用程序之间的通信数据传输。
7 基于Netty+Zookeeper手写RPC远程调用框架-Dubbo
7.1 Netty+Zookeeper手写Dubbo框架有哪几个实现步骤?
(1).实现服务生产者和消费者
(2).实现Zookeeper服务注册
(3).实现Dubbo服务器,基于反射获取需要注册到Zookeeper注册中心的服务并注册到Zookeeper注册中心,初始化Netty服务器,绑定事件驱动处理器和编码解码器。
(4).实现Zookeeper注册中心服务发现
(5).实现Dubbo框架负载均衡处理器
(6).实现Dubbo客户端,基于JDK动态代理获取需要远程调用的服务接口的JDK动态代理实例,在代理方法中实现服务发现和远程调用:
调用Zookeeper注册中心服务发现类获取需要调用的服务对应的Zookeeper注册中心的访问地址,基于负载均衡器实现负载均衡,初始化Netty客户端,建立Netty客户端和需要调用的远程服务器的连接,绑定事件驱动处理器和编码解码器。
7.2 RPC远程服务调用负载均衡器实现方式有哪些?
负载均衡器的作用是减轻服务器的访问压力,使用不同策略来均衡服务调用请求。
RPC远程服务调用负载均衡器实现方式有5种:
- . 轮询(轮询递增、轮询取模)
- . 权重
- . 一致性Hash
- . 随机权重
- . 随机
转载请注明原作者