随着写的WEB程序越来越多,项目的部署也越来越繁琐,对于一些线上问题总是搞不清楚是哪个环节出的问题,归根结底是对整个流程的不熟悉导致,所以分析下一个WEB请求从用户输入地址到页面出来到底经历过多少东西.
首先把URL分割为几个部分,以地址http://mrdear.cn/2017/04/15/动漫推荐/
为例
协议: http
网址: mrdear.cn
资源路径: 2017/04/15/动漫推荐/
浏览器拿到地址后会对其中非ASCII码的Unicode字符解析,比如空格会变成%20,汉字也会变成其16进制对应的编码值,如下例子:
上面链接等价于
http://mrdear.cn/2017/04/15/%E5%8A%A8%E6%BC%AB/%E5%8A%A8%E6%BC%AB%E6%8E%A8%E8%8D%90/
中间还有其他很复杂的流程,比如参数,协议,请求头,请求体等建立.
对于网址mrdear.cn,浏览器并不知道他所处的服务器位置,因此需要解析出其服务器ip,这个过程就是DNS域名解析.
chrome://net-internals/#dns
即可看到缓存列表.该缓存通常几分钟到几小时不等,存在的话就直接返回,否则下一步/etc/resolv.conf
中,可以使用nslookup或者dig查
看解析过程.
服务器以nginx+tomcat为例,经过以上步骤后请求到达了nginx,nginx对URL进行分析,验证其所在机器上有所需要的服务,并且用户是有权限调用的,决定该URL由哪一个tomcat服务处理,捕获处理结果,返回给请求者,最后四次挥手结束请求.到此完成浏览器,服务端的通信.
浏览器拿到了服务器的返回信息后会对内容进行解析,展现成用户所需要的内容,如html,pdf等.
那么整个过程总结来看就是 用户输入URL -> 浏览器解析地址 -> DNS查找域名对应ip -> 服务器响应 ->浏览器拿到响应渲染.
CDN又叫内容分布网络,一般用于静态资源如html,css,js的存储,简单的理解为一张大网,网上每一个节点都有着很多资源.那么每一个用户想要访问的时候就会去找离他最近的节点上面获取需要的内容.从而加快了网站整体访问速度. 举个例子:用户访问taobao的某css文件,首先浏览器会发送请求 -> DNS解析域名,这里一般会有一个DNS负载均衡服务器,其得到最适合用户的CDN节点ip -> 用户拿到CDN节点ip得到资源.
了解了DNS的解析是一个递归过程,找到域名对应的ip就返回,如果有人手动修改了该条映射信息,那么就会返回到错误的ip地址,这种行为也叫DNS劫持,对于客户端来说,没有很好地方式能认为服务器返回的信息是可靠的,也就是不可靠的HTTP通信,所以也就导致了这一层的攻击漏洞,而这种事一般是天朝的电信运营商能干得出来,所以选择一个靠谱的DNS是非常重要,推荐114.114.114.114
应对HTTP的不可靠通信,所以诞生了HTTPS,即HTTP over SSL,使用SSL/TLS对HTTP的内容进行加密解密.整个流程如下图:
流程清晰后乱码问题就很好解决了,把浏览器,Nginx,Tomcat等都当成水池的话,数据的乱码只能在每一个的入口端和出口端.如果发生了乱码,那么首先定位到是哪一个口产生了乱码,然后再去找原因,一般都能解决. 以JavaWEB应用为例,乱码主要发生在IO交互的过程中.其一浏览器与服务器建立socket连接,浏览器对URL以及request转换编码.请求到达tomcat,tomcat会对其进行解码,这个解码可在tomcat目录下的conf/server.xml中配置URIEncoding
<connector port=”8080″ protocol=”HTTP/1.1″ maxThreads=”150″ connectionTimeout=”200000″
redirecPort=”8443″ URIEncoding=”utf-8″/>
这里要保证不乱码,下一步tomcat建立了ServletRequest和ServletResponse,那么这里也有编码,一般是post表单或者request body乱码,那么就需要指定ServletRequest和ServletResponse的编码格式
request.setCharacterEncoding(encoding);//设置请求信息编码
response.setCharacterEncoding(encoding);//设置返回信息编码
Java程序在处理请求时和操作系统会有IO通信,和数据库会有IO通信,整个过程也会涉及编码,这种一般代码中会自动控制,出问题几率不大.
浏览器拿到返回信息后对页面进行渲染,这一步也会有编码,这个一般手动指定下浏览器的渲染编码,比如Content-Type: text/html;charset=UTF-8
,指定以UTF-8渲染该text/html返回.
域名解析记录主要分为:A 记录、MX记录、CNAME 记录、NS记录和 TXT记录
mrdear.cn
是使用CNAME解析到nl101531.github.io
的,二级域名oj.mrdear.cn
和md.mrdear.cn
都是使用A记录解析到对应主机的ip地址,到达主机后再使用Nginx进行不同的服务器转发.
个人总结,如有错误请指出,以免误人子弟.
window.disqusProxy={shortname:"mrdear",username:"屈定",server:"disqus.ifreehub.cn",port:443,adminAvatar:"/avatars/admin-avatar.jpg",identifier:"2017/04/30/运维/对一个WEB请求的理解/"},window.disqus_config=function(){this.page.url=window.location.href,this.page.identifier=window.disqusProxy.identifier}