微服务 Spring Cloud 9,RPC框架,客户端和服务端如何建立网络连接?

在服务化拆分之后,**服务提供者和服务调用者会运行在两台不同的物理机的不同的进程内,他们之间的调用称为远程方法调用,**简称RPC。
RPC的大体流是:
建立网络连接;
按照某种约定的协议进行网络通信;
正常通信后,服务端接收到客户端的请求,然后进行处理;
处理成功后,对处理结果进行压缩、序列化,再将其返回给客户端;
这也就对应着4个问题:

客户端和服务端如何建立网络连接?
服务端如何处理请求?
数据传输采用什么协议?
数据该如何序列化和反序列化?
在这里插入图片描述
一、客户端和服务端如何建立网络连接?
1、HTTP通信
HTTP通信是一种基于请求和响应模型的通信协议,用于在网络中传输数据。它由客户端和服务器组成,客户端向服务器发送请求,服务器处理请求并返回适当的响应。

(1)HTTP通信的过程如下
建立连接:HTTP协议是应用层协议,需要在传输层协议(如TCP)的基础上建立连接。当客户端向服务器发送请求时,首先需要建立TCP连接。
发送请求:一旦建立了TCP连接,客户端就可以向服务器发送HTTP请求。请求命令包括请求方法(如GET、POST、PUT、DELETE等)、请求URI、HTTP协议版本以及请求头和请求体等信息。
接收请求:服务器接收到请求后,会对其进行解析和处理,包括对请求方法、URI、协议版本以及请求头和请求体的处理。
返回响应:服务器处理完请求后,会返回适当的响应。响应包括HTTP协议版本、响应状态码、响应头和响应体等信息。
断开连接:在完成通信后,客户端和服务器会断开TCP连接、
2)HTTP通信的特点如下:

支持B/S模式:HTTP通信是浏览器和服务器之间的通信,支持B/S模式,不需要客户端和服务器建立直接的连接。
简单快速:HTTP协议简单快速,能够快速地传输数据,减少网络延迟。
灵活:HTTP协议支持多种请求方法,可以支持不同的操作类型,如GET用于获取数据,POST用于提交数据等。
无连接:HTTP协议无连接,每个请求都需要建立TCP连接,但连接建立后可以处理多个请求,减少了网络开销
无状态:HTTP协议无状态,每个请求都是独立的,服务器不会记录之前请求的状态。这使得HTTP通信具有更好的可扩展性和可维护性。
2、Socket通信
Socket通信是基于TCP/IP协议的封装,建立一次Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ;另一个运行于服务器端,称为ServerSocket 。就像下图所描述的,Socket通信的过程分为四个步骤:服务器监听、客户端请求、连接确认、数据传输。

服务器监听:ServerSocket通过调用bind()函数绑定某个具体接口,然后调用listen()函数实时监控网络状态,等待客户端的连接请求;
客户端请求:ClientSocket调用connect()函数向ServerSocket绑定的地址和端口发起连接请求;
服务端连接确认:当ServerSocket监听到或者接收到ClientSocket的连接请求时,调用accept()函数响应ClientSocket的请求,同客户端建立连接;
数据传输:当ClientSocket和ServerSocket建立连接后,ClientSocket调用send()函数,ServerSocket调用receive()函数,ServerSocket处理完请求后,调用send()函数,ClientSocket调用receive()函数,就可以得到返回结果。
在这里插入图片描述
当客户端和服务端建立网络连接后,就可以发起请求了。但网络不一定总是可靠的,经常会遇到网络闪断、连接超时、服务端宕机等各种异常,通常的处理手段有两种:

链路存活检测:客户端需要定时发送心跳检测信息(一般为ping请求)给服务端,如果服务端连续n次心跳检测或者超过规定的时间都没有回复消息,则认为此链路已经失效,这个时候客户端就需要重新与服务端建立连接。
断连重试:通常多种情况会导致连接断开,比如客户端主动关闭、服务端宕机、网络故障等。这个时候客户端就需要与服务端重新建立连接,但一般不会立刻完成连接,而是要等待一个固定的时间后再发起连接,避免服务端的连接回收不及时,而客户端瞬间重连的请求太多而把服务端的连接数占满。
二、服务端如何处理请求?
网络已经连通,服务端如何处理客户端请求呢?

1、通常来说,有三种处理方式:
同步阻塞BIO,**客户端的每一个请求,服务端就会生成一个线程去处理。**当客户端同时发起的请求很多时,服务端需要创建很多的线程去处理每一个请求,如果达到了系统最大的线程瓶颈数,新来的请求就无法处理了。
同步非阻塞NIO,客户端的每一个请求,服务端并不是每次都创建一个新的线程来处理,而是通过IO多路复用技术进行处理。系统的一个线程可以处理多个客户端请求,这种方式的优势是开销小,不用为每个请求创建一个新的线程,可以节省系统开销。
异步非阻塞方式AIO,客户端只需要发起一个IO操作,然后会立即返回,等IO操作完成后,客户端得到IO操作完成的通知,此时客户端再对返回值进行处理,不需要进行IO读写操作,真正的IO读取和写入操作已经由内核完成了。这种方式的优势是客户端无需等待,不存在阻塞等待的问题。
2、不同的处理方式对应着不同的业务场景:
BIO适用于连接数比较少的业务场景,系统会有足够的线程供你使用,这种程序比较简单直观,易于理解;
NIO适用于连接数比较多但是每个请求的业务量不是很大,处理速度很快,比如聊天服务器。
AIO适用于连接数比较多,而且每个请求的业务量比较大,处理比较耗时。
三、HTTP协议传输流程
最常用的协议是HTTP协议, 它是一种开放协议,各大网站的服务器和浏览器之间的数据传输大都采用这种协议。

根据协议的规定,服务消费者对数据进行处理;
然后通过网络传送到服务端;
服务端从网络中获取数据后,根据规定,对传输的数据进行解码操作;
然后根据业务逻辑进行处理;
再把处理结果返回给服务消费者;
服务消费者对返回的结果进行解码处理,最终得到服务端返回的数据结果。
通常协议规定中包含消息头和消息体两部分。消息头存放的是协议的公共字段以及用户扩展字段,消息体存放的是传输数据的具体内容。
四、数据该如何序列化和反序列化?
在微服务中,数据的序列化和反序列化是非常重要的环节,它们涉及到数据的传输和存储。以下是一些关于微服务中数据序列化和反序列化的建议:

1、选择合适的序列化方式
序列化是将数据结构或对象状态转换为可以存储或传输的格式的过程,而反序列化则是将已序列化的数据还原为原始数据结构或对象状态的过程。在微服务中,需要选择一种高效的、易于理解和使用的序列化方式。常见的序列化方式包括JSON、XML、Protocol Buffers等。其中,JSON是一种轻量级的数据交换格式,它以可读性高、兼容性好、支持多种语言等优点而被广泛使用。而Protocol Buffers则是一种高效的数据序列化格式,它能够将结构化的数据序列化成字节流,并可以在网络中进行传输。

2、考虑数据传输效率
在微服务中,数据传输效率是非常重要的,因此需要选择一种高效的序列化方式。JSON和XML虽然易于理解和使用,但它们的传输效率相对较低。而Protocol Buffers则是一种更高效的序列化格式,它能够将数据结构化并压缩成更小的字节流,从而提高了数据传输效率。

3、考虑数据结构的变化
在微服务中,数据结构可能会随着业务需求的变化而变化。因此,在选择序列化方式时需要考虑数据结构的变化情况。如果数据结构经常变化,那么选择一种灵活的序列化方式是非常重要的。如果数据结构相对稳定,那么可以选择一种更高效的序列化方式。

4、考虑跨语言和跨平台的需求
微服务通常需要支持不同的语言和平台。因此,在选择序列化方式时需要考虑跨语言和跨平台的需求。JSON和XML是一种通用的数据交换格式,支持多种语言和平台。而Protocol Buffers则是一种跨语言的数据序列化格式,它可以在不同的语言之间进行数据交换。

传统的BIO(同步阻塞的BIO)
就是说服务端一旦接受客户端的连接,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待同当前连接的客户端的操作执行完成,不过可以通过多线程来支持多个客户端的连接,循环导致高cpu消耗。

服务器的实现模式是一个连接一个线程,这样的模式很明显的一个缺陷是:

由于客户端连接数与服务器线程数成正比关系,可能造成不必要的线程开销,严重的还将导致服务器内存溢出。当然,这种情况可以通过线程池机制改善,但并不能从本质上消除这个弊端。

问题:当出现高并发怎么办?

NIO(同步非阻塞的NIO)
从JDK1.4以后开始,JDK引入的新的IO模型NIO
Channel(通道) :通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。因为 Buffer,通道可以异步地读写。
Buffer(缓冲区) :Buffer是一个对象,它包含一些要写入或者要读出的数据
Selector(选择器) :选择器用于使用单个线程处理多个通道。因此,它需要较少的线程来处理这些通道。线程之间的切换对于操作系统来说是昂贵的。因此,为了提高系统效率选择器是有用的。

就是说加了三个功能来解决bio中的单线程一对多的问题

而服务器的实现模式是多个请求一个线程,即而服务器的实现模式是多个请求一个线程,即请求会注册到多路复用器Selector上,多路复用器轮询到连接有IO请求时才启动一个线程处理。
Java NIO: 单线程管理多个连接。
劣处:维护成本高,容易出现bug,项目大了之后消耗成本
AIO(异步非阻塞的AIO)
JDK1.7发布了NIO2.0也可以说是Nio的加强版,它是异步非阻塞的IO模型。
异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

这就是真正意义上的异步非阻塞,服务器的实现模式为多个有效请求一个线程,客户端的IO请求都是由OS先完成再通知服务器应用去启动线程处理(回调)。

应用场景:并发连接数不多时采用BIO,因为它编程和调试都非常简单,但如果涉及到高并发的情况,应选择NIO或AIO,更好的建议是采用成熟的网络通信框架Netty。

总结:理解了这,浓缩了还是有点东西的

BIO是一个连接一个线程。
NIO是一个请求一个线程。
AIO是一个有效请求一个线程。

**同步阻塞模式:**这种模式下,我们的工作模式是先来到厨房,开始烧水,并坐在水壶面前一直等着水烧开。

同步非阻塞模式:这种模式下,我们的工作模式是先来到厨房,开始烧水,但是我们不一直坐在水壶前面等,而是回到客厅看电视,然后每隔几分钟到厨房看一下水有没有烧开。

异步非阻塞 I/O 模型:这种模式下,我们的工作模式是先来到厨房,开始烧水,我们不一直坐在水壶前面等,也不隔一段时间去看一下,而是在客厅看电视,水壶上面有个开关,水烧开之后他会通知我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值