05-网络 其他

IO 模型 ★★★

  • 阻塞 IO
  • 非阻塞 IO
  • 多路复用 IO
  • 信号驱动 IO
  • 异步IO

IO多路复用

复用分为时间上的复用和空间上的复用:

  • 空间上的复用是指将内存分为几部分,每一部分放一个程序,这样同一时间内存中就有多道程序。
  • 时间上的复用是指多个程序需要在一个 cpu 上运行,不同的程序轮流使用 cpu,当某个程序运行的时间过长或者遇到 I/O 阻塞,操作系统会把 cpu 分配给下一个程序,保证 cpu 处于高使用率,实现伪并发。

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:

  • 当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。
  • 当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。
  • 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。
  • 如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用。
  • 如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用。
  • 与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。

网卡的内核缓冲区,是在PC内存中,由内核控制。

select、poll、epoll 模型的区别

参考:IO模型

都是IO多路复用的机制,监视多个socket是否发生变化,本质上都是同步IO。因为他们都需要在读写事件就绪后自己负责进行把数据写进内存,也就是说把数据读写进内存这个过程是阻塞的。

select

select 的调用步骤如下:

  1. 使用 copy_from_user 从用户空间拷贝 fdset 到内核空间,并注册回调函数 __pollwait
  2. 遍历所有 fd,调用其对应的 poll 方法(对于 socket,这个 poll 方法是sock_pollsock_poll 根据情况会调用到 tcp_poll,udp_poll 或者datagram_poll),
    tcp_poll 为例,其核心实现就是 __pollwait,也就是上面注册的回调函数。
  3. __pollwait 的主要工作就是把 current(当前进程)挂到设备的等待队列中,不同的设备有不同的等待队列,对于 tcp_poll 来说,其等待队列是sk->sk_sleep(注意把进程挂到等待队列中并不代表进程已经睡眠了)。在设备收到一条消息(网络设备)或填写完文件数据(磁盘设备)后,会唤醒设备等待队列上睡眠的进程,这时 current 便被唤醒了。
  4. poll 方法返回时会返回一个描述读写操作是否就绪的 mask 掩码,根据这个 mask 掩码给 fd_set 赋值。
  5. 如果遍历完所有的 fd,还没有返回一个可读写的 mask 掩码,则会调用 schedule_timeout 是调用 select 的进程(也就是 current)进入睡眠。当设备驱动发生自身资源可读写后,会唤醒其等待队列上睡眠的进程。如果超过一定的超时时间(schedule_timeout),还是没人唤醒,则调用 select 的进程会重新被唤醒获得 CPU,进而重新遍历 fd,判断有没有就绪的 fd。
  6. fd_set 从内核空间拷贝到用户空间。

select 的几大缺点:

  • 每次调用 select 都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大
  • 每次调用 select 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 很多时也很大
  • select 支持的文件描述符数量太小了,默认是1024

poll

poll 与 select 不同,通过一个 pollfd 数组向内核传递需要关注的事件,故没有描述符个数的限制,pollfd 中的 events 字段和 revents 分别用于标示关注的事件和发生的事件,故 pollfd 数组只需要被初始化一次。

poll 的实现机制与 select 类似,其对应内核中的 sys_poll,只不过 poll 向内核传递 pollfd 数组,然后对 pollfd 中的每个描述符进行 poll,相比处理 fdset 来说,poll 效率更高。poll 返回后,需要对 pollfd 中的每个元素检查其 revents 值,来得知事件是否发生。

epoll

epoll 和 select/poll 不同,epoll 通过在 Linux 内核中申请一个简易的文件系统。

epoll 调用分成了 3 个部分:

  1. epoll_create():建立一个 epoll 对象,也就是 eventpoll 结构体。
    每一个 epoll 对象都有一个独立的 eventpoll 结构体,这个结构体会在内核空间中创造独立的内存,用于存放通过 epoll_ctl() 方法向 epoll 对象中添加进来的事件。这些事件都会被挂载在红黑树中,重复添加的事件就可以通过红黑树而高效的识别出来(红黑树的插入时间效率是 lgn,其中 n 为树的高度)。

  2. epoll_ctl():向 epoll 对象中添加或删除一些套接字,将 epitem 添加到 epoll 的红黑树中。
    所有添加到 epoll 中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当相对应的事件发生时会调用这个回调方法,这个回调方法在内核中叫 ep_poll_callback,它将发生的事件的 epitem 结构体 添加到 rdlist 双链表中;

  3. epoll_wait():收集发生的事件的连接。epoll_wait 的效率非常高,因为调用 epoll_wait 时,并没有向操作系统复制连接的句柄数据,内核不需要遍历全部的连接。

eventpoll 结构体中有两个成员与 epoll 的使用方式密切相关,如下

1
2
3
4
struct eventpoll {
struct rb_root rbr; # 红黑树的根节点,这棵树中存储着所有添加到 epoll 中需要监控的事件,也就是这个 epoll 监控的事件,epoll 机制通过红黑树保存需要监控的事件;
struct list_head rdllist; # 双向链表 rdllist 保存着将要通过 epoll_wait 返回给用户的、满足条件的事件
};

在 epoll 中,对于每一个事件,都会建立一个 epitem 结构体,简要结构如下所示。

1
2
3
4
5
6
7
struct epitem{
struct rb_node rbn; //红黑树节点
struct list_head rdllink; //双向链表节点
struct epoll_filefd ffd; //事件句柄信息
struct eventpoll *ep; //指向其所属的eventpoll对象
struct epoll_event event; //期待发生的事件类型
}

当调用 epoll_wait() 检查是否有事件发生时,只需要检查 eventpoll 对象中的 rdlist 双向链表中是否有 epitem 元素即可。如果 rdllist 链表不为空,则把发生的事件复制到用户态,同时把事件的数量返回给用户。

总结:

  • epoll_create 创建一个 epoll 实例,该实例有一个 eventpoll 结构体,结构体中含有关键成员(存放 epoll 中的事件的红黑树根节点 rbr、保存 epoll_wait 返回的事件的双向链表 rdllist),同时返回一个引用该实例的 fd。所以在使用完 epoll 后,必须调用 close() 关闭对应的文件描述符。
  • epoll_ctl 绑定 fd 到 epoll 实例,将 fd 添加到 epoll 实例的监听列表(红黑树),同时为 fd 设置一个回调函数监听事件 event。
  • 当 fd 上发生相应事件时,会调用回调函数,将 fd 添加到 epoll 实例的就绪队列(rdlist双链表)上。
  • epoll_wait 就相当于 select,但是 epoll 不需要像 select 那样遍历检测每个文件描述符,只需要判断就绪列表(rdlist双链表)是否为空即可。这样,在没有描述符就绪时,epoll 能更早地让出系统资源。

select\poll\epoll 对比

  • select、poll 需要自己不断轮询所有监测对象,直到对象发生变化,在这个阶段中,可能要睡眠和唤醒多次交替。

  • epoll 也需要调用 epoll_wait 不断轮询就绪链表。但是当对象发生变化时,就已经调用回调函数,将变化的对象放入就绪链接表中,如果此时有就绪的对象就唤醒在 epoll_wait 中进入睡眠的进程。虽然都会睡眠和唤醒,但是 select 和 poll 在被唤醒的时候要遍历整个监测对象集合,而 epoll 只要判断就绪链表是否为空即可,节省了大量 cpu 的时间。

  • select:select 本质上是通过设置或者检查存放 fd 标志位的数据结构来进行下一步处理。
    优点:

    1. 可移植性好,某些 Unix 系统不支持 poll。
    2. 对于超时值提供了更好的精度:微秒,而 poll 是毫秒。

    缺点:

    1. 最大并发数限制,(32 位默认 1024 个,64 位默认 2048)
    2. 效率问题,select 每次调用都会线性扫描全部的 FD 集合,所以将 FD_SETSIZE 改的越大,会越慢。
    3. 需要维护一个用来存放大量 fd 的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。
  • poll 本质上和 select 没有区别,它将用户传入的数组拷贝到内核空间,它没有最大连接数的限制,原因是它基于链表来存储的,但是同样有一个缺点:大量的 fd 的数组被整体复制于用户态和内核地址空间,而不管这样的复制是不是有意义。

  • epoll 支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉进程哪些 fd 刚刚变为就需态,并且只会通知一次。

    1. epoll 在 Linux 内核中申请了简易的文件系统,每次新建 IO 句柄(epoll_create)才复制并注册(epoll_register)到内核,也就是在 进程 启动时建立 1 个 epoll 对象,并在需要的时候向它添加或删除连接就可以了,因此,在实际收集事件时,epoll_wait 的效率就会非常高,因为调用 epoll_wait 时并没有向它传递这 100 万个连接,内核也不需要去遍历全部的连接。
    2. 内核根据 IO 事件,把准备好的 IO 句柄放到就绪队列,应用只要轮询 epoll_wait 就绪队列,然后去读取数据,不存在 select 的轮询,也没有内核的轮询,不需要多次复制所有的 IO 句柄。因此,可以同时支持的 IO 句柄数轻松过百万。

因为一个进程所打开的 FD (文件描述符)是有限制的,由 FD_SETSIZE 设置,默认值是 1024/2048,因此 select\poll\epoll 最大并发数都被这个所限制。

什么是异步非阻塞

  • 非阻塞:遇到 IO 阻塞时不等待(setblooking=False),(可能会报错->捕捉异常)。
  • 异步:回调(ajax),当达到某个指定状态之后,自动调用特定函数。

各种名词含义

C/SB/S 架构

  • C/S 架构:Client 端与 Server 端的服务架构。
  • B/S 架构:隶属于 C/S 架构,Broswer 端(网页端)与 Server 端。优点:统一了所有应用的入口,方便、轻量级。

局域网和广域网

局域网和广域网是按规模大小而划分的两种计算机网络。

  • 范围在几千米以内的计算机网络统称为局域网(LAN、私网、内网)。
  • 连接的范围超过10千米的,则称为广域网,因特网(Intenet)就是目前最大的广域网(WAN、公网、外网)。

什么是防火墙以及作用

防火墙是一个分离器,一个限制器,也是一个分析器,有效地监控了内部网和 Internet 之间的任何活动,保证了内部网络的安全。

作用:防火墙可通过监测、限制、更改跨越防火墙的数据流,尽可能地对外部屏蔽网络内部的信息、结构和运行状况,以此来实现网络的安全保护。

路由器和交换机的区别

  • 交换机。
    用于在同一网络内数据快速传输转发,工作在数据链路层;
    通过 MAC 寻址,不能动态划分子网;
    只能在一条网络通路中运行,不能动态分配。

  • 路由器。
    是一个网关设备,内部局域网到公网的一个关卡;
    工作在网络层;
    通过 IP 寻址,可以划分子网;
    可以在多条网络通道中运行,可以动态分配 IP 地址。

简单说:交换机就是把一根网线变成多根网线;路由器就是把一个网络变成多个网络;如果不上外网,只是局域网,交换机即可;如果上外网,并且给网络划分不同网段,就必须用路由器。

如何修改本地 hosts 文件

hosts 就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,可以用来屏蔽一些网站,或者指定一些网站。

  • windows:位置:C:\Windows\System32\drivers\etc
  • linux:位置:/etc/hosts

什么是 CDN ★★★

https://www.zhihu.com/question/36514327?rf=37353035
https://zhuanlan.zhihu.com/p/338951935

用户获取数据时,不需要直接从源站获取,通过 CDN 对数据分发,用户可以从一个较优的服务器获取数据,从而达到快速访问,并减少源站负载压力的目的。

CDN 的具体工作流程(下面的流程是两级 CDN 的流程,一级 CDN 的流程不分全局和区域负载均衡):

  1. 当用户点击网站页面上的 URL,经过本地 DNS 系统解析,DNS 系统会最终将域名的解析权交给 CDN 专用 DNS 服务器。
  2. CDN 的 DNS 服务器将 CDN 的全局负载均衡设备 IP地址 返回用户。
  3. 用户向 CDN 的全局负载均衡设备发起 URL 访问请求。
  4. CDN 全局负载均衡设备根据用户 IP 地址,以及用户请求的 URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。
  5. 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务,选择的依据包括:
    • 根据用户 IP 地址,判断哪一台服务器距用户最近;
    • 根据用户所请求的 URL 中携带的内容名称,判断哪一台服务器上有用户所需内容;
    • 查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力。
  6. 区域负载均衡设备把服务器的 IP 地址返回给用户。
  7. 用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容传送到用户终端。
    如果这台缓存服务器上并没有用户想要的内容,而区域均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉到本地。
    缓存服务器发给用户,并根据用户自定义的缓存策略,判断要不要把内容缓存到缓存服务器上。

CDN 好处:

  • CDN 最大的好处,就是加速了内容的访问。用户与内容之间的物理距离缩短,用户的等待时间也得以缩短。而且,分发至不同线路的缓存服务器,也让跨运营商之间的访问得以加速。
  • CDN 还有安全方面的好处。内容进行分发后,源服务器的 IP 被隐藏,受到攻击的概率会大幅下降。而且,当某个服务器故障时,系统会调用临近的健康服务器进行服务,避免对用户造成影响。

CDN 缺点:

  • CDN 适用于静态的内容,不适用动态的内容。用户动态的实时交互数据,是难以缓存的。例如一些频繁修改的数据库表单内容等。(大家可能没想到,直播其实也是可以使用 CDN 的。感兴趣的同学可以搜一下“直播CDN”。)
  • 其次,很多应用提供商和内容服务商,为了保护自身的数据私密,不允许第三方公司 CDN 缓存他们的数据,只允许自家 CDN 缓存自家的数据。这个对用户体验会造成一定影响。
  • 第三,建设 CDN 意味着不菲的资金投入。不管是自己买服务器搭建 CDN,还是租用云服务提供商的 CDN 服务,都需要花钱。而且,区域越多,花的钱越多。这些 CDN 到底有没有人用,利用率是多少,很难精准预测。也许大部分时间里,利用率很低,就造成了资源浪费。

Nginx 是什么及作用

Nginx 是一个轻量级、高性能、稳定性高、并发性好的 HTTP 和反向代理服务器。`

keepalived 是什么及作用?

Keepalived 是 Linux 下一个轻量级别的高可用解决方案。

高可用其实有两种不同的含义:广义来讲是指整个系统的高可用行,狭义的来讲就是之主机的冗余和接管。

HAProxy 是什么以及作用

HAProxy 提供高可用性、负载均衡以及基于 TCP 和 HTTP 应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。

HAProxy 特别适用于那些负载特大的 web 站点,这些站点通常又需要会话保持或七层处理。HAProxy 运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架中,同时可以保护你的 web 服务器不被暴露到网络上。

什么是 RPC(Remote Procedure Call) 及应用场景?

RPC 是一种进程间通信方式。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。

即程序员无论是调用本地的还是远程的,本质上编写的调用代码基本相同(例如QQ远程操作)

什么是 socket?简述基于 tcp 协议的套接字通信流程。

Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口。

在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面,对用户来说,一组简单的接口就是全部。

  • 服务端:创建 socket 对象 -> 绑定 ip 端口 bind() -> 设置最大链接数 listen() -> accept() 等待连接 -> 与客户端的connect() 创建双向管道 -> send()、recv() 收发数据 -> close()
  • 客户端:创建 socket 对象 -> connect() -> 与服务端 accept() 创建双向管道 -> send()recv() 收发数据 -> close()

负载均衡

什么是负载均衡

负载均衡有两方面的含义:

  • 首先,大量的并发访问或数据流量分担到多台节点设备上分别处理,减少用户等待响应的时间。
  • 其次,单个重负载的运算分担到多台节点设备上做并行处理,每个节点设备处理结束后,将结果汇总,返回给用户,系统处理能力得到大幅度提高。

LVS 是什么及作用?

LVS :Linux 虚拟服务器。

作用:LVS 主要用于多服务器的负载均衡。

  • 它工作在网络层,可以实现高性能,高可用的服务器集群技术。
  • 它廉价,可把许多低性能的服务器组合在一起形成一个超级服务器。
  • 它易用,配置非常简单,且有多种负载均衡的方法。
  • 它稳定可靠,即使在集群的服务器中某台服务器无法正常工作,也不影响整体效果。另外可扩展性也非常好。

F5

负载均衡的硬件设备


05-网络 其他
https://flepeng.github.io/interview-10-网络-05-网络-其他/
作者
Lepeng
发布于
2020年8月8日
许可协议