review3

60 阅读11分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情

START

  1. 解释是什么的问题。
  2. 解释这个技术的应用点、应用场景在哪里。
  3. 整理一下这个问题的优缺点是什么。

前言

见上上篇:review1[1-11]

见上一篇:review2[12-20]

21、正向代理和反向代理的区别?

  • (解释是什么的问题。)
    • 正向代理:就是客户端代理,帮助客户端方位无法访问的服务端资源
    • 反向代理:是服务器的代理,帮助服务器做负载均衡,安全防护等。比如nginx
    • 区别:
      • 正向代理:用来解决访问限制问题,服务端不知道真正的客户端是谁
      • 反向代理:提供负载均衡、安全防护等作用。客户端不知道真正的服务端是谁

22、域名解析过程是怎样的?

以www.baidu.com为例,主要通过五个步骤进行域名解析

  1. 浏览器访问 www.baidu.com,询问本地 DNS 服务器是否缓存了该网址解析后的 IP 地址。
  2. 如果本地 DNS 服务器没有缓存的话,就去 root-servers.net 根服务器查询该网址对应的 IP 地 址。
  3. 根服务器返回顶级域名服务器的网址 gtld-servers.net,然后本地 DNS 服务器去顶级域名服务 器查询该网址对应的 IP 地址。
  4. 顶级域名服务器返回 www.baidu.com 主区域服务器的地址,然后本地 DNS 服务器去 www.ba idu.com 主区域服务器查询此域名对应的 IP 地址。
  5. 本地 DNS 服务器拿到 www.baidu.com 解析后的 IP 地址后,缓存起来以便备查,然后把解析 后的 IP 地址返回给浏览器。

23、TCP协议三次握手、四次挥手的过程,为什么挥手要4次?

第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

如果TCP传输过程中ACK丢失会怎样?

由于server端发送syn_ack报文后进入SYN_RCVD状态,就会启动tcp重传计时器,超时时就会重新发送syn_ack报文,总共发送 net.ipv4.tcp_synack_retries次;客户端在没有收到重传的syn_ack之前,发送数据给server端,由于server端的状态为SYN_RCVD状态,而不是ESTABLISHED状态,就会发送RST报文给client端,客户端就能接收到服务器侧未收到ack报文。

  • 第一次挥手:客户端发出释放FIN=1,自己序列号seq=u,进入FIN-WAIT-1状态
  • 第二次挥手:服务器收到客户端的后,发出ACK=1确认标志和客户端的确认号ack=u+1,自己的序列号seq=v,进入CLOSE-WAIT状态
  • 第三次挥手:客户端收到服务器确认结果后,进入FIN-WAIT-2状态。此时服务器发送释放FIN=1信号,确认标志ACK=1,确认序号ack=u+1,自己序号seq=w,服务器进入LAST-ACK(最后确认态)
  • 第四次挥手:客户端收到回复后,发送确认ACK=1,ack=w+1,自己的seq=u+1,客户端进入TIME-WAIT(时间等待)。客户端经过2个最长报文段寿命后,客户端CLOSE;服务器收到确认后,立刻进入CLOSE状态。

为什么三次握手和四次挥手?

  • 三次握手时,服务器同时把ACK和SYN放在一起发送到了客户端那里
  • 四次挥手时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方 ACK 和 FIN 一般都会分开发送。

(三次)

建立连接---- C发包,S接收。S:C有消息

S发包,C接收。C:S在了

C发包,S接收

(四次)

断开连接 ---- C发包,S接收。S:C请求结束

S发包,C接收。C:S已收到,等待S关闭

S发包,C接收。C:S可以关闭了

C发包,S接收。S:已关闭

24、nextTick, setTimeout/setInterval 以及 setImmediate 三者有什么区别?

  • (解释是什么的问题)
    • setTimeout:
    • setInterval:不断重复
    • setImmediate: 一旦poll阶段完成,就立即执行的脚本代码。**即时计时器立即执行工作,它是在事件轮询之后执行,为了防止轮询阻塞,每次只会调用一个。**nextTick()的回调函数执行的优先级要高于setImmediate();
    • nextTick: 它和setImmediate()执行的顺序不一样,它是在事件轮询之前执行,为了防止I/O饥饿,所以有一个默认process.maxTickDepth=1000来限制事件队列的每次循环可执行的nextTick()事件的数目。
  • 总结:
    • nextTick()的回调函数执行的优先级要高于setImmediate();
  • 区别
    • process.nextTick(),效率最高,消费资源小,但会阻塞CPU的后续调用; 
    • setTimeout(),精确度不高,可能有延迟执行的情况发生,且因为动用了红黑树,所以消耗资源大; 
    • setImmediate(),消耗的资源小,也不会造成阻塞,但效率也是最低的。

25、说一下你在项目的安全性做了哪些工作?

  • (解释是什么的问题。)
    • 在前端做安全性的工作要先知道恶意攻击人员从哪几个方面入手。前端主要被攻击的方式有下面几个

XSS攻击【代码注入问题】

  • xss分为存储型(持久型):存储在服务器 反射型(非持久型):改变url
  • xss就是攻击者把一些可执行的代码嵌入到代码中,比如<script>...</script>,这里面可以写一些函数获取到我们的cookie,sessionid等。
    • 如下图,用户评论的时候可以这样写

image.png

解决
  1. 过滤转义

    1. 把输入评论时候的内容关于符号类的东西。比如:‘<’,'>'...转义

    【对于URL地址的转义可以使用encodeURI,当你需要编码URL中的参数的时候,那么encodeURIComponent是最好方法。】

        const signs = {
          '&''&amp',
          '<''&lt',
          '>''&gt',
          '"''&quot',
          "'"'&#39'
        }
        const signReg = /[&<>"']/g
        function escape(string) {
                return (string && reUnescapedHtml.test(string))
                    ? string.replace(reUnescapedHtml, (chr) =>htmlEscapes[chr])
                    : string
    2. 使用xss.js插件
    
  2. Cookie设置HttpOnly

CSRF攻击【http问题】

  • 跨站点请求伪造(Cross-Site Request Forgeries),也被称为 one-click attack 或者 session riding。冒充用户发起请求(在用户不知情的情况下), 完成一些违背用户意愿的事情(如修改用户信息,删除评论等)。
  • 特点
    • 通常在第三方网站上(点击广告链接)
    • 攻击者不能获取cookie,只能使用
  • 解决(防御)
    • 验证码,强制要求人工交互再发请求
    • 使用post请求,避免攻击者在url上拿到参数
    • 服务端校验referer
    • 随机token 每次页面访问生成一个token 请求时带上
  • 如何解决:
  1. 请求参数加密,使用sm3(国家标准)
  2. 验证码登录-图形验证码、手机验证码
  3. 使用https
  4. 输入区域转义代码内容

26、当一张表数据量比较多的时候,为了提高查询速度,你们一般会使用哪些方式做优化?

  • 先沟通
  • 分页
  • 触底滚动加载
  • 虚拟列表

27、webSocket与传统的http相比有什么优势?

  • (解释是什么的问题)
    • webSocket: 是Web浏览器和服务器之间的一种全双工通信协议。一旦Web客户端与服务端建立起连接,之后的全部数据通信都通过这个连接进行。通信过程中,可互相发送JSON、XML、HTML或图片等任意格式的数据。
  • 与http比较
    • 相同点
      • 都是基于TCP的应用层协议;
      • 都使用Request/Response模型进行连接的建立;
      • 在连接的建立过程中对错误的处理方式相同,在这个阶段WS可能返回和HTTP相同的返回码;
      • 都可以在网络中传输数据。
    • 不同点
      • WS使用HTTP来建立连接,但是定义了一系列新的header域,这些域在HTTP中并不会使用;
      • WS是HTML5中的协议,支持持久连接;而Http协议不支持持久连接。
      • WS的连接不能通过中间人来转发,它必须是一个直接连接;
      • WS连接建立之后,通信双方都可以在任何时刻向另一方发送数据;
      • WS连接建立之后,数据的传输使用帧来传递,不再需要Request消息;
      • WS的数据帧有序。
  • WS 优点
    • websocket则允许我们在一条ws连接上同时并发多个请求
    • http协议的头部太大,websocket则因为复用长连接而没有这一问题
    • websocket支持服务器推送消息,这带来了及时消息通知的更好体验,也是ajax请求无法达到的。
  • 解决了传统轮询,长轮询带的问题——服务器过载,延迟等
  • WS 缺点
    • 服务器长期维护长连接需要一定的成本
    • 各个浏览器支持程度不一
    • websocket 是长连接,受网络限制比较大,需要处理好重连,比如用户进电梯或电信用户打个电话网断了,这时候就需要重连
  • WS 应用
    • 实时通讯领域较多,聊天,弹幕,游戏,

28、如何用同一套代码部署到服务器中,怎么区分当前本地开发环境还是线上环境?是测试环境还是生产环境呢,怎么去区分?

node中提供的变量:process.env.NODE_ENV 根据域名判断

29、待支付的订单,到期后主动取消这个功能你会怎么设计去做?

  • 定时器,倒计时时间为0后,改变订单状态
    • 优点:实现容易,成本低
    • 缺点:时间可能不准确,数据库压力大
  • 后端监听

30、如果要做音视频的安全性,你能想到哪些方案?

31、多台服务器部署定时任务怎么保证一个任务只会做一遍呢?

32、你觉得程序员除了提升技术能力之外,其他什么能力你比较看重?

  • 沟通能力
  • 学习能力
  • 希望能提高一下自己的管理协调能力

33、用过koa吗?简要阐述一下koa的洋葱模型。

Koa基于Node.js平台的下一代web开发框架

  • 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理
  • Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。

image.pngimage.png

在洋葱模型中,每一层相当于一个中间件,用来处理特定的功能。

Koa 的洋葱模型指的是以 next() 函数为分割点,先由外到内执行 Request 的逻辑,再由内到外执行 Response 的逻辑。通过洋葱模型,将多个中间件之间通信等变得更加可行和简单。其实现的原理并不是很复杂,主要是 compose 方法。

34、用过promise吗?它的使用是为了解决一个什么问题?promise底层是怎么设计的?

Promise 对象是一个可用于存储异步操作结果状态和数据的容器

  • promise 作用

    • promise主要要解决一个if else 回调地狱的问题。
    • promise可以直接多个并发请求,获取并发请求中的数据,可以解决异步的问题
    • 将业务逻辑与数据处理分隔开使代码更优雅,方便阅读,更有利于代码维护
  • promise 用法

    • 有三种状态:pending、fulfilled、rejected,只有异步操作的结果,可以决定当前是哪一种状态,任何操作都无法改变这个状态
    • 状态一旦改变就不会改变
    • 构造函数promise必须接收一个函数作为参数,函数包括resolve和reject
    • then、catch支持链式调用
  • promise 方法

    • Promise.all()
  • Promise.race()

  • Promise.resolve()

  • Promise.reject()

  • Promise.prototype.catch()

  • Promise.prototype.finally()

  • Promise.prototype.then()

  • promise 底层怎么设计的

image.png

/**
 * promise手写思路
 * @type {string}
 *
 * 以容器概念作为切入点,实现Promise对象的基本结构
 * 分析Promise容器和异步操作的关系,实现Promise的构造方法constructor
 * 理清Promise容器中数据的写入方式,实现Promise的resolve和reject方法
 * 理清Promise容器中数据的读取方式,实现Promise的then方法
 * 给then方法加个需求,支持链式调用,方便处理异步操作流
 */

const REJECTED = 'REJECTED';
const FULFILLED = 'FULFILLED';
const PENDING = 'PENDING';
class newPromise {
    constructor(executor) {
        /*先定义容器中需要用到的变量*/
        this.state = PENDING // promise的状态
        this.value = undefined //resolve下的返回值
        this.reason = undefined //reject下的返回值
        this.onResolvedTodoList = [] //resolve的存储数组
        this.onRejectedTodoList = [] //reject的存储数组
        const resolve = (value) => {}
        const reject = (reason) => {}
        try {
            //执行入参函数
            executor(resolve, reject);
        } catch(err) {
            reject(err);
        }
    }
    static all = () => {}
    static race = () => {}
    static finally = () => { }
    static catch = () => {}
    then = (onResolved, onRejected) => {
        return new Promise((resolve, reject) => {
            // 代码
        })
    }

}

END