我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
查看源代码

为什么我无法访问一个网站

这是从我开始经营 RP 主机 以来,被问及的最多的一个问题。

本文将以诊断「为什么我无法访问一个网站」的方式,讲述 Web 服务的大致工作流程。

目录

  • URL
  • DNS
  • TCP/IP 连接
  • 加载资源
  • 渲染

URL

通常来讲,所谓访问一个网站,我们输入给浏览器的是类似于这样的一个地址:

http://jysperm.me/note/1519

用术语来讲,这是一个 URI, 一个 URI 有两个部分,一是协议,二是定位符。
比如「mailto:jysperm@gmail.com」这是一个邮箱的标识符,其中「mailto」是协议,「jysperm@gmail.com」是定位符。

再比如「urn:isbn:9787115281487」这是一本书(HTTP 权威指南)的标识符。

用来表示网页的 URI 有一个比较特殊的名字叫 URL, 它大致分成这几个部分:

  • http - 协议
  • jysperm.me - 主机名
  • /note/1519 - 路径

除此之外还可能会有类似于「?id=1519」的查询字符串。

这样的一个 URL, 便可以定位到一个网页。

DNS

首先我们要找到为我们提供服务的服务器,即 URL 中的主机名,在这里是 jysperm.me.

TCP/IP 网络中通过 IP 地址来唯一地定位一台主机,更确切地说,每一块网卡,会有一个唯一的 IP 地址。

IP 地址形如 117.121.25.186, 它本身是存在一定结构性的,比如 117.121.25.186 和 117.121.25.187,就有非常大的可能性两者的物理距离很近。

这样的结构性方便于计算机之间互相联络,但不便于人类记忆,于是我们用由字母组成的域名来表示主机。

我们通过一个叫 DNS 的系统,来将域名翻译成 IP 地址,DNS 系统本身说简单也简单,说复杂也复杂,在这里我们只讲述如何使用,而不研究其原理。

如果浏览器给你的提示是类似于「无法找到 jysperm.me」或者「无法连接到 jysperm.me」,那么有很大可能性是 DNS 查找失败或者出错。

我们可以使用 nslookup 这个命令来手动进行 DNS 查询

> nslookup jysperm.me
Server: 8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
Name:   jysperm.me
Address: 117.121.25.186

可以看到,我们向 8.8.8.8(Google 的免费公众 DNS), 查询 jysperm.me 这个域名,它返回给我们的结果是 117.121.25.186.

这里是 8.8.8.8 是系统的默认 DNS 服务器,我们还可以自己来指定 DNS 查询服务器:

> nslookup jysperm.me 114.114.114.114
Server: 114.114.114.114
Address:    114.114.114.114#53

Non-authoritative answer:
Name:   jysperm.me
Address: 117.121.25.186

这里使用了国内的 114.114.114.114 进行查询,返回的结果是一样的。

在某些网络封锁比较严重的国家,DNS 查询的结果可能会被篡改,因为 DNS 本身几乎没有任何安全措施,所以查询到的结果可能并不是可靠的。

TCP/IP 连接

知道了服务器的 IP 地址,下一步是建立 TCP 连接。这一步最常遇到的问题有:

  • 无法连接到服务器/连接超时
  • 连接被拒绝
  • 连接被重置

首先 IP 层面,要向一台主机发送数据,这个主机必须是「可达的」,换句话说就是对方必须在线。

最简单的,我们可以用 ping 命令验证一个主机是否在线:

> ping 117.121.25.186
PING 117.121.25.186 (117.121.25.186): 56 data bytes
64 bytes from 117.121.25.186: icmp_seq=0 ttl=128 time=138.651 ms
64 bytes from 117.121.25.186: icmp_seq=1 ttl=128 time=71.345 ms
64 bytes from 117.121.25.186: icmp_seq=2 ttl=128 time=286.960 ms

ping 使用的是 ICMP ECHO 指令,就好比你跟对方打招呼,问它是否在线,如果对方回应了,就说明它在线。但是,并非所有服务器都会回应 ICMP ECHO.

如果发现 ping 命令没有回应,类似于下面的情况:

> ping 59.24.3.173
PING 59.24.3.173 (59.24.3.173): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2

那么就说明你和服务器直接没有建立连通的连接,但是,连接是在那里断开的呢?这时我们可以用 traceroute 来探测数据包所走过的路径:

> traceroute www.qq.com
traceroute to www.qq.com (180.96.86.192), 64 hops max, 52 byte packets
 1  * * *
 2  100.64.0.1 (100.64.0.1)  10.224 ms  5.379 ms  6.794 ms
 3  218.4.12.229 (218.4.12.229)  8.342 ms  6.817 ms  8.169 ms
 4  218.94.165.2 (218.94.165.2)  8.128 ms  8.259 ms  7.173 ms
 5  61.155.133.121 (61.155.133.121)  11.152 ms  9.288 ms  9.990 ms
 6  202.102.69.254 (202.102.69.254)  11.464 ms  12.463 ms  11.027 ms
 7  180.96.51.94 (180.96.51.94)  13.674 ms  13.192 ms  12.364 ms
 8  180.96.48.202 (180.96.48.202)  13.564 ms  11.213 ms  13.945 ms
 9  * * *

traceroute 依赖于 ICMP, 并非所有服务器都开启了 ICMP, 因此会有一些路径点被显示为星号。

我们再来看另一个不可达的例子:

> traceroute twitter.com
traceroute to twitter.com (59.24.3.173), 64 hops max, 52 byte packets
 1  * * *
 2  100.64.0.1 (100.64.0.1)  4.694 ms  4.502 ms  8.044 ms
 3  218.4.12.237 (218.4.12.237)  8.874 ms  5.177 ms  8.133 ms
 4  218.4.13.49 (218.4.13.49)  15.205 ms  11.400 ms  12.011 ms
 5  202.97.55.41 (202.97.55.41)  14.011 ms  15.794 ms  16.518 ms
 6  202.97.50.254 (202.97.50.254)  12.207 ms  12.614 ms  13.165 ms
 7  202.97.35.78 (202.97.35.78)  12.246 ms
    202.97.35.22 (202.97.35.22)  13.337 ms
    202.97.34.126 (202.97.34.126)  13.701 ms
 8  202.97.60.33 (202.97.60.33)  58.292 ms  12.432 ms  18.093 ms
12  * * *

可以看到,最后一个可以追踪到的路径点是 202.97.60.33, 通过一些 IP 库可以查到,这个地址属于「广东省广州市 互联网交换中心」,可以打个电话问问他们那边出了什么情况。

加载资源

访问一个网页会发起不止一个请求,除了网页本身还会加载一些例如样式,图片,脚本之类的资源,甚至很多时候还会加载来自其他网站的资源,通过 Chrome 的开发人员工具中的「Network」选项卡,可以看到加载一个页面所发起的所有请求。

这是一个正常的网站, 所有的资源都加载成功了:

正常网站的加载情况

再看下面这张图,其中一个资源没有加载完成,导致整个页面都无法完成,这时我们就可以通过上面的方法单独排查这一个请求。

没有加载完全的情况

通过浏览器来检查一个资源究竟能不能下载在一些复杂情况下并不可靠,因为浏览器会为你的请求加上大量的参数,而且在得到资源后,还会进行渲染。

因此为了「纯粹」地下载一个资源,我们可以用 curl:

> curl http://pomotodo.com -I
HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Fri, 01 Aug 2014 03:51:35 GMT
Content-Type: text/html
Content-Length: 154
Connection: keep-alive
Location: https://pomotodo.com/

可以看到 http://pomotodo.com 并非像我们看到的那样显示了一个页面,而是发起了一个到 SSL 版本地址的重定向,SSL 可以保证传输的私密性,目前国内只有很小一部分有节操的网站在使用。

渲染

等到所有资源都加载完了,但是页面还是没有内容,或者乱七八糟怎么办?

在正确地得到所有资源后,浏览器会执行网站提供的脚本,来对资源进行加工,以便像网站制作者期望的那样来展现页面。

在这个过程中,脚本需要使用浏览器提供的 API 来进行渲染,而不同的浏览器所支持的 API 是有差异的,因此一些制作不是很精良的网站会在不同的浏览器中呈现不同的效果,甚至直接出错。

在此建议大家选择一个现代而强大的浏览器,比如 Chrome, 这样可以保证浏览器支持网页所需要的功能。

撰写评论

如希望撰写评论,请发邮件至 jysperm@gmail.com 并注明文章标题,我会挑选对读者有价值的评论附加到文章末尾。

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2024-04-08.