简单概括就是:
- 域名解析成IP地址;
- 与目的主机进行TCP连接(三次握手);
- 发送与收取数据(浏览器与目的主机开始HTTP访问过程);
- 与目的主机断开TCP连接(四次挥手);
- 当访问网址(例如www.coder.com后,浏览器获得coder.com的IP地址并把缓存起来(发送一个UDP的包给DNS服务器,DNS服务器会返回coder.com的IP),方便下次加快访问。
- 可以通过chrome://net-internals/#dns来查看。
- 浏览器向IP地址发起HTTP请求,但是HTTP Request/Response必须在TCP这个“虚拟的连接”上来发送和接收。想要建立“虚拟的”TCP连接,TCP邮差需要知道4个东西:(本机IP, 本机端口,服务器IP, 服务器端口),现在只知道了本机IP,服务器IP, 两个端口怎么办?
本机端口很简单,操作系统可以给浏览器随机分配一个,服务器端口更简单,用的是一个“众所周知”的端口,HTTP服务就是80, 我们直接告诉TCP邮差就行。
经过三次握手以后,客户端和服务器端的TCP连接就建立起来了!终于可以发送HTTP请求了。
3. HTTP GET请求到达服务器端进行处理,这里以Nginx为例,Nginx接下来要判断,这是个静态的请求还是个动态的请求?
- 如果是静态的请求(HTML文件,JavaScript文件,CSS文件,图片等),也许自己就能搞定了(当然依赖于Nginx配置,可能转发到别的缓存服务器去),读取本机硬盘上的相关文件,直接返回。
- 如果是动态的请求,需要后端服务器(如Tomcat)处理以后才能返回,那就需要向Tomcat转发,如果后端的Tomcat还不止一个,那就需要按照某种策略选取一个。
Ngnix支持这么几种策略:
- 轮询:按照次序挨个向后端服务器转发
- 权重:给每个后端服务器指定一个权重,相当于向后端服务器转发的几率。
- ip_hash: 根据ip做一个hash操作,然后找个服务器转发,这样的话同一个客户端ip总是会转发到同一个后端服务器。
- fair:根据后端服务器的响应时间来分配请求,响应时间短的优先分配。
- Http Request 都会被Tomcat交给某个Servlet处理,这个Servlet又会把Http Request做转换,变成框架所使用的参数格式,然后分发给某个Controller(如果你是在用Spring)或者Action(如果你是在Struts)。
- Tomcat也可能为每个请求分配一个线程去处理,即通常所说的BIO模式(Blocking I/O 模式)。
- 也可能使用I/O多路复用技术,仅仅使用若干线程来处理所有请求,即NIO模式。
- Tomcat把Http Response发给了Ngnix,Ngnix把Http Response 发给了浏览器
发完以后TCP连接能关闭吗?
- 如果使用的是HTTP1.1, 这个连接默认是keep-alive,也就是说不能关闭;
- 如果是HTTP1.0,要看看之前的HTTP Request Header中有没有Connetion:keep-alive,如果有,那也不能关闭。
- 浏览器收到了Http Response,从其中读取了HTML页面,准备显示,HTML页面中可能引用了大量其他资源,例如js文件,CSS文件,图片等,这些资源也位于服务器端,并且可能位于另外一个域名下面,例如static.coder.com。浏览器没有办法,只好一个个地下载,从使用DNS获取IP开始,之前做过的事情还要再来一遍。不同之处在于不会再有应用服务器如Tomcat的介入了,收到全部的内容随后断开与该服务器之间的TCP连接。
参考文章:刘哥的码农翻身