TInyWebServer面试题

news2025/1/6 19:31:06

一、项目介绍
(1)为什么要做这样一个项目?

(2)介绍一下你的项目
这个项⽬是我在学习计算机⽹络和Linux socket编程过程中独⽴开发的轻量级Web服务器,服务器的⽹络模型是主从reactor加线程池的模式,IO处理使⽤了⾮阻塞IO和IO多路复⽤技术,具备处理多个客户端的http请求和ftp请求,以及对外提供轻量级储存的能⼒。这个项⽬从4⽉份开始做,到7⽉份完成了项⽬的整体功能。
项⽬中的⼯作可以分为两部分,⼀部分是服务器⽹络框架、⽇志系统、存储引擎等⼀些基本系统的搭建,另⼀部分是为了提⾼服务器性能所做的⼀些优化,⽐如缓存机制、内存池等⼀些额外系统的搭建。最后还对系统中的部分功能进⾏了功能和压⼒测试。对于存储引擎的压⼒测试,在本地测试下,存储引擎读操作的QPS可以达到36万,写操作的QPS可以达到30万。对于⽹络框架的测试,使⽤webbench创建1000个进程对服务器进⾏60s并发请求,测试结果表明,对于短连接的QPS为1.8万,对于⻓连接的QPS为5.2万。
在开发阶段对于⼀些功能的不同实现⽅法,我先思考⼀下各个⽅法的应⽤场景和效率,再进⾏选择,通过这个项⽬,我学习了两种Linux下的⾼性能⽹络模式,熟悉了Linux环境下的编程,并在后期优化的过程中了解了⼀些服务端性能调优的⽅法。

二、线程池相关
(1)手写线程池

(2)线程的同步机制有哪些?

(3)线程池中的工作线程是一直等待吗?

(4)你的线程池工作线程处理完一个任务后的状态是什么?
这⾥要分两种情况考虑
(1)当处理完任务后如果请求队列为空时,则这个线程重新回到阻塞等待的状态
(2)当处理完任务后如果请求队列不为空时,那么这个线程将处于与其他线程竞争资源的状态,谁获得锁谁就获得了处理事件的资格。

(5)如果1000个客户端同时进行访问请求,线程数不多,怎么能及时响应处理每一个呢?
⾸先这种问法就相当于问服务器如何处理⾼并发的问题。
⾸先我项⽬中使⽤了I/O多路复⽤技术,每个线程中管理⼀定数量的连接,只有线程池中的连接有请求,epoll就会返回请求的连接列表,管理该连接的线程获取活动列表,然后依次处理各个连接的请求。如果该线程没有任务,就会等待主reactor分配任务。这样就能达到服务器⾼并发的要求,同⼀时刻,每个线程都在处理⾃⼰所管理连接的请求。

(6)如果一个客户请求需要占用线程很久的时间,会不会影响接下来的客户请求呢?有什么好的策略呢?

影响分析
会影响这个⼤请求的所在线程的所有请求,因为每个eventLoop都是依次处理它通过epoll获得的活动事件,也就是活动连接。如果该eventloop处理的连接占⽤时间过⻓的话,该线程后续的请求只能在请求队列中等待被处理,从⽽影响接下来的客户请求。
应对策略

  1. 主 reactor 的⻆度:可以记录⼀下每个从reactor的阻塞连接数,主reactor根据每个reactor的当前负载来分发请求,达到负载均衡的效果。
  2. 从 reactor 的⻆度:
    超时时间:为每个连接分配⼀个时间⽚,类似于操作系统的进程调度,当当前连接的时间⽚⽤完以后,将其重新加⼊请求队列,响应其他连接的请求,进⼀步来说,还可以为每个连接设置⼀个优先级,这样可以优先响应重要的连接,有点像 HTTP/2 的优先级。
    关闭时间:为了避免部分连接⻓时间占⽤服务器资源,可以给每个连接设置⼀个最⼤响应时间,当⼀个连接的最⼤响应时间⽤完后,服务器可以主动将这个连接断开,让其重新连接。

三、并发模型相关
(1)简单说一下服务器使用的并发模型

(2)reactor\proactor\主从reactor模型的区别

  1. Reactor 是⾮阻塞同步⽹络模式,感知的是就绪可读写事件。在每次感知到有事件发⽣(⽐如可读就绪事件)后,就需要应⽤进程主动调⽤ read ⽅法来完成数据的读取,也就是要应⽤进程主动将 socket 接收缓存中的数据读到应⽤进程内存中,这个过程是同步的,读取完数据后应⽤进程才能处理数据。
  2. Proactor 是异步⽹络模式, 感知的是已完成的读写事件。在发起异步读写请求时,需要传⼊数据缓冲区的地址(⽤来存放结果数据)等信息,这样系统内核才可以⾃动帮我们把数据的读写⼯作完成,这⾥的读写⼯作全程由操作系统来做,并不需要像 Reactor 那样还需要应⽤进程主动发起 read/write 来读写数据,操作系统完成读写⼯作后,就会通知应⽤进程直接处理数据。
    Proactor这么好⽤,那你为什么不⽤?
    在 Linux 下的异步 I/O 是不完善的, aio 系列函数是由 POSIX 定义的异步操作接⼝,不是真正的操作系统级别⽀持的,⽽是在⽤户空间模拟出来的异步,并且仅仅⽀持基于本地⽂件的 aio 异步操作,⽹络编程中的 socket 是不⽀持的,也有考虑过使⽤模拟的proactor模式来开发,但是这样需要浪费⼀个线程专⻔负责 IO 的处理。
    ⽽ Windows ⾥实现了⼀套完整的⽀持 socket 的异步编程接⼝,这套接⼝就是 IOCP ,是由操作系统级别实现的异步 I/O,真正意义上异步 I/O,因此在 Windows ⾥实现⾼性能⽹络程序可以使⽤效率更⾼的 Proactor ⽅案。

reactor模式中,各个模式的区别?
Reactor模型是⼀个针对同步I/O的⽹络模型,主要是使⽤⼀个reactor负责监听和分配事件,将I/O事件分派给对应的Handler。新的事件包含连接建⽴就绪、读就绪、写就绪等。reactor模型中⼜可以细分为单reactor单线程、单reactor多线程、以及主从reactor模式。

  1. 单reactor单线程模型就是使⽤ I/O 多路复⽤技术,当其获取到活动的事件列表时,就在reactor中进⾏读取请求、业务处理、返回响应,这样的好处是整个模型都使⽤⼀个线程,不存在资源的争夺问题。但是如果⼀个事件的业务处理太过耗时,会导致后续所有的事件都得不到处理。
  2. 单reactor多线程就是⽤于解决这个问题,这个模型中reactor中只负责数据的接收和发送,reactor将业务处理分给线程池中的线程进⾏处理,完成后将数据返回给reactor进⾏发送,避免了在reactor进⾏业务处理,但是 IO 操作都在reactor中进⾏,容易存在性能问题。⽽且因为是多线程,线程池中每个线程完成业务后都需要将结果传递给reactor进⾏发送,还会涉及到共享数据的互斥和保护机制。
  3. 主从reactor就是将reactor分为主reactor和从reactor,主reactor中只负责连接的建⽴和分配,读取请求、业务处理、返回响应等耗时的操作均在从reactor中处理,能够有效地应对⾼并发的场合。

subreactor负责读写数据,由线程池进⾏业务处理。

在这里插入图片描述

(3)你用了epoll,说一下为什么用epoll,还有其他复用方式吗?区别是什么

⽂件描述符集合的存储位置
对于 select 和 poll 来说,所有⽂件描述符都是在⽤户态被加⼊其⽂件描述符集合的,每次调⽤都需要将整个集合拷⻉到内核态;epoll 则将整个⽂件描述符集合维护在内核态,每次添加⽂件描述符的时候都需要执⾏⼀个系统调⽤。系统调⽤的开销是很⼤的,⽽且在有很多短期活跃连接的情况下,由于这些⼤量的系统调⽤开销,epoll 可能会慢于 select 和 poll。

⽂件描述符集合的表示⽅法
select 使⽤线性表描述⽂件描述符集合,⽂件描述符有上限;poll使⽤链表来描述;epoll底层通过红⿊树来描述,并且维护⼀个就绪列表,将事件表中已经就绪的事件添加到这⾥,在使epoll_wait调⽤时,仅观察这个list中有没有数据即可。
遍历⽅式
select 和 poll 的最⼤开销来⾃内核判断是否有⽂件描述符就绪这⼀过程:每次执⾏ select 或 poll 调⽤时,它们会采⽤遍历的⽅式,遍历整个⽂件描述符集合去判断各个⽂件描述符是否有活动;epoll 则不需要去以这种⽅式检查,当有活动产⽣时,会⾃动触发 epoll 回调函数通知epoll⽂件描述符,然后内核将这些就绪的⽂件描述符放到就绪列表中等待epoll_wait调⽤后被处理。
触发模式
select和poll都只能⼯作在相对低效的LT模式下,⽽epoll同时⽀持LT和ET模式。
适⽤场景
当监测的fd数量较⼩,且各个fd都很活跃的情况下,建议使⽤select和poll;当监听的fd数量较多,且单位时间仅部分fd活跃的情况下,使⽤epoll会明显提升性能。

(4)IO多路复⽤
1)说⼀下什么是ET,什么是LT,有什么区别?

  1. LT:⽔平触发模式,只要内核缓冲区有数据就⼀直通知,只要socket处于可读状态或可写状态,就会⼀直返回sockfd;是默认的⼯作模式,⽀持阻塞IO和⾮阻塞IO
  2. ET:边沿触发模式,只有状态发⽣变化才通知并且这个状态只会通知⼀次,只有当socket由不可写到可写或由不可读到可读,才会返回其sockfd;只⽀持⾮阻塞IO
    2)LT什么时候会触发?ET呢?
    LT模式
  3. 对于读操作
    只要内核读缓冲区不为空,LT模式返回读就绪。
  4. 对于写操作
    只要内核写缓冲区还不满,LT模式会返回写就绪。
    ET模式
  5. 对于读操作
    当缓冲区由不可读变为可读的时候,即缓冲区由空变为不空的时候。
    当有新数据到达时,即缓冲区中的待读数据变多的时候。
    当缓冲区有数据可读,且应⽤进程对相应的描述符进⾏EPOLL_CTL_MOD 修改EPOLLIN事件时。
  6. 对于写操作
    当缓冲区由不可写变为可写时。
    当有旧数据被发送⾛,即缓冲区中的内容变少的时候。
    当缓冲区有空间可写,且应⽤进程对相应的描述符进⾏EPOLL_CTL_MOD 修改EPOLLOUT事件时。
    3)为什么ET模式不可以⽂件描述符阻塞,⽽LT模式可以呢?
    因为ET模式是当fd有可读事件时,epoll_wait()只会通知⼀次,如果没有⼀次把数据读完,那么要到下⼀次fd有可读事件epoll才会通知。⽽且在ET模式下,在触发可读事件后,需要循环读取信息,直到把数据读完。如果把这个fd设置成阻塞,数据读完以后read()就阻塞在那了。⽆法进⾏后续请求的处理。
    LT模式不需要每次读完数据,只要有数据可读,epoll_wait()就会⼀直通知。所以 LT模式下去读的话,内核缓冲区肯定是有数据可以读的,不会造成没有数据读⽽阻塞的情况。

四、http报文解析相关

(1)为什么用状态机

(2)状态机转移图画一下

(3)https协议为什么安全

(4)https的ssl连接过程

(5)GET和POST的区别

五、数据库登录注册相关
(1)登录说一下?

(2)你这个保存状态了吗?如果要保存,你会怎么做?(cookie和session)

(3)登录中的用户名和密码你是load到本地,然后使用map匹配的,如果有10亿数据,即使load到本地后hash,也是很耗时的,你要怎么优化?

(4)用的mysql啊,redis了解吗?用过吗?

六、定时器相关
(1)为什么要用定时器?

(2)说一下定时器的工作原理

(3)双向链表啊,删除和添加的时间复杂度说一下?还可以优化吗?

(4)最小堆优化?说一下时间复杂度和工作原理

七、日志相关
(1)说下你的日志系统的运行机制?

(2)为什么要异步?和同步的区别是什么?

(3)现在你要监控一台服务器的状态,输出监控日志,请问如何将该日志分发到不同的机器上?(消息队列)

八、压测相关
(1)服务器并发量测试过吗?怎么测试的?

(2)webbench是什么?介绍一下原理

(3)测试的时候有没有遇到问题?

九、综合能力
(1)你的项目解决了哪些其他同类项目没有解决的问题?
项⽬中我主要的⼯作可以分为两部分:

  1. ⼀部分是服务器⽹络框架、⽇志系统、存储引擎等⼀些基本系统的搭建,这部分的难点主要就是技术的理解和选型,以及将⼀些开源的框架调整后应⽤到我的项⽬中去。

  2. 另⼀部分是为了提⾼服务器性能所做的⼀些优化,⽐如缓存机制、内存池等⼀些额外系统的搭建。这部分的难点主要是找出服务器的性能瓶颈,然后结合⾃⼰的想法去突破这个瓶颈,提⾼服务器的性能

  3. ⼀⽅⾯是对不同的技术理解不够深刻,难以选出最合适的技术框架。这部分的话我主要是反复阅读作者在GitHub提供的⼀些技术⽂档,同时也去搜索⼀些技术对⽐的⽂章去看,如果没有任何相关的资料我会尝试去联系作者。

  4. 另⼀⽅⾯是编程期间遇到的困难,在代码编写的过程中由于⼯程能⼒不⾜,程序总会出现⼀些bug。这部分的话我⾸先是通过⽇志去定位bug,然后推断bug出现的原因并尝试修复,如果是⾃⼰⽬前⽔平⽆法修复的bug,我会先到⽹上去查找有没有同类型问题的解决⽅法,然后向同学或者直接到StackOverflow等⼀些国外知名论坛上求助。
    (2)说一下前端发送请求后,服务器处理的过程,中间涉及哪些协议?

(3)项⽬中⽤到哪些设计模式?
单例模式:在线程池、内存池中都有使⽤到。
单例模式可以分为懒汉式和饿汉式,两者之间的区别在于创建实例的时间不同:
懒汉式:指系统运⾏中,实例并不存在,只有当需要使⽤该实例时,才会去创建并使⽤实例。(这种⽅式要考虑线程安全)
饿汉式:指系统⼀运⾏,就初始化创建实例,当需要时,直接调⽤即可。(本身就线程安全,没有多线程的问题)

(4)这个web服务器是你⾃⼰申请的域名吗
我没有申请域名,但是阿⾥云服务器上⾃带⼀个公⽹ip,可以直接通过公⽹ip来访问服务器。但是本地测试的话,我⼀般使⽤本地回环ip,127.0.0.1来进⾏访问。能 ping 通 127.0.0.1 说明本机的⽹卡和IP协议安装都没有问题。

(5)你是如何对项⽬进⾏测试的?
对项⽬的测试分为两部分:基本功能模块的测试和扩展功能模块的测试。
【基本功能测试】

  1. ⽇志系统
    写⼊⽇志类型、等级
    多个线程同时写⼊的响应
    短期⼤量⽇志进⾏写⼊
  2. ⽹络框架
    正确接收 client 连接和分发
    正确感知 client 连接的读写事件
    正确对 client 连接进⾏读写
    ⾼并发、多请求(webbench)
  3. 存储引擎
    正确写⼊和读取
    定时落盘(写⼊⽂件和定时写⼊)
    多个线程同时读取和写⼊
    单个线程读取和写⼊⼤量数据
    【扩展功能测试】
  4. 线程池
    能否将任务放⼊任务队列,任务是否能够正确执⾏多个线程同时往任务队列放⼊任务
  5. 内存池
    能否正确分配内存(空对象、⼤内存、⼩内存),调⽤对象的构造函数和析构函数多个线程同时申请内存
  6. 缓存机制
    能否成功命中缓存
    多个线程读取缓存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1969507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VMware虚拟机网络模式配置详解【原理,功能,特点层面】

VMware虚拟机网络模式配置详解【原理,功能,特点层面】 文章目录 VMware虚拟机网络模式配置详解【原理,功能,特点层面】桥接模式(Bridged)原理功能点介绍虚拟网络编辑器配置虚拟机配置 配置教程编辑-虚拟网络编辑器虚拟机网络配置 特点 NAT模式概念功能点…

数学建模--智能算法之蚁群优化算法

目录 基本原理 算法步骤 Python代码示例 应用领域 特点及改进 蚁群优化算法在解决哪些具体组合优化问题方面表现最为突出? 如何有效地改进蚁群优化算法以提高其收敛速度和避免陷入局部最优的问题? 蚁群优化算法与其他群体智能优化算法&#xff0…

三维旋转矩阵

前言 本文讲述三维旋转的矩阵推导,推导过程遵循下面的规则: 本文的坐标系是基于右手坐标系的逆时针旋转为正向旋转 围绕坐标轴的旋转 x x x轴 我们假设旋转的点为 P P P 假设旋转之前点 P P P的坐标为 ( x 0 , y 0 , z 0 ) (x_0,y_0,z_0) (x0​,y0​,…

CAN总线中注入拓展帧、远程帧,CAPL通用函数。

🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】🍅 玩转CANoe,博客目录大全,点击跳转👉 【测试需求】:CAN总线要求DUT 接收到非预期的扩展帧、远程帧时,通信正常,…

vulhub:nginx解析漏洞nginx_parsing

这个解析漏洞其实是PHP CGI的漏洞,在PHP的配置文件中有一个关键的选项cgi.fix_pathinfo默认是开启的,当URL中有不存在的文件,PHP就会向前递归解析。在一个文件/xx.jpg后面加上/.php会将 /xx.jpg/xx.php 解析为 php 文件 条件: Ngi…

釉面陶瓷器皿和玻璃器皿 SOR/2016-175认证

釉面陶瓷制品和釉面玻璃制品设计用于盛装食品,包括扁平餐具、杯子或马克杯、小号或大号凹形器皿(杯子或马克杯除外)以及水罐。这些法规适用于以下釉面陶瓷制品和釉面玻璃制品: 完全或部分由陶瓷或玻璃制成完全或部分覆盖含铅或镉…

MATLAB(12)预测模型

一、前言 在MATLAB中创建一个预测模型通常涉及多个步骤,包括数据准备、模型选择、训练模型、评估模型以及使用模型进行预测。以下是一个简化的例子,说明如何使用MATLAB中的内置函数来创建一个基于线性回归的预测模型。这个例子将使用MATLAB的fitlm函数来…

C语言函数初识

文章目录 🍊自我介绍🍊函数初识前言概念具体实例解释函数的实用性 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞关注评论收藏(一键四连)哦~ 🍊自我介绍 Hello,大家好,我是小珑也…

院人全年无休计划背后,芒果把To C综艺玩明白了

《种地吧》掉粉闹得沸沸扬扬,不少禾伙人希望芒果把“十个勤天”挖走,毕竟芒果做综艺群像确实是一把好手,“院人”就是最好的例子。 在#种地吧粉丝让芒果把十个勤天挖走#的话题登上热搜之后,“学分们”(院人粉丝&#…

JS等待所有方法执行完成在执行下一个方法,promise All

在工作中会遇到这样一个场景,前端需要拿到不同接口返回的结果在执行某个逻辑,当使用链式那样的方式去请求,等一个接口响应完在请求下一个接口,这种方法就会导致请求时间特别长。这个时候就可以使用promise all,同时请求…

国产麒麟操作系统下搞单机版

去年纪委单位的一个项目,因为单位保密性质,档案必须要保密,要求采用单机版, 要求跟EXE那样,双击打开,阿公单位信息人员电脑操作水平化滞后还是相当严重啊。 去年已经给他花了时间按他们的要求实现了。 上周…

【直角三角形】python刷题记录

R3-新增每日一题打卡。 目录 思路(遍历中间乘法原理): 乘法原理如下: ps: python的zip操作 矩阵转置 并行遍历 对象组合 创建字典 处理不等迭代长度 思路: 这题遍历主要从直角点开始遍历,用到了…

软科中国大学排名爬虫+数据可视化

这一期是关于软科中国大学排名的爬虫分析 目标网址:https://www.shanghairanking.cn/rankings/bcur/2024 每页30所学校信息,共20页 点击翻页,你发现网址没有发生变化,说明该页面信息应该是利用js实现动态加载数据的方式展示的&am…

基于51单片机的篮球计分器Protues仿真设计(LCD12864显示)

目录 一、设计背景 二、设计要求 三、仿真演示 四、程序展示(部分) 一、设计背景 近年来,随着国家对体育事业的日益重视,体育运动在全民中的普及程度显著提高,篮球作为一项广受欢迎的运动项目,其比赛与…

Linux云计算 |【第二阶段】CLUSTER-DAY1

主要内容: 集群概念、LVS概述、LVS-NAT集群、LVS-DR集群 一、集群概念 集群(Cluster)是指将多台计算机(节点)通过网络连接在一起,形成一个统一的计算资源池,共同完成一项或多项任务的系统。集…

如何使用 FTP 将文件上传到 WordPress

作为新手站长,在学习如何管理和维护自己的网站时,掌握一些基本的文件管理技能是非常重要的。通过FTP上传文件到WordPress网站是其中一个必备的技能。本文将详细介绍如何使用FTP将文件上传到WordPress,并分享一些在使用Hostease主机的过程中积…

场外个股期权是什么?20倍奇迹,神仙操作的场外个股期权!

今天带你了解场外个股期权是什么?20倍奇迹,神仙操作的场外个股期权!场外期权交易具有独特的特点和优势,它结合了“彩票”和“保险”的双重属性,为投资者提供了一种灵活且高效的投资工具。 场外个股期权是一种金融合约…

Linux内存不够了?看看如何开启虚拟内存增加内存使用量

1、为什么要使用虚拟内存 当我们没有多余的钱去购买大内存的云服务器时,但是当前服务器里面的软件和程序运行的比较多导致内存不够用了。这个时候可以通过增加虚拟内存来扩大内存容量。但是在启用虚拟内存时,需要仔细考虑系统的实际需求和硬件配置&#…

前端技术回顾系列 14 | 总结 + Vue 3.x 必修课

欢迎关注公众号:CodeFit 创作不易,如果你觉得这篇文章对您有帮助,请不要忘了 点赞、分享 和 关注,为我的 持续创作 提供 动力! 1. 回顾系列的初衷和目标 在六月初,我开始编写 「前端技术回顾系列 2024」&a…

⭕️【读论文】Learning To Count Everything

2021 IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR) 任务名称: visual counting ; few shot counting;crowd counting;cell counting 目录 Abstract 1. Introduction 2. Related Works 3. Few-…