为什么需要DNS我们要访问某个度,可以在浏览器搜索栏输入IP地址112.80.248.76直接进入页面。这种行为是合法的,但却是病态的。大部分人连伴侣的电话号码都记不住,哪能记住这么一串IP地址。哦,对不起,我伤害了兄弟们,你们没有对手。但我假设你有。回想一下,即使您不记得伴侣的电话号码,也不会阻止您给她打电话。你的操作过程是不是打开通讯录,输入“富婆”,然后弹出一个电话号码。点击通话。在计算机领域,大概率你会记不住IP,所以你也需要有类似通讯录的功能。比如你只需要输入www.baidu.com,它就可以帮你找到对应的112.80.248.76,然后访问。其中www.baidu.com为域名,通过该域名可以获取其背后的IP为112.80.248.76。就像一个人可以有多个电话号码一样,一个域名也可以有多个IP地址。把域名解析成IP的过程,也就是查“通讯录”的过程,其实就是DNS(DomainNameSystem,域名系统)协议要做的事情。另外需要注意的是,上面的IP地址是我写这篇文章的时候可以访问的,但不代表大家看文章的时候可以访问。因为这背后的IP地址很可能会发生变化。pingwww.baidu.com可以得到最新的IP地址。但问题来了。普通人的通讯录通常有一千个电话号码,放在通讯录里绰绰有余。但是,网站域名不同。据说2015年就有3亿多。如果这3亿条记录放在一台服务器上,会出现两个问题。?3亿多条域名数据,数据量过大,且数据量持续增长?需要承担大量的读请求。每个网站域名可能有数千次访问。四舍五入时,这加起来高达数千亿qps。显然,如果把DNS做成手机通讯录那样的单点服务,是不可能实现这样的能力的,必须是分布式系统。那么,问题就变成了,如何设计一个支持千亿+qps请求的大规模分布式系统。我知道有人会说:“这是只有10qps服务的人应该考虑的事情吗?”虽然我们做的服务可能只有10qps,但这并不妨碍我们学习DNS中优秀的设计。让我们从URL层次结构开始。URL层次结构的示例。一个普通的域名,比如www.baidu.com。可以看到,这个域名中间有两个句号。域名可以用点符号分为三个部分。其中com称为一级域名或顶级域名,其他常见的顶级域名还有cn、co等,baidu为二级域名,www为三级域名。另外,在com后面,其实是省略了一个句号。它被称为根域。当域名比较多的时候,提取其中相同的部分,多个域名就可以变成这样一个树状的层次结构。这时候我们可以看到,这些领域其实是一种层级关系,就像学校、年级、班级一样。当你想定位一个特定的域名时,你可以通过这个层级找到对应的域名。例如。大家应该还记得那句标语,“三年级二班李晓明,你妈妈给你带了两罐旺仔牛奶。”层层找人。DNS的原理我们回头看看大佬们是怎么设计DNS的。首先直接得出最重要的结论。?使用分层结构拆分服务?添加多级缓存并扩展。使用URL层级拆分服务DNS承受着很大的流量压力,必须做成分布式服务,所以问题的关键就变成了如何拆分服务。由于URL具有树状的层次结构,因此存储它们的服务也可以基于此以非常自然的方式拆分成树状的形式。服务器维护一个或多个域的信息。于是服务就变成了下面的层级形式。当我们需要访问www.baidu.com时。查询过程同下图。该请求将首先到达最近的DNS服务器(例如您的家庭路由器)。如果在DNS服务器中找不到,DNS服务器会直接询问根域服务器。虽然根域服务器中没有www.baidu.com这条记录,但是它可以知道这个网址属于com域,所以它找到com域服务器的IP地址,然后访问com域服务器,重复以上操作,然后找出baidu域名放在哪个服务器上,继续往下,直到找到www.baidu.com的记录,最后返回对应的IP地址。可以看出原理比较简单,但是这里涉及到两个问题。?这台机器如何知道最近的DNS服务器IP是什么??最近的DNS服务器如何知道根域的IP?让我们一一回答。这台机器怎么知道最近的DNS服务器的IP是多少?在我之前写的《刚插上网线,电脑怎么知道自己的IP是什么?》中提到过,当插上网线时,机器会通过DHCP协议获取本机IP地址、子网掩码、路由器地址、DNS服务器IP地址。下面是我的mac机,DHCPOffer第二阶段的抓包截图。可以看到,这里返回的信息中包含了DNS服务器的IP。同时也可以通过点击左上角苹果图标->系统偏好设置->网络->高级->DNS查看左上角DNS服务器的IP地址。这是一个小细节。从上面的抓包图中,可以看到路由器地址、DNS服务器地址、DHCP服务器地址。它们实际上是192.168.31.1。这个其实是我家路由器的IP地址,也就是据说一般的家用路由器都有这些功能。而在某一个云服务器中,DNS服务器也是一样的,都是通过dhcp协议获取的。查看DNS服务器IP地址也很方便,执行cat/etc/resolv.conf即可。在上面的nameserver中,可以看到有两台DNS服务器,机器会按照在文件中出现的先后顺序发起请求。如果第一个服务器没有响应,它将请求第二个。最近的DNS服务器如何知道根域的IP是多少?我们也知道根域是域名树的最顶层。由于是顶级,所以信息一般都比较少。对应的IPV4地址只有13个,IPV6地址只有25个。我们可以通过dig命令的+trace选项查看一个域名的dns解析过程。而前面提到的13个传说中的根域,从字母a到m,都在上图中。但这又引出了一个问题,上面看到的都是域名。这。..“我本来是想通过域名找IP的,你让我找别的域名的IP?”听起来不科学,这不是死循环吗?是的,所以这些根域名对应的IP会以配置文件的形式放在各个域名服务器中。也就是说不需要请求根域名对应的IP,直接在配置中读取即可。下面的截图是域名服务器中的配置内容。可以看到以A开头的根域,其IPv4地址为198.41.0.4。对于读多写少的高并发场景,添加多级缓存几乎是标准配置。DNS也不例外,它加了缓存,而且不止一层。从浏览器的搜索框中输入URL。它会依次访问浏览器缓存、操作系统缓存/etc/hosts、最近的DNS服务器缓存。如果都找不到,就会去根域、顶级(一级)域、二级域等DNS服务器进行查询请求。于是请求流程就变成了如下图。大家可以看到我在上面提到的有缓存的地方都加了一个绿色的文件小图标,我优先在缓存里面查询。由于缓存了上述树形结构中的信息,因此最近的DNS服务器不再需要每次都从根域中查找。比如在缓存中能找到baidu.com的服务器IP,直接跳转到二级域名服务器上搜索即可。因为多级缓存的存在,大大减少了每一层实际接收到的请求。而且大家每天访问的网站就那么几个,所以大部分时间都可以命中缓存,直接返回IP地址。简单总结一下。在DNS的设计中,通过层级结构拆分服务,将流量分发到多个服务器。通过加入多级缓存,大大减少了每一级实际接收到的请求,从而大大提高了系统的性能。这两点都是我们在业务开发过程中可以参考的优秀设计。但是还有一点我们可能学不会。它被称为任播。它还为DNS实现高并发处理能力提供了重要支持。我会放在下一篇文章中讲到。协议格式DNS是一个域名解析系统,运行在该系统上的协议称为DNS协议。与HTTP类似,DNS协议也是一个应用层协议。下图是它的报文格式。字段太多,头晕?现在是对的。我们只挑几个关键点。交易ID是交易ID。对于一个request和这个request对应的response,它们的transactionid是相同的,类似于微服务系统中的log_id。标志字段是指标志位,有2个字节,16位。需要注意的是QR、OpCode、RCode。?QR用于标记这是查询还是响应消息,0是查询,1是响应。?OpCode用于标记操作码,正常查询为0,无论是查域名的ip还是查ip的域名,都是正常查询。可以粗略地认为,我们通常只看到0。?RCode是响应码,类似于HTTP中的404、502等状态码。用于表示本次请求结果是否正常。0表示一切正常。1表示报文格式错误,2是服务域名服务器内部错误。Queries字段是指您实际查询的内容。这里面其实包含了三部分信息,Name,Type,Class。?名称可以包含域名或IP。比如要查看域名baidu.com对应的IP,域名就放在里面。反之,如果通过IP查看对应的域名,则IP放在Name字段中。?类型是指您要查看的信息类型。比如你要查看这个域名对应的IP地址,那就填A(地址)。如果要查看此域名是否有其他别名,填写CNAME(CanonicalName)。如果要查看xiaobaidebug@gmail.com对应的邮件服务器地址(如gmail.com),则填写MX(MailExchanger)。还有很多其他的类型,下面是一个常见的Type表。?Class字段更有趣。你可以简单的认为我们只会看到它填写IN(Internet)。其实DNS协议的设计初衷就是考虑到可能会有更多的应用场景。比如这里也可以填CH和HS。你甚至不需要知道它们是什么意思,因为随着时间的发展,这些都已经成为了化石。我们知道这个字段唯一的作用就是面试的时候可以随意打个x,隐藏功绩和姓名。Answers字段,从名字就可以看出,对应Queries,一问一答。功能是返回查询结果,比如通过域名搜索对应的IP地址,具体的IP信息会放在该字段中。看完了抓包的原理,我们来抓一个包。我们打开wireshark。然后执行digwww.baidu.com,此时操作系统会发送DNS请求,查询www.baidu.com对应的IP地址。上图是DNS查询(请求)的内容,可以看出是一个应用层协议,传输层使用UDP协议进行数据传输。截图中红色标记的部分就是上面提到的需要注意的message字段的内容。其中,flag字段是按位显示的,所以在抓包中是按行显示的。接下来看响应包的内容。可以看出交易ID(TransactionID)与DNS请求报文是一致的。Answers字段中有两个IP地址。尝试后,两个IP地址都可以正常访问。总结DNS是一个优秀的高并发分布式系统,通过层次结构拆分服务,将流量分发到多台服务器。通过加入多级缓存,大大减少了每一级实际接收到的缓存,从而大大提高了系统的性能。这两点在业务发展过程中可以借鉴。当网线接入网络后,机器通过DHCP协议获取DNS服务器地址。根域服务器的IP会以配置的形式加载到各个DNS服务器中。因此,访问任何一台DNS服务器,都可以轻松找到根域对应的IP地址。最后,我留给你两个问题。从抓包可以看出,DNS在传输层使用的是UDP协议,那么是不是只使用UDP呢?上面说了,DNS里面只有13个IPV4根域名,而且很多其实都部署在美丽的国度。那是不是说只要他们不高兴,切断我们的访问,我们的网络就会瘫痪??
