写在前面:
博主在字节一面的时候,面试官就问我:浏览器输入URL之后,会发生什么?
虽然博主心里知道面试官想考察的内容是对网络包传输的流程,但是当时还是答得不是很好,故决定总结一系列文章来好好讲讲网络相关知识。
此为系列第一讲,讲的内容是关于DNS协议的。
博主当时的回答
博主当时的回答是这样的:
当用户输入一个URL之后,浏览器会根据HTTP/HTTPS协议将该请求逐个经过TCP/IP协议栈进行封装。在应用层除了根据HTTP/HTTPS协议添加报头之外,还会根据DNS协议去查询URL所对应的服务器,获取该服务器的IP地址。然后将该IP添加到网络包的目的IP中。之后和服务器建立TCP三次握手,之后服务器响应浏览器的请求,讲请求包发给浏览器。客户端收到请求包之后会根据请求包内的内容将资源渲染给用户。之后,如果是短链接,会进行TCP四次挥手;如果是长链接,则双方会建立相关信息维护这条链接。
今天的文章就是去讲DNS协议在这个过程中扮演了什么样的角色。
DNS服务器
在网络世界中,IP地址是唯一标识主机的DNS。但是我们在www.baidu.com其实也可以访问百度的主机啊?这是因为有DNS服务器这个网络世界的地址簿。它记录了域名和IP地址的对应关系。由于现实世界中域名的大量使用,所以DNS服务器就一定要设置成高可用、高并发和分布式的。
于是,就有了以下的树状层次结构:
域名和DNS解析
域名本身我们都很熟悉,其是一串用点分割开的字符串。其本身是全球唯一的,需要通过专门的域名注册商才可以申请注册。为了组织全球互联网中的众多计算机,域名的一个个块被用点分开,形成分层的结构。而每个被点分开的字符串就构成了域名中的一个层级,并且位置越靠后,层级就越高。
我们拿CSDN的网址:www.csdn.net来看一下,这个字符串中,.net
是顶级域名,中间的.csdn
是二级域名。这里有一点要注意以下,.
是所有域名的根,也就是说所有域名都以点作为后缀。比如说www.csdn.net,其实最后会被修饰成www.csdn.net.
DNS解析流程
为了提高DNS的解析效率,很多网络都会就近部署DNS缓存服务器。于是就有了以下的DNS解析流程:
- 主机客户端现在本地DNS缓存中查询数据,如果没有就转到第二步。
- 然后本地域名服务器(本地DNS)询问www.csdn.net的ip地址是多少?本地DNS就是由网络服务商,电信、移动、联通等自动分配,它通常是在网络服务商的某个机房。
- 本地DNS收到客户端的请求之后,会去它缓存的域名-IP对应表中查询www.csdn.net所对应的IP地址。如果找到了就返回给客户端;如果没找到就将此请求转发到根DNS服务器。
- 根DNS服务器收到请求之后,发现后缀是
.net
,就将.net
顶级域名服务器的地址给客户端发过去。 - 客户端收到地址后,就去
.net
顶级域名服务器上去请求。顶级域名服务器负责管理二级域名。 - .net顶级域名服务器收到请求之后,就将负责www.csdn.net区域的权威DNS服务器地址给客户端。
- 客户端收到权威DNS服务器的地址后,就去权威DNS服务器上请求IP地址,权威DNS服务器将IP返回给客户端
- 收到IP地址之后,客户端就可以根据IP地址访问目标服务器了
查看本地DNS配置
上面的DNS递归查询挺麻烦的,不过其是DNS服务器自动完成。我们要做的就是配置可用的DNS服务器。
我们可以在Linux中输入以下命令来查看我们的系统配置:
ubuntu@VM-0-2-ubuntu:~/code/Code/leetcode$ cat /etc/resolv.conf
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients to the
# internal DNS stub resolver of systemd-resolved. This file lists all
# configured search domains.
#
# Run "systemd-resolve --status" to see details about the uplink DNS servers
# currently in use.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.
nameserver 127.0.0.53
options edns0
在这里,博主的系统配置的是127.0.0.53
这个域名服务器。
查看域名对应的IP地址
另外,DNS服务通过资源记录的方式,来管理所有数据,其支持A、CNAME、MX、NS、PTR等多种类型的记录。比如:
- A:把域名转换成IP地址
- CNAME:创建别名
- NS:该域名对应的域名服务器地址
我们可以在Linux中使用 nslookup 运行以下命令查看域名的A记录:
ubuntu@VM-0-2-ubuntu:~/code/Code/leetcode$ nslookup www.csdn.net
# 域名服务器及端口信息
Server: 127.0.0.53
Address: 127.0.0.53#53
# 非权威查询结果
Non-authoritative answer:
Name: www.csdn.net
Address: 39.106.226.142
在这上面我们最终在本地DNS缓存中查询到了www.csdn.net的IP地址,是39.106.226.142
查看DNS递归过程
前面DNS查询流程的时候,还提到了。如果没有命中缓存,DNS查询实际上是一个递归的过程。
那么我们如何去查看DNS这个递归的过程呢?在Linux中我们可以使用解析工具 dig
,其就提供了trace功能,可以展示递归查询的整个过程。
ubuntu@VM-0-2-ubuntu:~/code/Code/leetcode$ dig +trace +nodnssec www.csdn.com
; <<>> DiG 9.11.3-1ubuntu1.13-Ubuntu <<>> +trace +nodnssec www.csdn.com
;; global options: +cmd
;; Received 28 bytes from 127.0.0.53#53(127.0.0.53) in 0 ms
博主,这里就是在本地DNS缓存中查找到了www.csdn.com的IP地址。
DNS负载均衡
我们现在回到DNS解析流程那里,站在客户端的角度,这是一次DNS递归查询的过程。因为本地DNS会全权完成这件事情。而我们只需要等待结果罢了。但是,在这个过程中,DNS除了可以通过名称映射为IP地址,它还可以做另一件事情,就是负载均衡。
例如,某个应用要访问另外一个应用,如果配置另外一个应用的IP地址,那么这个访问就是一对一的。但是当被访问的应用撑不住的时候,我们其实可以部署多个。这样在域名解析的时候,我们只要配置策略,这次返回第一个IP,下次返回第二个IP,这样就可以实现负载均衡了。
一般来说,大型的架构服务需要保证高可用。为了保证高可用,我们往往会将服务部署在多个机房,每个机房都会有自己的IP地址。当用户访问某个域名的时候,这个IP地址就可以轮询访问多个数据中。如果一个数据中心因为某种原有挂了之后,只要在DNS服务器里面。将这个数据中心对应的IP地址删除,就可以实现一定的高可用。
参考文献
[1] 刘超.趣谈网络协议.极客时间
[2] 倪朋飞.Linux性能优化实战.极客时间
转载:https://blog.csdn.net/shenmingxueIT/article/details/117389594