1. 谈谈你对七层网络协议体系架构的理解
学习计算机网络时我们一般采用折中的办法,也就是中和 OSI(OpenSystem Interconnection Model)参考模型 和 TCP/IP 模型的优点,采用一种只有五层协议的体系结构,这样既简洁又能将概念阐述清楚。在实际生产中实现的网络协议是四层 TCP/IP 体系。
应用层
应用层的任务是通过应用进程间的交互来完成特定网络应用。应用层协议定义的是应用进程(进程:主机中正在运行的程序)间的通信和交互的规则。对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如域名系统 DNS,支持万维网应用的 HTTP 协议,支持电子邮件的 SMTP 协议等等。我们把应用层交互的数据单元称为报文。
传输层
传输层的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务。应用进程利用该服务传送应用层报文。“通用的”是指并不针对某一个特定的网络应用,而是多种应用可以使用同一个运输层服务。
网络层
在计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP / IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报,简称数据报。
数据链路层
两台主机之间的数据传输,总是在一段一段的链路上传送的,这就需要使用专门的链路层的协议。在两个相邻节点之间传送数据时,数据链路层将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如:同步信息,地址信息,差错控制等)。
在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。这样,数据链路层在收到一个帧后,就可从中提出数据部分,上交给网络层。控制信息还使接收端能够检测到所收到的帧中有无差错。如果发现差错,数据链路层就简单地丢弃这个出了差错的帧,以避免继续在网络中传送下去白白浪费网络资源。如果需要改正数据在链路层传输时出现差错(这就是说,数据链路层不仅要检错,而且还要纠错),那么就要采用可靠性传输协议来纠正出现的差错。这种方法会使链路层的协议复杂些。
物理层
在物理层上所传送的数据单位是比特。物理层的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。使其上面的数据链路层不必考虑网络的具体传输介质是什么。
2. 每一层对应的网络协议有哪些?
3. ARP 协议的工作原理?
网络层的 ARP(Address Resolution Protocol)协议完成了 IP 地址与物理地址的映射。首先,每台主机都会在自己的 ARP 缓冲区中建立一个 ARP 列表,以表示 IP 地址和 MAC 地址的对应关系。当源主机需要将一个数据包要发送到目的主机时,会首先检查自己 ARP 列表中是否存在该 IP 地址对应的 MAC 地址:如果有,就直接将数据包发送到这个 MAC 地址;如果没有,就向本地网段发起一个 ARP 请求的广播包,查询此目的主机对应的 MAC 地址。
4. 在浏览器上输入 url 地址后会发生什么?
总体来说分为以下几个过程:
- DNS 解析:浏览器查询 DNS,获取域名对应的 IP 地址。
- TCP 连接:浏览器获得对应域名的 IP 地址后,浏览器向服务器请求建立连接,发起三次握手。
- 发送 HTTP 请求:TCP 连接之后,浏览器向服务器发送 HTTP 请求。
- 服务器处理请求并返回 HTTP 报文:服务器接收到这个请求,并根据路径参数映射到特定的请求处理器进行处理,并将处理结果及相应的 HTTP 报文返回给浏览器。
- 浏览器解析渲染页面:浏览器解析并渲染视图,若遇到对 js 文件、css 文件及图片等静态资源的引用,则重复以上步骤向服务器请求静态资源。浏览器根据其请求到的资源、数据渲染页面,最终向用户呈现一个完整的页面。
- 连接结束。
5. URI 和 URL 的区别
- URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。
- URL(Uniform Resource Location) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI,即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。
URI的作用像身份证号一样,URL的作用更像家庭住址一样。URL是一种具体的URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。
6. Forward 和 Redirect 的区别?
Forward 和 Redirect 代表了两种请求转发方式:直接转发和间接转发。
直接转发方式(Forward):客户端和浏览器只发出一次请求,Servlet、HTML、JSP 或其它信息资源,由第二个信息资源响应该请求,在请求对象 request 中,保存的对象对于每个信息资源是共享的。
间接转发方式(Redirect):实际是两次 HTTP 请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个 URL 发出请求,从而达到转发的目的。
举个通俗的例子,直接转发就相当于:“A 找 B 借钱,B 说没有,B 去找 C 借,借到借不到都会把消息传递给 A”;间接转发就相当于:”A 找 B 借钱,B 说没有,让 A 去找 C 借”。
7. 当在局域网中使用ping www.xxx.com时,用到了哪些协议?
- 使用 DNS 协议,将 ping 后接的域名转换为 IP 地址。(DNS使用的传输层协议是UDP)
- 使用 ARP 协议,由 IP 地址解析出 MAC 地址,以在数据链路层传输。
- ping 是为了测试另一台主机是否可达,发送一份 ICMP 回显请求给目标主机,并等待 ICMP 回显应答。(ICMP 用于在 IP 主机、路由器间传递网络是否通畅、主机是否可达等控制信息)
8. Cookie 和 Session 的区别?
Cookie 和 Session 都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
- Cookie 一般用来保存用户信息。比如登录网站时可以直接进入,不用重新登录。
- Session 的主要作用就是通过服务端记录用户的状态。 典型的场景是购物车,服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。
Cookie 存储在客户端中,而Session存储在服务器上,相对来说 Session 安全性更高。如果要在 Cookie 中存储一些敏感信息,不要直接写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。
9. 从演进的角度讲讲 Cookie、Session 和 Token?
Cookie 的诞生
1990 年,HTTP 协议诞生,当时的需求只有 GET,拿完了连接就可以断了,也不需要什么交互,所以 HTTP 起初的设计就是无状态的,也就是请求和请求之间是没有关联的。
之后随着互联网的发展,交互开始兴起,服务器需要判断每个请求的发起者是谁,也就是需要状态。这时就需要一种技术让请求与请求之间建立起联系,让请求变得有状态。这个技术就叫做 Cookie,就是一个以 Key-Value 格式存储的小文件,保存在客户端本地。比如登录之后,服务器就能设置 Cookie 返回给浏览器,然后保存在本地。把一些用户信息存到 Cookie 中,服务器就能判别是哪个用户的请求了。
Session 的诞生
Cookie 存在两个问题:
- Cookie 将用户信息明文存储在用户本地,安全性得不到保障。
- 每次请求携带大量的 Cookie 信息,对带宽来说不太合算。
于是 Session 出现解决了这个问题,Session 就是将用户的会话信息存储在服务端,它颁发一个 sessionId 给客户端,让客户端之后带着 sessionId 来请求,这样服务端就可以通过 sessionId 找到这个用户的信息,从而识别请求。这个 sessionId 是按照 Cookie 的形式存在用户本地,发起请求的时候带上即可。
但是这又带来一个问题,这样做相当于把状态信息存储到服务器中,就使得服务器有状态了,而对于大型项目,一般会在线上部署多台服务器来做负载均衡的,如果 Session 的信息存在某一台服务器上,那么下一次请求被负载到另一台机器上那就找不到这个 Session 信息了。
有三种方法可以解决服务器有状态的问题:
- 同步 Session:就是服务器之间互相同步 Session,不过这会带来额外的开销,而且服务器之间会产生耦合。
- 黏性 Session:就是把请求一直粘在某一台服务器上,如果一开始被指派的是 A 服务器,那么之后的所有请求都会被指派到A服务器上。但是如果 A 服务器挂了,那么这种方法就失效了。而且这种方法很难保证负载均衡。
- 第三方存储:可以把 Session 放到第三方存储中,比如 Redis 里。这样服务器等于又没状态了,服务器的无状态意味着可以随意伸缩,服务集群可以根据流量加几台减几台,很方便。但是把 Session 放到第三方存储上只是把这个维护从服务器转嫁到第三方身上,第三方也得保证其自身的高可用,不过一般而言我们的系统本来就要维护第三方存储,所以影响不大。
Token 的诞生
如果不考虑带宽的问题,可不可以仍然在客户端存储用户的信息呢?这样我们只需要解决安全性的问题就可以了。
我们可以让服务端根据存储在服务器上的密钥和用户信息生成签名,然后将签名拼接到用户信息后面,然后再将这个 Token 颁发给用户,当下一次请求带着 Token 访问服务器时,服务器可以根据 Token 的用户信息生成签名,然后和 Token 上的签名进行比较,从而验证 Token 的真伪。具体过程如下图所示:
这样服务器就无状态了,但是客户端就有状态了。有了 Token 之后服务器因为无状态所以可扩展,并且 Token 还能跨应用使用。比如同一个公司不同应用之间的调用,所有应用只要能识别这个 Token 就都能登录,这就是单点登录。如果是第三方服务提供方也更容易地提供服务,只需要颁发一个 Token 给调用者即可。其实这还蕴含了时间换空间的思想,把存储在服务器的用户信息暴露出去,利用签名来验证 Token 的真伪。
10. 什么是前后端分离?
前端静态资源和后端动态服务解耦。前端只关心 HTML 等前端代码,不涉及一行后端代码,后端只关心自己提供的服务,不涉及一行前端代码。这就是前后端分离的思想。
在这种思想的指引下,SPA(single page web application,单页面应用)就出现了。SPA 是单个 HTML 页面的 Web 应用程序,它在用户与应用程序交互时由 JavaScript 动态更新页面。其工作原理如下图:
浏览器客户端一开始会加载必需的 HTML、CSS 和 JavaScript,之后的所有的操作都在这张页面上完成,由 JavaScript 来控制,通过某种数据格式和服务端产生交互,获取返回结果。
11. 什么是 REST?
REST 是 REpresentational State Transfer(表述性状态转移) 的首字母缩写,可以将其拆开理解,如下图所示:
REST 是一种设计思想,它的核心是资源,可以理解成在 REST 的世界里,万物皆资源。
- REpresentational(表述性):这是个形容词,它想要表达的意思是,资源可以用各种形式来进行表述,无论是 XML、JSON 还是 HTML,只要适合资源使用者,任何形式都可以。
- State(状态):这是个名词,也是 REST 思想的本质。它告诉开发者,REST 关注的是资源当前的状态,而不是对资源采取的行为。无论资源的形式如何变化,它要表达的内容其实是统一的,该资源存在还是不存在,单个信息还是多个信息,都有哪些属性,这就是资源的状态。
- Transfer(转移):这是个动词,它指转移资源,以某种表述性形式把资源从一个应用转移到另一个应用。转移过程中,资源状态可能会有所变化。
比如很多网站会维护用户的个人资料信息,如果用 REST 来设计相关操作的 API,可以这么设计:
操作项 | URL | HTTP 方法 |
---|---|---|
新增个人资料 | http://api.example.com/profile | POST |
查询个人资料 | http://api.example.com/profile | GET |
修改个人资料 | http://api.example.com/profile | PUT |
删除个人资料 | http://api.example.com/profile | DELETE |
简单讲,REST 就是 URL 定位资源,HTTP 方法操作资源。