请求从客户端到服务器的过程简单分析

本文详细剖析了HTTP请求从客户端发起,经过网络传输,到服务器接收处理,最终返回响应的全过程,涵盖了TCP连接建立、HTTP报文结构、DNS解析、TLS加密等关键步骤。
摘要由CSDN通过智能技术生成
当我们在客户端(以浏览器为例)使用域名发送一个HTTP请求的时候,DNS协议会尝试将域名解析为对应的IP。(我们知道每一个台服务器都可以通过ip和端口直接被访问。但是,用户对于由数字组成的ip是很难有记忆点的,所以就出现了域名,域名可以映射到ip。那么域名是如何与ip进行映射的,就需要DNS协议的帮忙
 
1.OS会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。
 
Linux下默认hosts文件位置是/etc/hosts
 
Windows下默认是c:\windows\system32\drivers\etc\hosts
 
2.如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。
 
3.如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,会在本地DNS服务器查询,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。
 
在Linux下,DNS客户机配置文件为/etc/resolv.conf
 
Linux下的DNS服务器在进行DNS解析的时候,默认的解析超时时间是5秒,默认的重试次数是两次。我们可以看到,当DNS解析慢的时候,我们可能在DNS解析的过程中发费10秒钟,这在有些时候是很致命的。
 
在我们使用HttpCient等工具请求第三方接口(比如百度的定位接口)的时候,会出现超时非常严重的情况,我们在排查的时候发现我们已经设置各种超时时间,读超时,链接超时等等,但是还是出现了超时很严重的情况,这是为什么呢,因为HttpClient并没有提供一个线程运行总时长的超时时间配置,这导致了DNS解析可能花了10秒才完成,导致了调用时间非常长。那么如何去解决DNS解析失败的问题呢?在使用OKHTTP时,我们可以使用HTTPDNS来解决,这样就会变成IP直连,省去了DNS解析的步骤,但是这样会有一个问题,就是当你变成了IP直连的时候,连接无法复用了,这个时候是有问题的,但是好在OKHTTP在底层帮我们实现了链接复用。而对于HTTPClient,也可以使用HTTPDNS解决DNS解析失败,但是是否会帮我们实现链接复用,还没有测试过。
 
在Windows下,DNS的配置就不多说了。在“控制面板”-“网络”中配置。
 
4.如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。
 
5、如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至13台根DNS,根DNS服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(qq.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找qq.com域服务器,重复上面的动作,进行查询,直至找到www.qq.com主机。
 
6、如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环。不管是本地DNS服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。
 
从客户端到本地DNS服务器是属于递归查询,而DNS服务器之间的交互查询就是迭代查询。
 
而在如今的后端架构中,要做到高可用,服务器都是多个节点的。通过DNS解析出来的IP其实一般都不是服务器的IP,而是反向代理服务器的IP,当前求到达反向代理服务器的时候,反向代理服务器会根据负载均衡策略将请求分发到相应的服务器上。
 
但是随之有一个问题,如果代理服务器挂掉了,那么就会导致所有的请求都到不了服务器,所以我们要做到代理服务器的高可用。而要做到代理服务器高可用,对于我们常用的代理服务器NG来说,我们可以采用keepalived结合NG来做到高可用。
 
keepalived分别安装在主机A和备机B上,双方启动以后,主机A就会向局域网内发送arp响应包,该arp响应包的ip地址被设为vip,mac地址被设为macA,所有接收到此报文的电脑就会将这个对应关系写入自己的ARP缓存表中,下次访问vip时,就会根据对应的mac地址访问到主机A当备机B监听到主机A挂了的时候,就会向局域网内发送arp响应包,并将arp响应包的ip地址设为vip,mac地址设为macB,所有接收的此报文的电脑就会将这个对应关系写入自己的ARP缓存表中,下次访问vip时,就会根据对应的mac地址访问到备机B这样就实现了高可用。
 
从上述分析中,我们可以得知,一个客户端请求要到达服务器,可能会经过层层转发,那么就会有一个问题,我们要怎么去获取用户的真实IP呢?
 
在业界中,我们会使用X-Forwarded-For这个请求头来帮助我们获取到客户端真实IP.它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入RFC 7239(Forwarded HTTP Extension)标准之中。
 
请求头的格式如下
 
X-Forwarded-For: client, proxy1, proxy2
1
最开始的ip代表最远端的客户端IP,接下来依次是每层代理的IP。
当服务器要获取客户端真实IP的时候,我们只需要获取X-Forwarded-For的第一个IP即可。
 
一般代理服务器处理X-Forwarded-For这个请求头都是这样的。
 
获取上一层传递过来的X-Forwarded-For请求头
通过获取remote_addr获取上一层的真实ip,将上一层的真实ip加入到X-Forwarded-For请求头尾部,然后再将X-Forwarded-For请求体转发给下一层。
 
但是正因为这样的机制,导致了我们只要在客户端伪造X-Forwarded-For请求头,就会导致服务器拿不到正确的客户端IP。
 
我们要如何应对伪造X-Forwarded-For请求头的情况呢?
 
我们知道Remote Address是无法伪造的,这个IP一定是和目标主机完成TCP连接的地址。
因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求。在正常的TCP/IP通信中,是可以伪造数据包来源 IP 的,但这会让发送出去的数据包返回到伪造的IP上,无法实现正常的通信。所以我们可以说Remote Address一定是真实的。
 
因此,我们可以将首层代理将握手 IP 设置为 HTTP 请求头的 X-Real-IP(个人更建议是一个更生僻的请求头) 中向后传递。后面的每一层原样传递下去(有则原样传递,无则设置为握手 IP )
---------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值