虾皮测试面经整理
虾皮测试面经整理目录虾皮测试面经整理一、基础知识1、操作系统2、数据结构3、计算机网络4、数据库5、Linux6、Java二、测试基础三、算法题1、有效括号一、基础知识1、操作系统2、数据结构3、计算机网络(1)http 1.0 1.1 2.0的区别(2)TCP KeepAlive http keepalive4、数据库5、Linux6、Java二、测试基础三、算法题1、有效括号给定一个只包含三种
之前整理的了,给今年的同学一个参考吧!如果有出错的地方,欢迎大家指正!加油!
虾皮测试面经整理
目录
一、基础知识
1、操作系统
进程调度算法:
先来先服务、时间片轮转、最短作业优先、最短剩余时间优先、最高响应比优先、多级反馈队列调度算法
2、数据结构
3、计算机网络
(1)TCP怎么保证可靠传输
校验和、确认应答+序列号、超时重传、流量控制、拥塞控制
TCP四次挥手的TIME_WAIT
在第三次挥手的时候,服务端发FIN给客户端,然后客户端再发ACK命令给客户端,然后进入TIME_WAIT状态,2MSL之后,进入CLOSED状态,从客户端的角度来说,第四次挥手是为了告诉服务端,我收到了你的FIN信号,一切正常,等待2MSL是为了确保服务端收到了ACK,如果因为网络波动导致服务端没收到ACK,那么服务端会重传FIN信号。从服务端的角度老说,第四次挥手能确保客户端收到FIN信号。
- 为实现TCP全双工连接的可靠释放:如果客户端最后一次发送给服务端的ACK确认关闭报文段丢失,此时二者的连接并没有完全关闭,基于超时重传,服务端会再次向客户端发送一个Fin包请求断开连接,如果直接关闭的话,则后面会直接以RST包响应对方,这会被对方认为是有错误发生,导致连接关闭失败。
- 为使旧的数据包在网络因过期而消失:其实一个TCP连接可以用一个四元组唯一标识:(客户端IP,客户端port, 服务端IP, 服务端port),如果上次连接直接关闭,而第二次又以相同的四元组参数连接,数据接收方是分辨不出来这两次不同的;如果有旧数据到达接收端之前,旧连接已断开且一条由相同四元组构成的新TCP连接已建立,那么这条旧数据会和本次连接的新数据混到一起传输给应用层,造成异常。所以等待2个最长报文寿命段,保证此时没有新的连接建立,并且让原有数据包因超时而失效。
TCP、UDP的区别
- TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
- TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
- TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
- UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
- 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
- TCP首部开销20字节;UDP的首部开销小,只有8个字节
- TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
三次握手
- 第一次握手:建立连接时,客户端发送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连接成功)状态,完成三次握手。
四次挥手
- 挥手1: 当客户端已经没有要发送的数据了,决定释放连接,就会发送一个终止连接报文,主动关闭TCP连 接,其中终止控制位FIN=1,序号seq=u,u的值为之前客户端发送的后一个序号+1。此时客户端进入FIN-WAIT1(终止等待1)状态,等待B的确认。FIN报文段不携带数据也会消耗一个序号。
- 挥手2:服务端收到该报文后,发送给客户端一个确认报文,ACK=1,ack=u+1,seq=v,v的值为服务端之前发送的 后一个序号+1。此时客户端进入了FIN-WAIT-2(终止等待2)状态,服务端进入了CLOSE-WAIT(关闭等待)状 态,但连接并未完全释放,服务端会通知高层的应用层结束客户端到服务端这一方向的连接,此时TCP处于半关闭状 态,服务端能向客户端发送数据,但是客户端不能向服务端发送数据。
- 挥手3: 当服务端发送完数据后,准备释放连接时就向客户端发送连接终止报文,FIN=1,同时还要重发ACK=1, ack=u+1,seq=w(在半关闭状态B可能又发送了一些数据,所以要重复之前已经发送过的确认号 ack=u+1)。此时客户端进入LAST-ACK状态。
- 挥手4: 客户端收到连接终止报文后还要再进行一次确认,确认报文中ACK=1,ack=w+1,seq=u+1。发送 完之后进入TIME-WAIT(时间等待)状态,等时间等待计时器设置的时间2MSL(Maximum Segment Lifetime)之后进入CLOSED状态,服务端收到该确认后也进入CLOSED状态。
为什么连接的时候是三次握手,关闭的时候却是四次挥手
- 1. TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。即SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。
- 2. TCP释放连接时之所以需要“四次挥手”,是因为FIN释放连接报文与ACK确认接收报文是分别由第二次和第三次"握手"传输的。为何建立连接时一起传输,释放连接时却要分开传输?建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。
所以是“三次握手”,“四次挥手”
为什么不能用两次握手进行连接?
- 3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
- 现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
如果已经建立了连接,但是客户端突然出现故障了怎么办?
- TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
TCP拥塞控制算法
- 慢开始算法:发送方会维持一个拥塞窗口的变量;刚开始发送的发送,从2^0开始发送,每发送一个报文接收方都发送一个确认;一直往后以指数增长的方式发送报文,拥塞窗口也跟着变化,到达到其门限值的时候,停止使用慢开始算法,改用拥塞避免算法
- 拥塞避免算法:
- 加法增大:当拥塞窗口超过其门限值之后,采用加法增大的方式,每经过一个往返时间(从发送到收到确认包),让拥塞窗口值加1;其按照线性规律增长;
- 乘法减小:在拥塞窗口一直增大的过程中,当出现网络丢包的时候,停止使用加法增大,改而使用乘法减小;即将拥塞窗口的值减半作为新的门限的值,然后拥塞窗口从2^0开始,重新执行慢开始算法.
- 快重传算法:
- 有时,个别报文段会在网络中丢失,但实际上网络并未发生拥塞;
- 这将导致发送方超时重传,并误认为网络发生了拥塞;
- 发送方错误地启动慢开始算法,并把拥塞窗口设置为最小值1,因而降低了传输效率。
- 所谓的快重传算法是:使发送方尽快进行重传,而不是等待超时重传计时器超时再重传。
- 要求接收方不要等待自己发送数据时才进行稍待确认,而是要立即发送确认;
- 快恢复算法:
TCP长短连接,优缺点
所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接。
短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接,即每次TCP连接只完成一对 CMPP消息的发送。
现阶段,要求ISMG之间必须采用长连接的通信方式,建议SP与ISMG之间采用长连接的通信方式。
应用场景:
数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。
WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的 连接用短连接会更省一些资源,如果用长连接,而且同时有
千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频 繁操作情况下需用短连好。
长连接、短连接的优缺点:
长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户端适合使用长连接。在长连接的应用场景下,client端一般不会主动关闭连接,当client与server之间的连接一直不关闭,随着客户端连接越来越多,server会保持过多连接。这时候server端需要采取一些策略,如关闭一些长时间没有请求发生的连接,这样可以避免一些恶意连接导致server端服务受损;如果条件允许则可以限制每个客户端的最大长连接数,这样可以完全避免恶意的客户端拖垮整体后端服务。
短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。但如果客户请求频繁,将在TCP的建立和关闭操作上浪费较多时间和带宽。
cookie 和 session的区别
什么是cookie?什么是session?
- cookie位于用户的计算机上,用来维护用户计算机中的信息,直到用户删除。比如我们在网页上登录某个软件时输入用户名及密码时如果保存为cookie,则每次我们访问的时候就不需要登录网站了。我们可以在浏览器上保存任何文本,而且我们还可以随时随地的去阻止它或者删除。我们同样也可以禁用或者编辑cookie,但是有一点需要注意不要使用cookie来存储一些隐私数据,以防隐私泄露
- session称为会话信息,位于web服务器上,主要负责访问者与网站之间的交互,当访问浏览器请求http地址时,将传递到web服务器上并与访问信息进行匹配, 当关闭网站时就表示会话已经结束,网站无法访问该信息了,所以它无法保存永久数据,我们无法访问以及禁用网站
区别:
- 数据存放位置不同:cookie数据存放在客户的浏du览器上,session数据放zhi在服务器上。
- 安全程度不同:cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
- 性能使用程度不同:session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
- 数据存储大小不同:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制
- 会话机制不一样:
- session会话机制:session会话机制是一种服务器端机制,它使用类似于哈希表(可能还有哈希表)的结构来保存信息。
- cookies会话机制:cookie是服务器存储在本地计算机上的小块文本,并随每个请求发送到同一服务器。 Web服务器使用HTTP标头将cookie发送到客户端。在客户端终端,浏览器解析cookie并将其保存为本地文件,该文件自动将来自同一服务器的任何请求绑定到这些cookie。
HTTP和HTTPS的区别:
- http和https的区别:
- HTTPS 协议需要到 CA (Certificate Authority,证书颁发机构)申请证书,一般免费证书较少,因而需要一定费用。(以前网易官网是http,而网易邮箱是 https 。)
- HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。
- HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- HTTP 的连接很简单,是无状态的。HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。(无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。)
HTTP无状态、无连接是指什么
HTTP协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和上一次打开这个服务器上的网页之间没有任何联系。HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。
无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。为请求时建连接、请求完释放连接,以尽快将资源释放出来服务其他客户端,可以加KeepAlive弥补无连接的问题
无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。即我们给服务器发送 HTTP 请求之后,服务器根据请求,会给我们发送数据过来,但是,发送完,不会记录任何信息。 可以通过Cookie和Session来弥补这个问题。
HTTP的请求方式
HTTP 1.0包括三种请求方法,分别是:
(1)GET:请求指定的页面信息,并返回实体主体。
(2)HEAD:类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
(3)POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
HTTP 1.1中新增了五种请求方法:
(1)OPTIONS: 允许客户端查看服务器的性能;
(2)PUT: 从客户端向服务器传送的数据取代指定的文档的内容;
(3)DELETE:请求服务器删除指定的页面;
(4)TRACE:回显服务器收到的请求,主要用于测试或诊断;
(5)CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
get和post的区别:
- GET提交的数据会放在URL之后。POST放在Body中。
- GET提交的数据大小是有限制的(URL长度有限制)。POST没有限制。
- GET方式提交数据会带来安全问题,比如用户名和密码出现在URL中。页面被缓存或其他人访问这台机器,可从历史记录中获得该用户的账号和密码。
HTTP的长连接和短连接
在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。
而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
HTTP1.0 HTTP1.1 HTTP2.0的区别
1991年 HTTP/0.9 仅支持GET请求,不支持请求头
1996年 HTTP/1.0 默认短连接(一次请求建议一次TCP连接,请求完就断开),支持GET、POST、 HEAD请求
1999年 HTTP/1.1 默认长连接(一次TCP连接可以多次请求);支持PUT、DELETE等五种请求
增加host头,支持虚拟主机;支持断点续传功能
2015年 HTTP/2.0 多路复用,降低开销(一次TCP连接可以处理多个请求);
服务器主动推送(相关资源一个请求全部推送);
解析基于二进制,解析错误少,更高效(HTTP/1.X解析基于文本);
报头压缩,降低开销。
HTTP 0.9 :
(1)、只接受GET一种请求方法,没有在通信中指定版本号,且不支持请求头;
(2)、此外该版本也不支持POST方法,因此客户端无法向服务器传递太多信息;
HTTP 1.0:(1)、支持POST、GET、HEAD三种方法;
(2)、规定浏览器与服务器之间只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求;
HTTP 1.1:(1)、新增了五种请求方法:PUT、DELETE、CONNECT、TRACE、OPTIONS;
(2)、HTTP 1.1 在Request消息头里头多了一个Host域,便于一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点;
(3)、在HTTP/1.1中新增了24个状态响应码:
100-199 用于指定客户端应相应的某些动作。
200-299 用于表示请求成功。
300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。
400-499 用于指出客户端的错误。
500-599 用于支持服务器错误。
SSL建立连接的过程:
- SSL建立连接的过程(用对称加密的方式加密传输的信息,因为对称加密效率更快;用非对称加密的方式加密传输的密钥,因为更加安全)
- 客户端向服务端发起连接,将自己所支持的加密套件发送给服务器端。
- 服务器端收到后选择一个自己所支持的加密算法和HASH算法,同时将证书也一并发送给客户端(证书中包含公钥)
- 客户端收到证书后验证证书的合法性,如果是合法的,则生成对称密钥并且用证书的公钥加密后发送给服务端。[生成的对称密钥用于后面信息的传输加密,用公钥加密生成的对称密钥的内容然后传输实则是用非对称加密的方式传输密钥内容的过程]
- 服务端收到后用私钥解密,取出对称加密的密钥。至此握手完成,后续开始传送密文了
SSL握手流程为什么要使用非对称秘钥?
HTTPS请求过程:(一次HTTPS请求要进行两次HTTP传输)
1.客户端发出https请求,请求服务端建立SSL连接;
2.服务端收到https请求,申请或自制数字证书,得到公钥和服务端私钥,并将公钥发送给客户端;
3.客户端验证公钥,不通过验证则发出警告,通过验证则产生一个随机的客户端私钥;
4.客户端将公钥与客户端私钥进行对称加密后传给服务端;
5.服务端收到加密内容后,通过服务端私钥进行非对称解密,得到客户端私钥;
6.服务端将客户端私钥和内容进行对称加密,并将加密内容发送给客户端;
7.客户端收到加密内容后,通过客户端私钥进行对称解密,得到内容。
双向认证 SSL 协议的具体过程
① 浏览器发送一个连接请求给安全服务器。
② 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。
③ 客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA 中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。
④ 接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。
⑤ 服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。
⑥ 客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。
⑦ 服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。
⑧ 浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。
⑨ 服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。
⑩ 服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。
HTTP请求和响应格式:
HTTP请求由三部分组成,分别是:
(1)请求行:
(2)消息报头;
(3)请求正文。HTTP响应由四部分组成,分别是:
(1)状态行;
(2)消息报头;
(3)空行;
(4)响应正文;
HTTP常见的头部:
Request Header:
- GET /sample.Jsp HTTP/1.1 //请求行
Host: www.uuid.online/ //请求的目标域名和端口号
- Origin: http://localhost:8081/ //请求的来源域名和端口号 (跨域请求时,浏览器会自动带上这个头信息)
Referer: https:/localhost:8081/link?query=xxxxx //请求资源的完整URI
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36 //浏览器信息
Cookie: BAIDUID=FA89F036:FG=1; BD_HOME=1; sugstore=0 //当前域名下的Cookie
Accept: text/html,image/apng //代表客户端希望接受的数据类型是html或者是png图片类型
Accept-Encoding: gzip, deflate //代表客户端能支持gzip和deflate格式的压缩
Accept-Language: zh-CN,zh;q=0.9 //代表客户端可以支持语言zh-CN或者zh(值得一提的是q(0~1)是优先级权重的意思,不写默认为1,这里zh-CN是1,zh是0.9)
Connection: keep-alive //告诉服务器,客户端需要的tcp连接是一个长连接
Response Header:
- HTTP/1.1 200 OK // 响应状态行
- Date: Mon, 30 Jul 2018 02:50:55 GMT //服务端发送资源时的服务器时间
- Expires: Wed, 31 Dec 1969 23:59:59 GMT //比较过时的一种验证缓存的方式,与浏览器(客户端)的时间比较,超过这个时间就不用缓存(不和服务器进行验证),适合版本比较稳定的网页
- Cache-Control: no-cache // 现在最多使用的控制缓存的方式,会和服务器进行缓存验证,具体见博文”Cache-Control“
etag: "fb8ba2f80b1d324bb997cbe188f28187-ssl-df" // 一般是Nginx静态服务器发来的静态文件签名,浏览在没有“Disabled cache”情况下,接收到etag后,同一个url第二次请求就会自动带上“If-None-Match”
- Last-Modified: Fri, 27 Jul 2018 11:04:55 GMT //是服务器发来的当前资源最后一次修改的时间,下次请求时,如果服务器上当前资源的修改时间大于这个时间,就返回新的资源内容
- Content-Type: text/html; charset=utf-8 //如果返回是流式的数据,我们就必须告诉浏览器这个头,不然浏览器会下载这个页面,同时告诉浏览器是utf8编码,否则可能出现乱码
- Content-Encoding: gzip //告诉客户端,应该采用gzip对资源进行解码
- Connection: keep-alive //告诉客户端服务器的tcp连接也是一个长连接
HTTP常用头部中的cache-control
Cache-Control字段是http报文中的通用首部字段,既存在于请求报文中,也存在于响应报文中。部分字段值是共有的,但是具体的处理也会有差异。
网页的缓存是由HTTP消息头中的“Cache-control”来控制的
在Cache-Control 中,这些值可以自由组合,多个值如果冲突时,也是有优先级的,而no-store优先级最高。
max-age:(只接受 Age 值小于 max-age 值,并且没有过期的对象)
max-stale:(可以接受过去的对象,但是过期时间必须小于 max-stale 值)
min-fresh:(接受其新鲜生命期大于其当前 Age 跟 min-fresh 值之和的缓存对象)
响应:public(可以用 Cached 内容回应任何用户)
private(只能用缓存内容回应先前请求该内容的那个用户)
no-cache(可以缓存,但是只有在跟WEB服务器验证了其有效后,才能返回给客户端)
max-age:(本响应包含的对象的过期时间)
ALL: no-store(不允许缓存)默认为private。其作用根据不同的重新浏览方式分为以下几种情况:
(1) 打开新窗口
如果指定cache-control的值为private、no-cache、must-revalidate,那么打开新窗口访问时都会重新访问服务器。而如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器,例如:
Cache-control: max-age=5
表示当访问此网页后的5秒内再次访问不会去服务器
(2) 在地址栏回车
如果值为private或must-revalidate(和网上说的不一样),则只有第一次访问时会访问服务器,以后就不再访问。如果值为no-cache,那么每次都会访问。如果值为max-age,则在过期之前不会重复访问。
(3) 按后退按扭
如果值为private、must-revalidate、max-age,则不会重访问,而如果为no-cache,则每次都重复访问
(4) 按刷新按扭
无论为何值,都会重复访问
HTTP的缓存:缓存控制和缓存校验
缓存控制:控制缓存的开关,用于标识请求或访问中是否开启了缓存,使用了哪种缓存方式。
缓存校验:如何校验缓存,比如怎么定义缓存的有效期,怎么确保缓存是最新的。
- 缓存开关是: pragma, cache-control。
- 缓存校验有:Expires,Last-Modified,etag。
缓存控制:
Pragma
Pragma有两个字段Pragma和Expires。Pragma的值为no-cache时,表示禁用缓存,Expires的值是一个GMT时间,表示该缓存的有效时间。
Pragma是旧产物,已经逐步抛弃,有些网站为了向下兼容还保留了这两个字段。如果一个报文中同时出现Pragma和Cache-Control时,以Pragma为准。同时出现Cache-Control和Expires时,以Cache-Control为准。即优先级从高到低是 Pragma -> Cache-Control -> Expires
缓存校验:
在缓存中,我们需要一个机制来验证缓存是否有效。比如服务器的资源更新了,客户端需要及时刷新缓存;又或者客户端的资源过了有效期,但服务器上的资源还是旧的,此时并不需要重新发送。缓存校验就是用来解决这些问题的,在http 1.1 中,我们主要关注下Last-Modified 和 etag 这两个字段。
Last-Modified
服务端在返回资源时,会将该资源的最后更改时间通过Last-Modified字段返回给客户端。客户端下次请求时通过If-Modified-Since或者If-Unmodified-Since带上Last-Modified,服务端检查该时间是否与服务器的最后修改时间一致:如果一致,则返回304状态码,不返回资源;如果不一致则返回200和修改后的资源,并带上新的时间。
If-Modified-Since和If-Unmodified-Since的区别是:
If-Modified-Since:告诉服务器如果时间一致,返回状态码304
If-Unmodified-Since:告诉服务器如果时间不一致,返回状态码412etag
单纯的以修改时间来判断还是有缺陷,比如文件的最后修改时间变了,但内容没变。对于这样的情况,我们可以使用etag来处理。
etag的方式是这样:服务器通过某个算法对资源进行计算,取得一串值(类似于文件的md5值),之后将该值通过etag返回给客户端,客户端下次请求时通过If-None-Match或If-Match带上该值,服务器对该值进行对比校验:如果一致则不要返回资源。
If-None-Match和If-Match的区别是:
If-None-Match:告诉服务器如果一致,返回状态码304,不一致则返回资源
If-Match:告诉服务器如果不一致,返回状态码412
DNS 查询服务器的基本流程是什么(DNS解析过程)?DNS 劫持是什么?
DNS劫持是在域名解析成IP地址时,被解析成错误的IP地址
HTTP劫持是DNS解析的域名的IP地址不变。在和网站交互过程中的劫持了你的请求。在网站发给你信息前就给你返回了请求。
HTTP的状态码
TCP 的 keepalive 了解吗?说一说它和 HTTP 的 keep-alive 的区别?
HTTP中是keep-alive,TCP中是keepalive,HTTP中是带中划线的。大小写无所谓。
http keep-alive与tcp keepalive,不是同一回事,意图不一样。http keep-alive是为了让tcp活得更久一点,以便在同一个连接上传送多个http,提高socket的效率。而tcp keepalive是TCP的一种检测TCP连接状况的保鲜机制。
每个http请求都要求打开一个tpc socket连接,并且使用一次之后就断开这个tcp连接。
使用keep-alive可以改善这种状态,即在一次TCP连接中可以持续发送多份数据而不会断开连接。通过使用keep-alive机制,可以减少tcp连接建立次数,也意味着可以减少TIME_WAIT状态连接,以此提高性能和提高httpd服务器的吞吐率。keepalive是TCP保鲜定时器,当网络两端建立了TCP连接之后,闲置idle(双方没有任何数据流发送往来)了tcp_keepalive_time后,服务器内核就会尝试向客户端发送侦测包,来判断TCP连接状况(有可能客户端崩溃、强制关闭了应用、主机不可达等等)。如果没有收到对方的回答(ack包),则会在 tcp_keepalive_intvl后再次尝试发送侦测包,直到收到对对方的ack,如果一直没有收到对方的ack,一共会尝试 tcp_keepalive_probes次,每次的间隔时间在这里分别是15s, 30s, 45s, 60s, 75s。如果尝试tcp_keepalive_probes,依然没有收到对方的ack包,则会丢弃该TCP连接。TCP连接默认闲置时间是2小时,一般设置为30分钟足够了。
总结:
1、TCP连接往往就是我们广义理解上的长连接,因为它具备双端连续收发报文的能力;开启了keep-alive的HTTP连接,也是一种长连接,但是它由于协议本身的限制,服务端无法主动发起应用报文。
2、TCP中的keepalive是用来保鲜、保活的;HTTP中的keep-alive机制主要为了让支撑它的TCP连接活的的更久,所以通常又叫做:HTTP persistent connection(持久连接) 和 HTTP connection reuse(连接重用)。
从输入 URL 到展现页面的全过程
- 第一步:浏览器输入域名
- 例如输入:csdn.net/
- 第二步:浏览器查找域名的IP地址,浏览器会把输入的域名解析成对应的IP,其过程如下:
- 查找浏览器缓存:因为浏览器一般会缓存DNS记录一段时间,不同浏览器的时间可能不一样,一般2-30分钟不等,浏览器去查找这些缓存,如果有缓存,直接返回IP,否则下一步。
- 查找系统缓存:浏览器缓存中找不到IP之后,浏览器会进行系统调用(windows中是gethostbyname),查找本机的hosts文件,如果找到,直接返回IP,否则下一步。
- 查找路由器缓存:如果1,2步都查询无果,则需要借助网络,路由器一般都有自己的DNS缓存,将前面的请求发给路由器,查找ISP 服务商缓存 DNS的服务器,如果查找到IP则直接返回,没有的话继续查找。
- 递归查询:如果以上步骤还找不到,则ISP的DNS服务器就会进行递归查询,所谓递归查询就是如果主机所询问的本地域名服务器不知道被查询域名的IP地址,那么本地域名服务器就以DNS客户的身份,向其他根域名服务器继续发出查询请求报文,而不是让该主机自己进行下一步查询。(本地域名服务器地址是通过DHPC协议获取地址,DHPC是负责分配IP地址的)
- 迭代查询:本地域名服务器采用迭代查询,它先向一个根域名服务器查询。本地域名服务器向根域名服务器的查询一般都是采用迭代查询。所谓迭代查询就是当根域名服务器收到本地域名服务器发出的查询请求报文后,要么告诉本地域名服务器下一步应该查询哪一个域名服务器,然后本地域名服务器自己进行后续的查询。(而不是替代本地域名服务器进行后续查询)。
- 本例子中:根域名服务器告诉本地域名服务器,下一次应查询的顶级域名服务器net的IP地址。本地域名服务器向顶级域名服务器dns.net进行查询。顶级域名服务器dns.net告诉本地域名服务器,下一次应查询的权限域名服务器dns.csdn.net的IP地址。本地域名服务器向权限域名服务器dns.csdn.net进行查询。权限域名服务器dns.csdn.net告诉本地域名服务器,所查询的主机www.csdn.net的IP地址。本地域名服务器最后把结果告诉主机。
- 第三步:浏览器与目标服务器建立TCP连接
- 主机浏览器通过DNS解析得到了目标服务器的IP地址后,与服务器建立TCP连接。
- TCP3次握手连接:浏览器所在的客户机向服务器发出连接请求报文(SYN标志为1);服务器接收报文后,同意建立连接,向客户机发出确认报文(SYN,ACK标志位均为1);客户机接收到确认报文后,再次向服务器发出报文,确认已接收到确认报文;此处客户机与服务器之间的TCP连接建立完成,开始通信。
- 第四步:浏览器通过http协议发送请求
- 浏览器向主机发起一个HTTP-GET方法报文请求。请求中包含访问的URL,也就是http://www.csdn.com/ ,KeepAlive,长连接,还有User-Agent用户浏览器操作系统信息,编码等。值得一提的是Accep-Encoding和Cookies项。Accept-Encoding一般采用gzip,压缩之后传输html文件。Cookies如果是首次访问,会提示服务器建立用户缓存信息,如果不是,可以利用Cookies对应键值,找到相应缓存,缓存里面存放着用户名,密码和一些用户设置项。
- 第五步:某些服务会做永久重定向响应
- 对于大型网站存在多个主机站点,了负载均衡或者导入流量,提高SEO排名,往往不会直接返回请求页面,而是重定向。返回的状态码就不是200OK,而是301,302以3开头的重定向码,浏览器在获取了重定向响应后,在响应报文中Location项找到重定向地址,浏览器重新第一步访问即可。
- 重定向的作用:重定向是为了负载均衡或者导入流量,提高SEO排名。利用一个前端服务器接受请求,然后负载到不同的主机上,可以大大提高站点的业务并发处理能力;重定向也可将多个域名的访问,集中到一个站点;由于com,www.baidu.com会被搜索引擎认为是两个网站,照成每个的链接数都会减少从而降低排名,永久重定向会将两个地址关联起来,搜索引擎会认为是同一个网站,从而提高排名。
- 第六步:浏览器跟踪重定向地址
- 当浏览器知道了重定向后最终的访问地址之后,重新发送一个http请求,发送内容同上。
- 第七步:服务器处理请求
- 服务器接收到获取请求,然后处理并返回一个响应。
- 第八步:服务器发出一个HTML响应
- 返回状态码200 OK,表示服务器可以响应请求,返回报文,由于在报头中Content-type为“text/html”,浏览器以HTML形式呈现,而不是下载文件。
- 第九步:释放TCP连接
- 浏览器所在主机向服务器发出连接释放报文,然后停止发送数据;
- 服务器接收到释放报文后发出确认报文,然后将服务器上未传送完的数据发送完;
- 服务器数据传输完毕后,向客户机发送连接释放报文;
- 客户机接收到报文后,发出确认,然后等待一段时间后,释放TCP连接;
- 第十步:浏览器显示页面
- 在浏览器没有完整接受全部HTML文档时,它就已经开始显示这个页面了,浏览器接收到返回的数据包,根据浏览器的渲染机制对相应的数据进行渲染。渲染后的数据,进行相应的页面呈现和脚步的交互。
- 第十一步:浏览器发送获取嵌入在HTML中的其他内容
- 比如一些样式文件,图片url,js文件url等,浏览器会通过这些url重新发送请求,请求过程依然是HTML读取类似的过程,查询域名,发送请求,重定向等。不过这些静态文件是可以缓存到浏览器中的,有时访问这些文件不需要通过服务器,直接从缓存中取。某些网站也会使用第三方CDN进行托管这些静态文件。
简述 JWT 的原理和校验机制
简述什么是 XSS 攻击以及 CSRF 攻击?
XSS(Cross Site Script,跨站脚本攻击)是向网页中注入恶意脚本在用户浏览网页时在用户浏览器中执行恶意脚本的攻击方式。
跨站脚本攻击分有两种形式:反射型攻击(诱使用户点击一个嵌入恶意脚本的链接以达到攻击的目标,目前有很多攻击者利用论坛、微博发布含有恶意脚本的URL就属于这种方式)和持久型攻击(将恶意脚本提交到被攻击网站的数据库中,用户浏览网页时,恶意脚本从数据库中被加载到页面执行,QQ邮箱的早期版本就曾经被利用作为持久型跨站脚本攻击的平台)。
解决方法:消毒(对危险字符进行转义)和HttpOnly(防范XSS攻击者窃取Cookie数据)。
CSRF攻击(Cross Site Request Forgery,跨站请求伪造)是攻击者通过跨站请求,以合法的用户身份进行非法操作(如转账或发帖等)。
CSRF的原理是利用浏览器的Cookie或服务器的Session,盗取用户身份。
解决方法:(1)在表单中添加令牌(token);(2)验证码;(3)检查请求头中的Referer(前面提到防图片盗链接也是用的这种方式)。
SQL注入:当服务器使用请求参数构造SQL语句时,恶意的SQL被嵌入到SQL中交给数据库执行。
防范SQL注入攻击也可以采用消毒的方式,通过正则表达式对请求参数进行验证,此外,参数绑定也是很好的手段,这样恶意的SQL会被当做SQL的参数而不是命令被执行,
(2)OSI七层模型、TCP/IP五层、四层模型
OSI七层模型 | 描述 | 数据格式 | 协议 | TCP/IP五层模型 | 设备 | TCP/IP四层模型 | 协议 | 描述 |
---|---|---|---|---|---|---|---|---|
应用层 | 为应用程序提供服务 | HTTP、FTP、TFTP、Telnet、DNS、SMTP | 应用层 | 应用层 | DNS、HTTP、WWW、FTP、TFTP、SMTP、Telnet、Usenet | |||
表示层 | 数据格式转化、数据加密 | JPEG、ASCII、GIF | ||||||
会话层 | 建立、管理和维护会话 | SQL | ||||||
传输层 | 建立、管理和维护端到端的连接 | 数据段 | TCP、UDP | 传输层 | 四层的路由器、四层交换机 | 传输层 | TCP、UDP | 提供端到端的通信 |
网络层 | IP选址及路由选择 | 数据包 | IP、ICMP、RIP、IGMP | 网络层 | 路由器、三层交换机 | 网间层 | ICMP、IP、RIP | 负责数据的包装、寻址和路由 |
数据链路层 | 提供介质访问和链路管理 | 以太网帧 | ARP、RARP、PPP、CSMA/CD、IEEE802.3 | 数据链路层 | 网桥、以太网交换机、网卡 | 网络接口层 | ARP、RARP | 包括用于协作IP数据在已有网络介质上传输的协议 |
物理层 | 物理层 | 比特流 | EIA/TIA-232 | 物理层 | 中继器、集线器、双绞线 |
OSI分层模型的优点:
4、数据库
事务隔离级别:
隔离级别 脏读(Dirty Read) 不可重复读 幻读(Phantom Read) 未提交读(Read uncommitted) 可能 可能 可能 已提交读(Read committed) 不可能 可能 可能 可重复读(Repeatable read) 不可能 不可能 可能 可串行化(Serializable ) 不可能 不可能 不可能 01:Mysql的默认隔离级别是:可重复读:Repeatable read;
02:oracle数据库中,只支持seralizable(串行化)级别和Read committed();默认的是Read committed级别;
MyISAM和InnoDB差别:
MyISAM不支持事务,InnoDB支持。MyISAM不支持行锁,只支持表锁,InnoDB支持行锁。
InnoDB没有保存具体的行数,所以在统计行数的时候回扫描全表,MyISAM有保存。
myisam的索引以表名+.MYI文件分别保存。innodb的索引和数据一起保存在表空间里。
Innodb引擎
Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别,关于数据库事务与其隔离级别的内容请见数据库事务与其隔离级别这篇文章。该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL后台的完整数据库系统,MySQL运行时Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎不支持FULLTEXT类型的索引,而且它没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用Innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。
MyIASM引擎
MyIASM是MySQL默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。不过和Innodb不同,MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。
主从复制:
主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;主数据库一般是准实时的业务数据库。
好处:
1、架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,物理服务器增加,负荷增加。
2、读写分离,使数据库能支撑更大的并发。主从只负责各自的写和读,极大程度的缓解X锁和S锁争用。在报表中尤其重要。由于部分报表sql语句非常的慢,导致锁表,影响前台服务。如果前台使用master,报表使用slave,那么报表sql将不会造成前台锁,保证了前台速度。
3、做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
原理:
1.数据库有个bin-log二进制文件,记录了所有sql语句。
2.我们的目标就是把主数据库的bin-log文件的sql语句复制过来。
3.让其在从数据的relay-log重做日志文件中再执行一次这些sql语句即可。
4.下面的主从配置就是围绕这个原理配置
5.具体需要三个线程来操作:
1.binlog输出线程:每当有从库连接到主库的时候,主库都会创建一个线程然后发送binlog内容到从库。
在从库里,当复制开始的时候,从库就会创建两个线程进行处理:
2.从库I/O线程:当START SLAVE语句在从库开始执行之后,从库创建一个I/O线程,该线程连接到主库并请求主库发送binlog里面的更新记录到从库上。从库I/O线程读取主库的binlog输出线程发送的更新并拷贝这些更新到本地文件,其中包括relay log文件。
3.从库的SQL线程:从库创建一个SQL线程,这个线程读取从库I/O线程写到relay log的更新事件并执行。
可以知道,对于每一个主从复制的连接,都有三个线程。拥有多个从库的主库为每一个连接到主库的从库创建一个binlog输出线程,每一个从库都有它自己的I/O线程和SQL线程。
乐观锁、悲观锁
乐观锁是指操作数据库时(更新操作),想法很乐观,认为这次的操作不会导致冲突,在操作数据时,并不进行任何其他的特殊处理(也就是不加锁),而在进行更新后,再去判断是否有冲突了。
常用的方法是加version字段,更新时比较第一次的version值和当前的值是否相同,相同则更新,不同则说明数据过期。
悲观锁:悲观锁就是在操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时都要通过获取锁才能进行对相同数据的操作,这点跟java中的synchronized很相似,所以悲观锁需要耗费较多的时间。另外与乐观锁相对应的,悲观锁是由数据库自己实现了的,要用的时候,我们直接调用数据库的相关语句就可以了。
事务四大特性(ACID):
一致性、原子性、隔离性、持久性
进程和线程区别
进程是资源分配最小单位,线程是程序执行的最小单位;
进程有自己独立的地址空间,每启动一个进程,系统都会为其分配地址空间,建立数据表来维护代码段、堆栈段和数据段,线程没有独立的地址空间,它使用相同的地址空间共享数据;
CPU切换一个线程比切换进程花费小;
创建一个线程比进程开销小;
线程占用的资源要⽐进程少很多。
5、Linux
杀死进程kill
在Linux/unix下,中止一个Java进程有两种方式,一种是kill -9 pid,一种是kill -15 pill(默认)。
SIGNKILL(9) 的效果是立即杀死进程. 该信号不能被阻塞, 处理和忽略。
SIGNTERM(15) 的效果是正常退出进程,退出前可以被阻塞或回调处理。并且它是Linux缺省的程序中断信号(默认是15)。
6、Java
二、测试基础
三、算法题
1、有效括号
给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
- 任何左括号 ( 必须有相应的右括号 )。
- 任何右括号 ) 必须有相应的左括号 ( 。
- 左括号 ( 必须在对应的右括号之前 )。
- * 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
- 一个空字符串也被视为有效字符串。
import java.util.*;
public class Solution {
/**
*
* @param s string字符串
* @return bool布尔型
*/
public boolean checkValidString (String s) {
// write code here
if (s.length() == 0 || s == null)
return true;
int left = 0;
int right = 0;
for (int i = 0; i < s.length(); i++){
left += (s.charAt(i) == ')' ? -1 : 1);
right += (s.charAt(s.length()-1-i) == '(' ? -1 : 1);
if (left < 0 || right < 0)
return false;
}
return true;
}
}
2、约瑟夫环问题
https://blog.csdn.net/github_38571976/article/details/107958784?spm=1001.2014.3001.5502
更多推荐
所有评论(0)