当前位置: 首页 > 创领中心 > 网络优化

终于字浪费面 惋惜没掌握住....

  • 网络优化
  • 2024-11-15

大家好,我是小林。

分享一篇字节后端开发校招一面经,同窗反应面试官人很 nice,只管问的很细节,然而会疏导疑问方向,然而惋惜自己没掌握住,深问一点细节的,就不会了。

这一面关键是拷打基础方向,重点拷打了网络IO、Linux 操作系统、网络协定、mysql、算法。

名目关系

epoll 的上班原理?

先用 epoll_create 创立一个 epoll 对象 epfd,再经过 epoll_ctl 将要求监督的 socket 增加到epfd中,最后调用 epoll_wait 期待数据,当epoll_wait前往后,就可以遍历它前往的事情列表,而后依据事情类型做出相应的处置。

 s  socketAF_INET SOCK_STREAM binds listens  epfd  epoll_createepoll_ctlepfd  //将一切要求监听的socket增加到epfd中 { n  epoll_wait接纳到数据的socket{}}

epoll、select、poll的区别?

select 成功多路复用的方式是,将已衔接的 Socket 都放到一个文件形容符汇合,而后调用 select 函数将文件形容符汇合拷贝到内核里,让内核来审核能否有网络事情发生,审核的方式很粗犷,就是经过遍历文件形容符汇合的方式,当审核到有事情发生后,将此 Socket 标志为可读或可写, 接着再把整个文件形容符汇合拷贝回用户态里,而后用户态还要求再经过遍历的方法找到可读或可写的 Socket,而后再对其处置。

所以,关于 select 这种方式,要求启动2 次「遍历」文件形容符汇合,一次性是在内核态里,一个次是在用户态里 ,而且还会出现2 次「拷贝」文件形容符汇合,先从用户空间传入内核空间,由内核修正后,再传出到用户空间中。

select 经常使用固定长度的 BitsMap,表示文件形容符汇合,而且所允许的文件形容符的个数是有限度的,在 Linux 系统中,由内核中的 FD_SETSIZE 限度, 自动最大值为1024,只能监听 0~1023 的文件形容符。

poll 不再用 BitsMap 来存储所关注的文件形容符,取而代之用灵活数组,以链表方式来组织,打破了 select 的文件形容符个数限度,当然还会遭到系统文件形容符限度。

然而 poll 和 select 并没有太大的实质区别,都是经常使用「线性结构」存储进程关注的 Socket 汇合,因此都要求遍历文件形容符汇合来找到可读或可写的 Socket,期间复杂度为 O(n),而且也要求在用户态与内核态之间拷贝文件形容符汇合,这种方式随着并发数过去,性能的损耗会呈指数级增长。

epoll 经过两个方面,很好处置了 select/poll 的疑问。

可以看到 epoll 关系的接口作用:

epoll 的方式即使监听的 Socket 数量越多的时刻,效率不会大幅度降落,能够同时监听的 Socket 的数目也十分的多了,下限就为系统定义的进程关上的最大文件形容符个数。因此,epoll 被称为处置 C10K 疑问的利器。

select线性表要从用户态复制到内核态,详细怎样复制的?

用户态预备一个文件形容符汇合,通常是经常使用fd_set数据结构来表示,该汇合蕴含要监督的文件形容符。调用select系统调用时,将该文件形容符汇协作为参数传递给select函数。

内核态的select函数接纳到用户态传递的文件形容符汇合后,会在内核中创立一个与用户态相对应的数据结构 fdset,而后将用户空间的ufdset拷贝到内核空间fdset。

操作系统

进程、线程、协程的概念

系统创立进程的时刻,会给进程调配哪些资源?

会调配虚构内存空间、文件形容符、信号资源。

线程的资源怎样回收?

linux 线程分开有多种方式,如return,pthread_exit,pthread_cancel等;线程分为可结合的(joinable)和 分别的(detached)两种。

怎样看进程当中有哪些线程?

经常使用ps命令:经过在终端中运转ps -eLf命令,可以列出一切进程及其对应的线程信息。每个线程都会显示线程ID(TID)、进程ID(PID)、线程优先级(PRI)、CPU占用率(%CPU)、内存占用(%MEM)等信息。

怎样检查网络的形态?

可以经过 netstat 命令。

假设只想看close_wait形态的衔接,怎样看?

netstat napt grep close_wait

计网

HTTP协定形态码 500 501 502 503 504区分代表什么?可以举出详细场景嘛?

形态码500:

形态码501:

形态码502:

形态码503 :

形态码504 :

说一说四次挥手的整个环节?

TCP 四次挥手的环节如下:

详细环节:

你可以看到,每个方向都要求一个 FIN 和一个 ACK,因此通常被称为四次挥手。

Time_wait 为什么2MSL ?

关键是两个要素:

要素一:防止历史衔接中的数据,被前面相反四元组的衔接失误的接纳

假定 TIME-WAIT 没有期待期间或期间过短,被提早的数据包达到后会出现什么呢?

TIME-WAIT 期间过短,收到旧衔接的数据报文

如上图:

为了防止历史衔接中的数据,被前面相反四元组的衔接失误的接纳,因此 TCP 设计了 TIME_WAIT 形态,形态会继续2MSL时长,这个期间足以让两个方向上的数据包都被摈弃,使得原来衔接的数据包在网络中都人造隐没,再出现的数据包肯定都是新树立衔接所发生的。

要素二:保障「主动封锁衔接」的一方,能被正确的封锁

在 RFC 793 指出 TIME-WAIT 另一个关键的作用是:

TIME-WAIT - represents waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request.

也就是说,TIME-WAIT 作用是期待足够的期间以确保最后的 ACK 能让主动封锁方接纳,从而协助其反常封锁。

假设客户端(主动封锁方)最后一次性 ACK 报文(第四次挥手)在网络中失落了,那么依照 TCP 牢靠性准则,服务端(主动封锁方)会重发 FIN 报文。

假定客户端没有 TIME_WAIT 形态,而是在发完最后一次性回 ACK 报文就间接进入 CLOSE 形态,假设该 ACK 报文失落了,服务端则重传的 FIN 报文,而这时客户端曾经进入到封锁形态了,在收到服务端重传的 FIN 报文后,就会回 RST 报文。

TIME-WAIT 期间过短,没有确保衔接反常封锁

服务端收到这个 RST 并将其解释为一个失误(Connection reset by peer),这关于一个牢靠的协定来说不是一个优雅的中断方式。

为了防止这种状况出现,客户端肯定期待足够长的期间,确保服务端能够收到 ACK,假设服务端没有收到 ACK,那么就会触发 TCP 重传机制,服务端会从新发送一个 FIN,这样一去一来刚好两个 MSL 的期间。

TIME-WAIT 期间反常,确保了衔接反常封锁

客户端在收到服务端重传的 FIN 报文时,TIME_WAIT 形态的期待期间,会重置回 2MSL。

当存在少量close_wait的衔接时怎样处置?

CLOSE_WAIT 形态是「主动封锁方」才会有的形态,而且假设「主动封锁方」没有调用 close 函数封锁衔接,那么就无法收回 FIN 报文,从而无法使得 CLOSE_WAIT 形态的衔接转变为 LAST_ACK 形态。

所以,当服务端出现少量 CLOSE_WAIT 形态的衔接的时刻,说明服务端的程序没有调用 close 函数封锁衔接。

那什么状况会造成服务端的程序没有调用 close 函数封锁衔接?这时刻通常要求排查代码。

咱们先来剖析一个普通的 TCP 服务端的流程:

或许造成服务端没有调用 close 函数的要素,如下。

第一个要素:第 2 步没有做,没有将服务端 socket 注册到 epoll,这样有新衔接来到时,服务端没方法感知这个事情,也就无法失掉到已衔接的 socket,那服务端人造就没时机对 socket 调用 close 函数了。

不过这种要素出现的概率比拟小,这种属于显著的代码逻辑 bug,在前期 read view 阶段就能发现的了。

第二个要素:第 3 步没有做,有新衔接来到时没有调用 accpet 失掉该衔接的 socket,造成当有少量的客户端主动断开了衔接,而服务端没时机对这些 socket 调用 close 函数,从而造成服务端出现少量 CLOSE_WAIT 形态的衔接。

出现这种状况或许是由于服务端在口头 accpet 函数之前,代码卡在某一个逻辑或许提早抛出了异常。

第三个要素:第 4 步没有做,经过 accpet 失掉已衔接的 socket 后,没有将其注册到 epoll,造成后续收到 FIN 报文的时刻,服务端没方法感知这个事情,那服务端就没时机调用 close 函数了。

第四个要素:第 6 步没有做,当发现客户端封锁衔接后,服务端没有口头 close 函数,或许是由于代码漏处置,或许是在口头 close 函数之前,代码卡在某一个逻辑,比如出现死锁等等。

可以发现,当服务端出现少量 CLOSE_WAIT 形态的衔接的时刻,通常都是代码的疑问,这时刻咱们要求针对详细的代码一步一步的启动排查和定位,关键剖析的方向就是服务端为什么没有调用 close。

什么是聚簇索引和非聚簇索引?

InooDB 为什么要经常使用聚簇索引?

经常使用聚簇索引的一些好处:

什么是 InooDB外面的联结索引?

经过将多个字段组分解一个索引,该索引就被称为联结索引。

比如,将商品表中的 product_no 和 name 字段组分解联结索引(product_no, name),创立联结索引的方式如下:

  index_product_no_name  productproduct_no name

联结索引(product_no, name)的 B+Tree 示用意如下(图中叶子节点之间我画了单向链表,然而实践上是双向链表,原图我找不到了,修正不了,偷个懒我不重画了,大家脑补成双向链表就行)。

可以看到,联结索引的非叶子节点用两个字段的值作为 B+Tree 的 key 值。当在联结索引查问数据时,先按 product_no 字段比拟,在 product_no 相反的状况下再按 name 字段比拟。

也就是说,联结索引查问的 B+Tree 是先按 product_no 启动排序,而后再 product_no 相反的状况再按 name 字段排序。

因此,经常使用联结索引时,存在最左婚配准则,也就是依照最左优先的方式启动索引的婚配。在经常使用联结索引启动查问的时刻,假设不遵照「最左婚配准则」,联结索引会失效,这样就无法应用到索引极速查问的个性了。

比如,假设创立了一个(a, b, c)联结索引,假设查问条件是以下这几种,就可以婚配上联结索引:

要求留意的是,由于有查问优化器,所以 a 字段在 where 子句的顺序并不关键。

然而,假设查问条件是以下这几种,由于不合乎最左婚配准则,所以就无法婚配上联结索引,联结索引就会失效:

下面这些查问条件之所以会失效,是由于(a, b, c)联结索引,是先按 a 排序,在 a 相反的状况再按 b 排序,在 b 相反的状况再按 c 排序。所以,b 和 c 是全局无序,部分相对有序的,这样在没有遵照最左婚配准则的状况下,是无法应用到索引的。

我这里举联结索引(a,b)的例子,该联结索引的 B+ Tree 如下(图中叶子节点之间我画了单向链表,然而实践上是双向链表,原图我找不到了,修正不了,偷个懒我不重画了,大家脑补成双向链表就行)。

可以看到,a 是全局有序的(1, 2, 2, 3, 4, 5, 6, 7 ,8),而 b 是全局是无序的(12,7,8,2,3,8,10,5,2)。因此,间接口头where b = 2这种查问条件没有方法应用联结索引的,应用索引的前提是索引里的 key 是有序的。

只要在 a 相反的状况才,b 才是有序的,比如 a 等于 2 的时刻,b 的值为(7,8),这时就是有序的,这个有序形态是部分的,因此,口头where a = 2 and b = 7是 a 和 b 字段能用到联结索引的,也就是联结索引失效了。

给出一个表A 有a1~a5 个列,联结索引(a2,a1)select a5 from A where a2=1 and a1=2 请问用到联结索引了嘛?它的详细环节呢?

查问合乎最左婚配准则,可以a1 和 a2 都可以经常使用联结索引。

详细的查问环节,在二级索引 b+树找到合乎条件 a2 和 a1 的记载,而后失掉这些记载的 id 值,拿 id 值去主键索引查问 a5 列的值,这里触及了回表的查问。

算法

滑动窗口

  • 关注微信

本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载联系作者并注明出处:https://clwxseo.com/wangluoyouhua/8935.html

猜你喜欢

热门资讯

关注我们

微信公众号