谷歌每收到一个请求会打开多少个套接字?

16
以下是我最近与一家知名网络软件公司的面试经历。我被问到关于交互TCP层和web请求的问题,这让我感到困惑。我真的很想听听专家对答案的看法。这不仅仅是关于面试,更重要的是对网络如何工作(或应用层和传输层是否交叉对话)的基本理解。
1. 面试官:告诉我当我打开浏览器并输入“google.com”时,在幕后发生的过程。
我:首先创建一个由{SRC-IP,SRC-PORT,DEST-IP,DEST-PORT,PROTOCOL}标识的套接字。 SRC-PORT编号是浏览器给出的随机数字。通常建立TCP/IP连接协议(三次握手建立)。现在客户端(我的浏览器)和服务器(Google)都准备好处理请求。(建立TCP连接)。
2. 面试官:等等,名称解析是何时发生的?
我:是的,我很抱歉。甚至在创建套接字之前,DNS名称解析就已经发生了。首先进行DNS名称解析以获取Google的IP地址。
3. 面试官:DNS名称解析会创建套接字吗?
我:嗯,我其实不知道。但我知道DNS名称解析是无连接的。也就是说,它不是TCP,而是UDP。只发生单个请求-响应周期。(因此需要为DNS名称解析创建一个新套接字)。
4. 面试官:google.com对其他客户端的请求也是开放的。那么,与Google建立连接会阻塞其他用户吗?
我:我不确定Google如何处理这个问题。但在典型的套接字通信中,阻塞到最小程度。
  • 面试官: 你认为这个问题该如何处理?

    : 我猜这个进程会分叉出一个新的线程,并创建一个套接字来处理我的请求。从现在开始,我的与谷歌通信的套接字终点是这个子套接字。

  • 面试官: 如果是这样,那么这个子套接字的端口号是否不同于父套接字的端口号?

    : 父套接字在80上监听来自客户端的新请求。子套接字必须在不同的端口号上监听。

  • 面试官: 由于您的目标端口号已更改,您的TCP连接是如何维护的(即发送到Google数据包的src-port号码)?

    : 作为客户端看到的目标端口始终是80。当响应被发送回来时,也是来自端口80。我猜测操作系统/父进程在发送响应之前会将源端口设置回80。

  • 面试官: 您与Google的套接字连接有多长时间?

    : 如果我在一段时间内没有发出任何请求,主线程将关闭其子套接字,我之后的任何请求都将像新客户端一样处理。

    面试官: 不,Google不会为您保留专用的子套接字。它处理您的请求并立即丢弃/回收套接字。

  • 面试官: 虽然Google可能有许多服务器来处理请求,但是每个服务器只能打开一个在端口80处的父套接字。访问Google网页的客户端数量必须大于他们拥有的服务器数量。这通常是如何处理的?

    : 我不确定这是如何处理的。我认为唯一的方法是为每个收到的请求生成一个线程。

  • 面试官: 您认为Google处理此问题的方式与任何银行网站有所不同吗?

    : 在TCP-IP套接字层面上,应该是相似的。在请求层面上,稍微有些不同,因为需要维护会话以保持银行网站之间请求的状态。

  • 如果有人可以解释每个要点,这对于网络初学者将非常有帮助。


    1
    很可能浏览器实际上并没有请求特定的源端口,而是将其留给操作系统来查找一个空闲端口,因为浏览器并不尝试提供任何内容。DNS解析也由操作系统处理;它首先检查主机文件(在Lunix上是/etc/hosts,在Winblows上是System32/drivers下的某个文件)。 - Parthian Shot
    1
    告诉我当我打开浏览器并输入google.com时,背后发生的过程。大部分过程将被Wireshark记录下来,“Wireshark与我的ISP不兼容”...什么?Wireshark是一款本地程序,被动监视通过您的NIC传输的流量。您的ISP不仅不知道它正在运行,而且您的ISP实际上无法知道您是否在捕获通过您的计算机传输的流量。您可以使用Wireshark、Fiddler、Tcpdump或Ethereal或Etherape... - Parthian Shot
    1
    你对面试官问题的回答都没有考虑到客户机可能有多个网卡需要检查适合通往Google的路由,或者本地首先执行DNS(主机文件),然后通过每个网卡的网关进行(以便路由器可以执行局域网地址的DNS),最终会达到ISP网关并通过ISP/互联网DNS服务器迭代工作,直到最终得出确定的答案。DNS本身支持TCP和UDP(是的,DNS涉及套接字,但通常不是你自己创建的,除非你发送自己的DNS查询)。 - Remy Lebeau
    1
    一旦您连接到Google,查询不会阻塞其他用户。任何值得信赖的Web服务器都不会是单线程的。众所周知,Google为其Web服务器和其他在线系统使用定制软件,因此它如何实现并发请求的处理是任何人的猜测,但它必须处理的大量流量绝对不会是同步/阻塞的。 - Remy Lebeau
    1
    很可能每个请求都不会生成一个新的线程,在像谷歌这样大规模的可扩展系统中,这是行不通的。你不能让单个服务器同时运行数万个线程,操作系统会崩溃。在大型系统中,跨多个服务器进行负载均衡非常普遍,每个服务器都必须管理其线程开销,因此在同一单个线程中异步处理多个请求是可能的,因此需要较少的线程。 - Remy Lebeau
    显示剩余11条评论
    2个回答

    18
    Google每收到一个请求会打开多少个套接字?
    这个问题实际上并没有出现在面试中,但既然您提到了,我还是来回答一下吧。Google实际上并不会打开任何套接字,它只是通过接受新的连接来形成套接字。所以我不会描述它为“打开”套接字。
    面试官: 当我打开浏览器并在其中输入google.com后,背后会发生什么过程?
    我: 首先创建一个由{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}标识的套接字。
    面试官:等等,名称解析是什么时候发生的?
    我:是的,对不起。在创建套接字之前应该已经进行了DNS名称解析,以获取谷歌的IP地址。
    面试官:DNS名称解析是否会创建套接字?
    我:我其实不知道。但我知道DNS名称解析是无连接的,也就是说它不是TCP而是UDP。只有一个单独的请求-响应周期。

    面试官:google.com可以处理来自其他客户端的请求,那么你连接Google会阻塞其他用户吗?

    我:我不确定Google是如何处理这个问题的。但在典型的套接字通信中,它只会被阻塞到最小程度。

    面试官:你认为应该如何处理这个问题?

    我:我猜进程会创建一个新线程并创建一个套接字来处理我的请求。从现在开始,我的与Google通讯的套接字端点是这个子套接字。

    面试官:如果是这样的话,这个子套接字的端口号是否与父套接字不同?

    我:父套接字正在80端口监听来自客户端的新请求。子套接字必须监听不同的端口号。

    面试官:由于你的目标端口号已经改变,你的TCP连接是如何保持的?(即Google包中发送的源端口号)

    我:作为客户端看到的目标端口始终是80。当请求被发送回来时,它也来自端口80。我猜测操作系统/父进程在发送回复之前会将源端口设置回80。

    面试官:你和谷歌的套接字连接建立多长时间了?

    我:如果我在一段时间内没有发出任何请求,主线程将关闭其子套接字,并且我之后的任何请求都像是一个新的客户端。

    错误。您对Google的线程一无所知,更不用说哪个线程关闭套接字了。任何一端都可以随时关闭连接。最可能的是服务器端会比你先关闭连接,但这并不是铁板钉钉的,也没有哪个线程会执行此操作。

    面试官说错了。他似乎没有听说过HTTP keep-alive,或者默认情况下是在HTTP 1.1中使用的事实。

    面试官:尽管Google可能有许多服务器来服务请求,但每个服务器只能在端口80上打开一个父套接字。访问Google网页的客户端数量必须超过它们拥有的服务器数量。这通常是如何处理的?

    我:我不确定这是如何处理的。我看到唯一可行的方式是为每个接收到的请求生成一个线程。

    这里你根本未回答问题。他正在寻找关于负载均衡器或循环DNS或在所有这些服务器前面的某些东西的答案。但是他的句子“访问Google网页的客户端数量必须超过它们拥有的服务器数量”已经通过您和他都错误地称之为“子套接字”的存在得到了回答。除非您不准确地报道了这个问题,否则这不是一个很好的问题。

    面试官:您认为Google处理方式与任何银行网站有什么不同吗?

    我:在TCP-IP套接字层面上,应该是类似的。在请求级别上,略有不同,因为银行网站中维护了一个会话以保持请求之间的状态。

    你几乎答对了这个问题。Google和银行网站都存在HTTP会话。这不是一个很好的问题。他应该询问事实,而不是你的观点。

    总体而言,(a)你完全失败了面试,(b)你过多地猜测了。你应该简单地说“我不知道”,让面试继续进行你真正了解的内容。


    好的。需要澄清一下,您提到“TCP服务器每个已接受的连接都有一个单独的套接字”,这是绝对正确的。但这仅适用于已接受的连接。服务器套接字是开放的以进行侦听。第一次客户端发出请求时,它需要创建一个新的Socket并将工作委托给该Socket。只有TCP连接建立。在新套接字创建完成之前,主线程将被阻塞(但这将非常非常小,仍然被阻塞)。这有意义吗? - brain storm
    还有一个重要的点:对于一个使用个人电脑浏览器并在不同的标签页中打开三个不同网址的典型客户端来说,操作系统会创建三个带有IP:端口对的套接字。对于一个连接来说,它将变成四对SRC-IP、SRC-PORT和DEST-IP、DEST-SRC,对吗? - brain storm
    @brainstorm TCP服务器打开1个监听套接字;它循环调用accept()来接收套接字,并启动线程来处理它们,将它们输入到select() FD集合中,或者启动一些异步操作。accept()是阻塞的,而接受循环是速率决定步骤,但断言它会阻塞其他客户端是过于夸张的。由于有积压队列,其他客户端可以继续连接。他们在接受循环开始接受他们之前不会得到服务,但这应该足够快,以至于除非服务器编程不良,否则不会察觉到。 - user207421
    @brainstorm 你不能把浏览器标签和套接字等同起来。浏览器使用连接池,因此没有1:1的关系。加载页面可能需要加载图像、.css/.js文件等,这通常是由多个套接字并行完成的。 - user207421

    -1
    对于第6点,这是我的理解:如果端到端连接的两端与另一个套接字相同,则确实无法区分两个套接字,但如果单个端口与另一个套接字不同,则很容易区分两者。因此,没有必要来回转换目标端口80(默认值),因为源端口不同。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接