(六)网络编程之化身一个哀求感受欣赏器输入URL后奥妙的网络之旅!

分享
程序员 2024-9-20 04:43:43 115 0 来自 中国
引言

   在欣赏器上输入一个URL后发生了什么? 这也是面试中老生常谈的话题,包罗网上也有大量关于这块的内容:

   
从百度的搜刮结果来看,能够搜到七千多万条纪录,因此本篇不会再以那种前篇划一的方式赘述,而是以现在较新的网络内容,连合体系中的大部分服务,将本身类比成一个哀求,切身感受到每个技能栈的详细细节,彻底从“根儿上”明白客户端哀求-服务端相应的全过程。
本篇以https://www.juejin.cn/为例举行分析,固然,这里假设掘金后端是Java做的(实际上掘金好像是基于Node做的后端)。
分享一个趣事,我发现掘金貌似使用的是.cn后缀的域名,并非通常使用的.com域名,好像www.juejin.com被人抢注了....^_^
一、地点栏输入后当地会发生的事故

   当我们在欣赏器的地点栏中,输入xxx内容后,欣赏器的历程起首会判断输入的内容:

  • 如果是平凡的字符,那欣赏器会使用默认的搜刮引擎去对于输入的xxx天生URL。
  • 如若输入的是网址,那欣赏器会拼接协议名形成完备的URL。
固然,在地点栏中输入某个内容后,也会举行一些额外利用,比方:安全查抄、访问限定等,但总归而言,欣赏器做的第一件工作则是天生URL,当按下回车后,欣赏器历程会将天生的完备URL发送到网络历程:

   
当网络历程收到传过来的URL后,起首并不会直接发出网络哀求,而是会先查询当地缓存:
   
观察上述流程,当网络历程收到传来的URL后,会起首通过URL作为Key,在当地缓存中举行查询:

  • ①如果当地中是否有缓存:

    • 没有:发起网络哀求去服务器获取资源,成功后将结果渲染页面并写入缓存。
    • 有:继承判断当地中的缓存内容是否已颠末期,没有则直接使用当地缓存。

  • ②如果当地中的缓存已颠末期,则会携带If-Modified-Since、If-None-Match等标识向服务器发起哀求,先判断服务器中的资源是否更新过:

    • 未更新:服务器返回304状态码,并继承读取之前的缓存内容使用。

  • ③如若服务器的资源更新过,那么也会向服务器发起哀求获取资源。
如果在当地缓存中,无法掷中缓存,大概当地缓存已逾期并服务器资源更新过,那么如今网络历程才会真正向目标网站发起网络哀求。
二、一个全新的“我”诞生过程与前期的履历

   当客户端的网络历程,在查询缓存无果后,会真正开始发送网络哀求,但要牢记:客户端的网络历程并非直接向目标网站发起哀求的,前期还需颠末一些细节处置处罚。
固然,为了能够更直观的感受整个过程,在这里我们将本身“化身”为一个哀求,站在哀求的角度切身材验一段奇特的“网络旅途”。
2.1、“我”诞生前的准备 - 分析URL

   在网络历程发起哀求之前,会起首对欣赏器历程传过来的URL举行分析,一样平常来说完备的URL结构如下:

   
但上述结构使用较少,通常环境下,欣赏器会使用的URL的常用结构如下:
   
URL中每个字段的释义如下:

  • scheme:表现使用的协议范例,比方http、https、ftp、chrome等。
  • ://:协议范例与后续形貌符之间的分隔符。
  • domainName:网站域名,经DNS分析后会得到详细服务器IP。
  • /path:哀求路径,代表客户端哀求的资源地点位置,差异层级目次之间用/区分。
  • ?query1=value:哀求参数,?背面表现哀求的参数,采取K-V键值对情势。
  • &query2=value:多个哀求参数,差异的参数之间用&分割。
  • #fragment:表现所定位资源的一个锚点,欣赏器可根据这个锚点跳转对应的资源位置。
网络历程会根据URL的结构对目标URL举行分析,其中有两个关键信息:

  • 起首会分析得到协议名,比方http、https,这关乎到后续默认使用的端标语。
  • 然后会分析得到域名,这个将关乎到后续详细哀求的服务器地点。
假设欣赏器传输过来的URL为https://juejin.cn/user/862486453028888/posts,那么在这个阶段会确定后续哀求的服务器端标语为443,哀求的目标域名为www.juejin.cn。其着实这里告急是根据欣赏器的输入信息,去分析出一些“诞生我(哀求)”的前置要素。
2.2、“我”该去往的详细位置 - DNS域名分析

   在上个阶段已经大概知道“我”该去往那边啦!但我详细地点该到那里呢?“我”好像不大清楚,要不找个人问问吧^_^。我记得好像有个叫做DNS的“各人属”是专门负责这个的!我要去找它们问问看~

6.png    
不过在问DNS之前,我先来看看当地有没有域名与IP的映射缓存,好像没有~,那我只能去找DNS了(-_-),我起首找到了「当地DNS大叔」,把我要查找的域名交给了它,它让我稍等半晌,它给我找一下,让我们一起来看看「当地DNS大叔」是怎么查找的:

  • ①起首「当地DNS大叔」找了它的「根DNS族长」,族长告诉它应该去找「顶级DNS长老」。
  • ②「当地DNS大叔」根据族长的表现去找了「顶级DNS长老」,然而长老又告诉它应该去找「授权DNS执事」。
  • ③「当地DNS大叔」又根据长老的表现找到了「授权DNS执事」,终极在「授权DNS执事」那里查到了我手里域名对应着的详细IP地点。
  • ④「当地DNS大叔」拿着从「授权DNS执事」那里查到的IP,终极把它交给了我,为了下次不贫困大叔,以是我获取了IP后,将其缓存在了当地。
呼~,我终于知道我该去哪儿啦!准备出发咯!
更为详细且专业性的查询过程请参考:《HTTP/HTTPS-DNS域名分析体系》。
2.3、确保路途安全 - TCP与TLS握手

   问过DNS大叔后,得到了目标地点的我,此时已经知道该去往那边啦!但在正式出发前,由于前路崎岖,途中会存在各类危急(网络壅闭、网络延长、第三方挟制等),因此为了我的安全出行,起首还需为我建立一条安全的通道,以是我还必要等一会儿才气出发,俺们一起来瞅瞅建立安全通道的过程是什么样的:

7.png    
看着好复杂啊~,但好像大要就分为了两个过程:
起首是TCP的三次握手过程,听说这个阶段是为了确保目标地能够正常吸收我、也是为了给我建立出一条可靠的出行通道、而且为我盘算一下出行失败之后多久重新出发的时间等目标(也就是为了测试双方是否能正常通讯、建立可靠连接以及推测超时时间等)。
其实按照之前的“交通规则”,在建立好TCP连接之后,我就可以继承走下一步啦,但如今有许多暴徒,在我们出行的蹊径上挟制我们,然后偷取、窜改俺们携带的数据,以是如今出行变得很不安全,因此还必要还必要建立一条安全的出行通道,就是TLS大叔的安全连接~(HTTP+TLS=HTTPS):
TLS握手阶段,在这个阶段中,TLS大叔为了俺的安全出行,会通过许多本事:非对称加密、对称加密、第三方授权等,先和俺的目标地交换一个密钥,然后再通过这个密钥对我加密一下,确保我被暴徒抓到了也无法得到俺护送的数据^_^!
详细且专业性的过程请参考之前的:《计网底子TCP/IP综述-TCP三次握手》、《全解HTTP/HTTPS-SLL、TLS详解》。
2.4、诞生“我的身材” - 构建哀求报文

   履历上述过程后,安全的出行蹊径已经建立好啦!但如今的我还不算完备,以是必要先构建一个“身材”,也就是HTTP哀求报文:

   
“我的身材”告急由哀求行、哀求头、空行以及哀求主体四部分构成,内里包罗了“我本次出远门的必要护送的数据和一些其他信息”。同时,为了我能够在“出行的蹊径上(传输介质)”安全且正常传输,我还必要颠末层层封装:
   
起首为了确保俺护送的数据安全,TLS大叔会先对我的数据举行一次加密,把我原来携带的明文数据变化为看都看不懂的密文,雷同下面这个样子:

颠末加密后的我会紧接着来到传输层,传输层会在我的脑壳上再贴上一个传输头,如果是TCP年老的话,它会给我贴上一个TCP头,但如果传输层的UDP年老在的话,它给我贴的就是UDP头。但不管是谁贴的,在这个传输头内,为了防止我迷路和走丢,TCP、UDP两位年老哥都会仔细的在内里写清楚“我来自那里,该去往那边”,也就是源地点和目标地点:

11.png
偷偷吐槽一句:TCP年老贴的传输头内里,放了许多多少许多多少东西,让我感觉脑壳沉沉的。
过了传输层这一站之后,我又来到了网络层,果不其然,网络层内里最常见的照旧IP大叔,IP大叔看到我之后,又在我的脑壳上贴上了一个网络头,也就是给我又加了一个IP头。
哒哒哒~,我出了网络层这关之后,又来到了数据链路层,这关则是由台甫鼎鼎的“以太网家属”驻守,在这里我和之前两关差异,除开在我脑壳上贴了一个链路头之外,还给我在尾巴上多加了一个链路尾。
不过刚刚出链路层的时间,好像有个人跟我说:你这个样子是无法在介质上行走的,你要记得改变一下啊!
我还没听的太清楚,就来到了物理层这关,这层和之前我“家里”以及之前的关卡环境都不一样,物理层的小搭档们好像都有实际的形态,但之前打仗全部内容都是假造的概念形态哎~。
在我对比物理层年老们的异样差距时,一不愣神发现我的身材好像发生了“翻天覆地”的变化,整个我好像都变为了0、1构成了,正当烦闷时,物理层的某个年老哥告诉我说:“只有变成如许子,你才可以在出行的蹊径上行走哈,以是我们给你转换了一下形态,你如今已经可以出发了”。
原来是如许呀,好像链路层的时间有人跟我说过哎~
同样对于更为专业、详细的过程可参考之前的:《HTTP/HTTPS-HTTP报文构成》、《计网底子之TCP/IP-网络分层模子》等内容。
2.5、踏上路途的我 - 数据传输

   GO~GO~GO~,终于出发啦!我终于踏上了网络之旅!呼呼呼~

12.png    
咔!我来到了第一个中转站,听别人说,好像它的名字叫做路由器,起首路由器年老把我的身材按照之前封装的步调层层解封了,但解封到传输层的时间,看到了我脑壳上的传输头,好像路由器年老发现了TCP哥哥写的目标地点,发现我的目标地还在更远的位置,然后路由器年老又按照原来的步调把我的身材封装归去了,然后还密切的给我指出了接下来该往那条路走,我又该继承前行啦....
我一边走着,一边在思考:好像路由器年老就是负责给俺们指路的,防止俺们走丢~
详细可参考:《TCP/IP-IP寻址与路由控制》
三、“我”在后端服务器中多姿多彩的历程

   啊!路途好迢遥呀,我一起走了很久很久,也遇到了许多许多的中转站,每次当我不知道怎么走时,路由器年老都会温馨的给我指出接下来该走的路途。期间我也走过许多许多路,曾踩着双绞铜线、同轴电缆、光纤前行,固然,可不要鄙视俺,就算没有物理连接的环境下,我也可以通过无线电技能,通过氛围前行呢!
再次声明,文中所谓的蹊径,就是指数据传输的介质。
3.1、东跑西颠的履历 - 接入层转发

   走着走着,忽然火线遇到一个叫做CDN的老爷爷,它问我说要去那里,我说要去xx地方服务,平和的CDN老爷爷跟我说,我来看看我这里有没有你要的东西,如果有的话,就不消贫困你这个小家伙不停跑下去了。但是很遗憾,CDN老爷爷说它哪儿没有我要的东西,因此我只能继承前行下去。
   记不清过了多久,一起跌跌撞撞,在迷暗昧糊中我来到了一个地方,但当我还在分辨时,刷的一下,很快啊,我就被丢到了其他地方,当我转头看的时间,发现刚刚哪个地方,大写着LVS
LVS一样平常会作为大型网站的网关接入层,负责提供更高的并发性能,详细可参考《亿级流量架构计划-LVS篇》。
再直视火线,火线有一个东西很眼熟,难道这就是当初听说过的服务器吗?带着一脸疑惑的我逐步走了进去,我发现内部空间很大,上面漂泊着一块大陆,名为Linux大陆,上面有许多多少许多多少的“都会(历程)”林立着,那我该去哪一座呢?让我想想!
对了,记起来了好像!!其时出门的时间有人跟我说过:如果你到了目标地之后,不知道该找谁,那么可以根据默认的编号(端标语)去找!
让我追念一下,HTTP的默认端口是80,HTTPS的默认端口是443,我现在属于HTTPS流派的哀求,那么我应该去找编号为443的都会!出发出发~
顺着我的推理,我来到了编号443都会的城门口,当我迈进城门后,嗖的一下,我被一个叫做Nginx的大叔抓了已往....

  • Nginx:小家伙,你是来干嘛的?
  • :我带了一些数据过来找地点为IP:443的地方服务!
  • Nginx:噢~,原来是如许啊,我就是负责监听443编号的守门将。
  • Nginx:小家伙,你过来让我看看....
话音刚落,Nginx三下五除二的就把我的身材拆开了,然后得到了HTTP报文,然后从HTTP报文的哀求行中,发现了我本次旅途的详细目标:/user/862486453028888/posts,然后Nginx大叔又把我组装了归去,然后根据它内部设置的规则,然后道:

  • Nginx:小家伙,我刚才看了一下,你应该要去的详细位置是xxx.xxx.xxx.xxx:xx,快去吧。
  • :你怎么知道我要去的是这里?
  • Nginx:我刚刚看了一下,你要去的详细位置为IP:443/user/....,根据现在的规则以及我署理的地点,你就应该去这里!
  • :大叔大叔,给我看看你署理了那些地点呗。
  • Nginx:你可以过来看看。
  • :哇,为什么这么多!我可不可以去找其他的地点,找其他人帮我服务呀?
  • Nginx:不可以噢!按照规则的话,你就应该去我给你的地点哈。
  • :好吧,那我去啦!
这里的规则是什么呢?其实就是Nginx的location路由匹配规则、upstream署理集群列表以及负载平衡算法,详细可参考:《Nginx篇:反向署理与负载平衡》、《负载平衡算法原理篇》。
顺着Nginx大叔给的地点,我又来到了别的一台服务器,上面同样有一块Linux大陆,然后根据地点在上面找到了一个名为Gateway的东东,听它本身先容,好像属于体系网关。但当我找它服务时,它却跟我说:“我不负责详细的业务处置处罚,根据你的目标/user/....,你应该去找Nacos注册局,问它们要一下USER-SERVICE的详细地点,以是,小家伙你还得继承奔忙哦”!
好的好的,感谢Gateway叔叔指路,那我如今就去啦!
哒哒哒~,迈着舒畅的步伐我来到了Nacos注册局,然后将Gateway叔叔给我的名字:USER-SERVICE交给了它们的工作人员,它们的工作人员颠末一番查询之后告诉我,这个“品牌”多有个分部,你可以去其中恣意一处分部处置处罚你的任务,你可以去:xxx.xxx.xxx.xxx:8080这个地点噢!
这里的“品牌”是指后端的详细服务,分部是指服务集群中的每个节点。
好的好的,那我就去你说的这个xxx.xxx.xxx.xxx:8080地点啦!
我一边在路上走着,一边想了一下刚刚过程发生的事故,然后把这个履历画成了一副逻辑图,如下:

13.png    
归去的时间我肯定要跟小搭档们分享一下这个风趣的履历,耶!
3.2、我遇到了一只大猫咪-叫作Tomcat

   根据Nacos给我的地点,我又来到了一台新的服务器眼前,我记得Nacos给了我一个端标语,要我来到这里之后找编号为8080的位置,我顺着这个编号逐步找着,忽然在我的火线,出现了一只大老虎,哦不,应该是一只大猫咪,它长这个样子:

14.png    
它的长相好像有些报看,但在它的脑门上恰好写着我要找到8080地点,那我要找的应该就是它了吧!终于到了!我逐步靠近了这只大猫咪,然后跟它说要找它服务,Tomcat说要看看我的数据,然后又把我的身材按照之前封装的方式逆向拆开了,从而还原了我最初的身材-HTTP哀求报文,末了Tomcat说:“我确实是你本次要找的终极目标,不过要办你这件事故得到我肚子内里去噢”!
说罢,Tomcat伸开了它的血盆大口,一口将我吞了下去.....,正当我以为我完蛋的时间,我却发现Tomcat内部别有乾坤,上面好像也有一块小陆地漂泊着,当我凑近的时间才看清楚,原来上面写的是JVM呀!
我二话不说,一脚踏上了这块陆地,正当我看着上面密密麻麻的“屋子(Java方法)”迷茫时,此时我正火线就走来了一个人,然后对我做了一个自我先容:
来自远方的尊敬客人,您好呀,欢迎光临JVM神州,我叫Thread-xxx,是线程家属的一员,您接下来的整个旅途,我终将伴随在您左右,您必要办的全部事故,都会由我代庖,客长这边请(45度鞠身)~
然后我一边走着,一边跟Thread-xxx聊着:

  • :为什么是你来接我呀?
  • 线程:由于每位从远方到来的客人,我们线程家属都会调派一位子弟欢迎。
  • 线程:本次轮到我了,因而由我为您本次的旅途提供服务。
  • :噢噢噢,那我们接下来该去哪儿呢?
  • 线程:这必要看客长您本次的目标啦!可以让我看看您本次的旅程吗?
  • :可以呀,看吧,[我将哀求哀求行中的资源地点摆了出来]。
  • 线程:/user/....,原来您是要去这里呀,这边请~。
  • 线程:我们起告急去找DispatcherServlet服务处,才气继承前行。
PS:接下来是陈诉Java-SpringMVC框架的实行过程,非Java开辟可忽略细节。
随着Thread-xxx的步伐,我们找到了线程口中所说的DispatcherServlet服务处,该服务处的工作人员起首看了一下我本次的详细目标地(资源地点),然后说:您必要先去问一下HandlerMapping管理局,让它给你找一下详细负责这块业务的工作室。
紧接着线程Thread-xxx又带我来到了HandlerMapping管理局找到了其中的管理人员,该管理人员让我先把要找的资源位置给它,然后只见它拿着我的目标地点作为条件,然后输入进了查询器,一刹时便查出来了我本次的终极目标地:UserController工作室!
线程Thread-xxx道:这就是负责您本次任务的终极工作室啦!我这就带您已往。
这其实本质上就是SpringMVC中,哀求定位详细Java方法的逻辑,但由于之前没出过《SpringMVC的原理篇》,因此接下来从专业性的角度简单叙述一下SpringMVC的核心原理。
先上一张SpringMVC的原理图:

   
观察如上流程图,其实看起来难免有些生涩,那如今咱们换成简单一点的方式叙述,不再通过这种源码性的流程去明白。
不知诸位是否还记得,最开始学习SpringMVC时的设置过程,接下来我们简单回想一下:
①设置springmvc-servlet.xml文件:
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-23 00:29, Processed in 0.201431 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表