RPC框架原理
- 网络和IO的关系,IO(input和output)面向的是谁?
- OSI 7层参考模型,TCP/IP协议
- 为什么会出现一个会话层
- 三次握手
- socket
- 心跳keep alive
- 四次挥手
- 网络IO(IO模型)
- IO框架
- 底层
学习顺序:从网络,到IO模型,到RPC
目前只涉及网络IO(与磁盘IO无关)
网络和IO的关系,IO(input和output)面向的是谁?
OSI 7层参考模型,TCP/IP协议
分层解耦是软件工程学特点,OSI7层模型被实现出来共通使用的是TCP/IP协议
为什么会出现一个会话层
逃离了底层内核里面连接的约束,不是同一个生命周期内的,会话层是比内核公共层次中更高的一个层次。
例子:用户持久化登陆,在浏览器上连接(登陆)一次某服务端,会话层中记住一个session,浏览器与服务端连接断开,在下一次重新连接的时候直接带上会话层中的session,无需重新认证(不需要重新走会话层重新构建)。
(ps:如果想让用户认证一次后永远不需要重新登陆,强调持久性,可以将session存到一个可靠性更高的地方,如redis)
三次握手
内核开辟一段空间(资源,即socket和queue)
因此
网路IO的读写是单机行为,是面向socket的queue(队列,即socket缓冲区)去读写
socket
套接字,插座
由客户端和服务端组成(客户端和服务端套在一起),形成的结果是四元组(全局唯一的)。(要是不唯一,数据包可能出现串扰)
四元组包括:客户端ip、port,服务端ip、port
心跳keep alive
在socket连接后,如何尽早感知对方下线(比如,挂掉),而不是在需要传数据时才发现。
内核开启心跳检查——属于健康检查级别
但是在内核中开辟的心跳,他的维度、层次(只检查tcp对应的socket是否连接);
想做服务的健康检查时,没有办法使用内核中的心跳检查。
kernel只能保证socket连接没问题,无法知道其上面的某一个服务(一个socket上面可能有多个服务)是否有问题。所以需要在applicate应用层也需要做心跳
心跳分为:
- 内核TCP级的心跳
- 应用层的心跳
长连接:生命周期较长,在三次握手和四次挥手之间,进行了多次数据传输,各种请求(复用了该连接)
短连接:生命周期短,只为了完成一个请求响应
无论长短连接,都可以开启keepalive
四次挥手
网络IO(IO模型)
网络IO是程序app和内核kernel之间的过程
程序在网络IO中无论是read还是write,其实都是要对内核中的队列Queue进行操作
IO模型:
BIO模型:当app读取(read)时,如果queue是空的,那么就没有返回值,这时候会进入一种阻塞状态blocking;如果有很多个连接,所以每一个连接对应一个线程,每个线程去阻塞自己对应线程去读取,直到有返文,对应线程才会动。需要的资源较多
NIO模型:无论有没有数据,read就一定会返回(所以可以使用一个线程处理多个连接) ,有弊端,如果一直没有收到消息,该线程一直在空跑(使用多路复用器解决)
多路复用器:多个连接就是多条路
多个连接作为参数传递给一个函数,这个函数会返回其中谁有数据的状态/事件
内核级的,减少read调用次数。
然后再去read,相比NIO的read精准有效不浪费。
同步/异步IO模型:
程序自己去read,都叫做同步IO模型;
异步IO模型
IO框架
IO模型是在内核kernel中实现的
内核可以完成对网卡向上一直到tcp,网络协议栈;可以向上支撑成千上万的程序
虚拟化:app->kernel(进程级)->kernel->CPU
容器化:app->kernel(协议栈放在kernel中)->CPU
底层
例如一个问题:有client端和server端,请问他们所选用的IO模型
client端可以使用BIO,server端使用NIO
因为一个client对应一个server,一个server可能与多个client连接
基本的计算机构成:一块CPU、内存、网卡、硬盘、键盘
程序是如何运行在计算机当中的
当按下电源,计算机中做的第一件事情(主板检测……先略过),从磁盘的引导分区里面拿到引导程序,再加载文件系统,识别文件系统后读取,内核是第一个进入内存的。
内核第一个加载进内存,然后是各种application程序
内核作用:可以向下管理所有硬件(统一管理);程序需要通过访问内核访问硬件
程序通过访问内核(内核中的函数)叫做——系统调用system call
但同时要考虑安全问题,使用空间划分进行安全隔离
CPU上的程序是如何切换的,才能理解从app切换到内核是如何实现的,才能理解如何完成系统调用
晶振给CPU一个信号,产生一个中断(时钟中断),内核中进程调度程序(函数),计算机中有很多表IDT(interrupt describe table)(中断描述表,0-255个信号,第二列是一个地址),CPU根据晶振信号找IDT表中地址,找到进程调度地址。
内核中有两个队列:running queue(可运行的进程)、blocking queue(阻塞的队列,等待事件,无法拿到CPU直接运行)
进程调度针对running queue中的进程,进程调度就是从running queue队列中选一个进程放入CPU执行
还有一个表GDT(描述内核空间在哪里)