我的 个人网站 上线了,上面可以更好的检索历史文章,并且可以对文章进行留言,欢迎大家访问

可能大家都知道或者被问过一个问题,那就是很经典的「从浏览器输入 URL 再到页面展示,都发生了什么」。这个问题虽然简单,但是真的能够从回答的各种细节上看出不同人之间的水平差距。

这篇文章主要是聊一聊输入 URL 之后的第一步——域名解析

域名就类似于 www.google.com,而通过 ping 命令,就可以查询到对应域名的 IP 地址了。

那为什么又要有域名,又要有 IP 呢?

域名、IP 共存

首先还是解释一下,为什么会出现现在这种域名、IP 地址共存的情况。主要有两个点:

  1. 提升用户体验
  2. 提高运行效率

分别解释一下,IP 地址长度为 32 位,平时用十进制来表示的话,就长这样——192.168.1.0 ,但是想象一下,如果我们要访问某个网站需要让我们输入这么一长串数字,体验肯定相当差,首先记忆这么长串数字对很多人来说就很痛苦,更何况我们常用的网站肯定不止一个。

除此之外,如果你给其他人推广你的网站,你吧啦吧啦说了一大堆,然后来个「如果你感兴趣,请访问我们的网站 192.168.1.0」,然后就没有然后了。

这也是为啥现在仍然在使用域名,方便人脑去记忆。

那为啥还需要 IP 地址呢?因为 IPv4 中的 IP 地址只需要 4 个字节,而用字符串表示的域名最少也需要几十个字节,长的甚至达到几百字节,而这会大大的增加底层路由器的负担。

这也是为啥 IP 地址仍然在被使用。人来使用域名,而路由器层则使用 IP 地址,就跟我们书写的是我们能认识的字符,而最终计算机认识的是一堆二进制一样。

DNS 解析

知道了这个背景之后,我们就可以来看看「域名」是如果变成「IP 地址」的。

首先我们知道,会往 DNS 服务器发送请求,那问题就来了,浏览器怎么知道 DNS 服务器的地址是啥?

答案是提前配置好的。当然这不是唯一的方式,DNS 也有可能通过 DHCP(Dynamic Host Configuration Protocol) 动态分配的。

例如,MacOS 中的 DNS 配置就长下面这样。

当然,你也可以通过命令行来查看、修改,地址在 /etc/resolv.conf

有了 DNS 服务器,那么你可能会觉得,接下来的事情就很简单了:

我给你传个域名,你返给我对应的 IP 地址即可。那问题来了,现在互联网中有数万台的 DNS 服务器,我怎么知道数据在哪台服务器上?难道要一台一台的遍历请求这数万台服务器吗?

我相信你肯定没有感知到在浏览器中输入域名到页面展示会花费那么久,这也说明肯定不是一台一台服务器进行遍历的。

域名的组成

要了解 DNS 是如何对其进行优化的,我们需要先知道域名的组成部分。看到这,很可能你会这么想:

啥组成?不就是一堆字符串吗?

实际上,域名是有由不同的组成的,每个 . 隔开的部分就是一个

这里举个例子,假设我们分析的域名为 www.google.com ,从我们平时写快递的收货地址的惯性思维来看,这个域的各个部分大小可能是这样的:

www > google > com

但是实际上并不是这样,而是:

. > com > google > www

你甚至发现,最大的还是个 . 。其实完整的域名应该是 www.google.com.. 代表根域,因为根域对于所有的域名来说,意义都一样,所以平时我们都把最后的点给省略了。

每个域都有自己的专属名词:

. > com > google > www

根域 | 一级级域|二级域名|(子域名)|主机名

当然,我们知道还可以针对二级域名再划分子域名,类似于 mail.google.com

所以看到这,你应该能够理解域名是由层次的这个概念了,我再举个比较的通俗的例子。

com 公司的 google 部门的 www。https://mail.google.com/mail/u/0/#inbox

DNS 的分层

了解完域名的分层之后,DNS 是如何优化域名解析的问题就迎刃而解了,那就是——分层。

DNS 服务器会将域名的数据分布式的存储在各个 DNS 服务器上,但是同一个域的数据,会存储在同一台 DNS 服务器上,同一台 DNS 服务器可以存储多个域的数据。

这么说可能会有些抽象,一图胜千言,其实就是这样:

有了对数据的分层,那么查询数据就会很有节奏感

查询域名数据

一图胜千言,有了分层的机制,整个的查询过程就会长这样:

首先会去配置的 DNS 服务器中查询,这个其实一般都是本地或者内网中的 DNS 服务器。如果没有找到,就会去问根域要,说哥们,我这里需要 www.google.com 的 IP 地址。

根域一看,我这里没有啊,但是我知道 com 域的 DNS 服务器地址,他可能知道。

然后 com 域的 DNS 服务器一看,www.google.com 的 IP 地址我也不知道,但是我知道 google.com 域的 DNS 服务器的地址,他可能知道,你再去问问他。

就这样一路问下去,最终就能够找到 www.google.com 所对应的 IP 地址了。

根域名服务器

看了上面的流程,可能你还是会有点疑问。因为去找 DNS 服务器查询 IP 地址时,初始的 DNS 的服务器的 IP 地址是走的本地计算机的配置的。那在分层查询时,我怎么知道有哪些根服务器?以及我怎么知道这些根服务器的 IP 地址是啥?

答案是内置

我们的设备,或者说所有能上网的设备都会内置根服务器的列表。总共有 13 台根 DNS 服务器,分别是[a-m].root-servers.net ,这些根服务器的地址根本不需要查询就能直接获取。

当然,稍微想想也知道,13 台服务器是很难扛住全球互联网用户的请求的,实际上对于这 13 台服务器有很多的镜像服务器

眼见为实

说了这么多虚的概念,接下来我们通过 dig 命令来实际操作一下。

可以看到,在 QUESTION SECTION 下的完整域名是 www.google.com. 是带了根域的,那后面的这个 INA 又是啥意思呢?

这是因为,在向 DNS 服务器查询请求的时候,需要三个参数,分别是:

  1. 域名(例如 www.google.com)
  2. 网络类型(Class 设计之初,考虑到了多种网络并存的场景,但是目前实际上只有一种网络——互联网,所以该参数的值一直都会为 —— IN
  3. 类型(例如 A 表示 IP 地址,而 MX 则表示邮件服务器的地址)

而在 ANSWER SECTION 中,则是 DNS 服务的响应结果,上图中显示了总有 6 条 DNS 记录,并且在后面返回了其对应的 IP 地址。

而其中的 69 则是 TTL,单位是秒,代表了在 69 之内都不用再次发送请求了。

最下面则是统计的信息,本次 DNS 查询所话费的时间,以及请求的 DNS 服务器的地址和端口。这个服务器地址是我们本机配置的 DNS 服务器的地址。

眼尖的可能发现了,上图中根本没有设计到对根服务器的请求。这是因为这个命令把这部分给省略掉了,我们可能通过加上 +trace 命令行参数来查看详细的分级查询过程

这次我们以 www.36kr.com 来作为例子。

可以看到,上图中列出了所有的根域名服务器,然后去找 com 域要,然后再找 36kr.com 域去要,最终是拿到了 www.36kr.com 的 IP 地址。

缓存机制

当然,如果每次都从根服务器开始往下找,明显是不合理的,因为域名和 IP 地址的对应关系本来变动的就不频繁,所以 DNS 服务器是都会将结果缓存的。

并且,在下图中:

我只写了一个 DNS 服务器中有同级别的域信息,但是实际上不同层级的域信息可能存在于同一个 DNS 服务器,举个例子,com 域和 google.com 域可能在同一台机器上。

但是,这个缓存是有有效期的。如果在这个有效期内 DNS 数据发生了变化,那么缓存中的数据就会不正确,此时需要手动的将 DNS 删除。

本篇文章已放到我的 Github github.com/sh-blog 中,欢迎 Star。微信搜索关注【SH的全栈笔记】,回复【队列】获取MQ学习资料,包含基础概念解析和RocketMQ详细的源码解析,持续更新中。

如果你觉得这篇文章对你有帮助,还麻烦点个赞关个注分个享留个言

你的域名是如何变成 IP 地址的?的更多相关文章

  1. 负载均衡实现,一个域名对应多个IP地址

    负载均衡实现,一个域名对应多个IP地址 - 宏宇 - 博客园 https://www.cnblogs.com/cuihongyu3503319/archive/2012/07/09/2583129.h ...

  2. 【转】一个域名对应多个IP地址,接下来系统是依据什么决定使用哪个IP地址的?

    例如下图所示:nslookup http://www.sina.com.cn返回了多个IP地址,当使用curl通过域名进行访问时,则自动选择了其中一个地址进行访问,这个选择的过程里发生了什么事情? 绝 ...

  3. nginx篇最初级用法之三种虚拟主机基于域名\基于端口\基于IP地址端口的虚拟主机

    在nginx中虚拟主机的类型与apache一样也有三种 1.基于域名的虚拟主机 2.基于端口的虚拟主机 3.基于IP地址端口的虚拟主机 在nginx配置文件中每一个server为一个虚拟主机如果需要多 ...

  4. 负载均衡实现,一个域名对应多个IP地址【转载】

    使用负载均衡实现,传统和常规做法,其他方式需要特殊处理.(dns轮询,或者自己做解析)1.一个域名设定多个dns服务或者服务器进行解析,同一个域名的每个解析都指向不同的ip地址,这样应答快的dns优先 ...

  5. Tomcat6 只允许指定域名访问,禁用IP地址访问,防止恶意解析

    运维网监控突然同事反应,在百度上搜索其他域名,竟然打开了和我们P2P一模一样的网站,我第一个反应是源代码被盗用了.后来发现,是域名被恶意解析了,解决方法 1.禁止IP地址访问项目 2.只允许指定的域名 ...

  6. 29、Tomcat只允许指定域名访问,禁用IP地址访问,防止恶意解析

    1.1.测试环境说明: Linux版本:7.6 IP地址:10.11.220.123/24 Tomcat版本:tomcat-8.5.37(端口号为8080) Jdk版本:1.8.0_202 1.2.配 ...

  7. nslookup获取域名对应的的ip地址

    1.先用nslookup获得域名对应的主机ip:nslookup 域名 2.再根据主机ip获得对应的主机名称: host ip $ nslookup baidu.com Server: 127.0.1 ...

  8. 域名ping不通,ip地址ping得通

    原因:dns服务器过期,需要更换dns服务器地址

  9. 【Web探索之旅】第三部分第二课:IP地址和域名

    内容简介 1.第三部分第二课:IP地址和域名 2.第三部分第三课预告:协议 第三部分第二课:IP地址和域名 上一课我们说了在Web之中,全球各地有无数台机器,有些充当客户机,有些作为服务器. 那么这些 ...

随机推荐

  1. 前端基础EL表达式(八)

    一.什么是EL表达式? 1.什么是EL表达式? EL(Expression Language) 是为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言, ...

  2. 【SpringCloud微服务实战】搭建企业级应用开发框架(一):架构说明

    SpringCloud分布式应用微服务系统架构图: SpringCloud分布式应用微服务系统组件列表: 微服务框架组件:Spring Boot2 + SpringCloud Hoxton.SR8 + ...

  3. JAVAWEB的基本入门(JSP、Tomcat)>从零开始学JAVA系列

    目录 JAVAWEB的基本入门(JSP.Tomcat) 使用idea创建web项目的两种方式 1.直接创建一个web项目(这样创建好的项目可以直接运行) 2.创建一个普通的java项目并配置web模块 ...

  4. JAVA集合类概览

    带着问题来阅读 1.Java有哪些集合 2.不同集合的应用场景分别是哪些 3.哪些实现类是线程安全的 4.为什么Java集合不能存放基本类型 5.集合的fail-fast和fail-safe是什么 J ...

  5. NAR | 张勇洪/周超/刘小云团队合作揭示2-羟基异丁酰化修饰调控光暗适应性反应机制

    景杰生物 | 报道 ​ 组蛋白赖氨酸的翻译后修饰是表观遗传学密码的重要组成部分,它们动态地调节染色质的结构和功能,影响基因表达活性,参与生物体的环境适应性调控.赖氨酸酰化修饰家族(Acylation) ...

  6. “百度杯”CTF比赛 十月场-Getflag(md5碰撞+sql注入+网站绝对路径)

    进去md5碰撞,贴一下脚本代码 import hashlib def md5(value): return hashlib.md5(str(value).encode("utf-8" ...

  7. bugku-web3

    这道题涉及的是HTML解码的问题,很简单,注意 HTML编码的格式 进入题目给出的网址,我们一直点击会一直循环跳动 勾选上阻止此页面创建更多对话框一栏,进去之后是空白的页面,查看源码. 这是一段HTM ...

  8. API文档生成(c# dll)

    一.Sandcastle 这个是c#类库方法根据注释生成帮助文档的工具,我们经常会遇到把DLL或者API提供给别人调用的情况,通过在方法中添加注释,然后再用Sandcastle 来自动生成文档给调用者 ...

  9. SaToken学习笔记-04

    SaToken学习笔记-04 如果有问题,请点击:传送门 角色认证 在sa-token中,角色和权限可以独立验证 // 当前账号是否含有指定角色标识, 返回true或false StpUtil.has ...

  10. Java-Collection、Map及Array之间的转换

    1 List -> Map 设个User类: public class User { private String userName; private String userId; privat ...