1.写在前面
今天我们来聊聊HTTP协议,今天打算从应用的场景来一步步的推出HTTP的协议。不再像别的一样,讲HTTP的协议头,请求的地址等等!既枯燥,又无趣。
2.浏览器发起HTTP请求的例子
用户在浏览器中输入URL的时候,浏览器直接联想我们输入的URL,因为我们浏览过的URL都会存入到浏览器的数据库中,这个时候当我们的URL输入完整的时候,按下回车的时候,这个时候浏览器通过渲染引擎,发起第一个请求,通过网络模块,然后如果返回的时候,这个时候发现有对应的JS,然后通过JS解释器来执行解析执行对应的JS,当整个页面的数据都请求完成后,然后绘制好完整的页面。
上图就是我们在谷歌浏览器中发起的一个请求,请求的是CSDN的博客的地址,可以发现走来请求的就是CSDN的官网的地址,然后后面加载的很多的其他的资源,比如说JS、图片等等。最后我们可以看下如下的图:
浏览器发起请求,现请求page.html,然后响应给浏览器,浏览器去解析,然后发现少一些资源,图片,JS脚本,视频,这个时候浏览器会继续去请求这些内容,最后全部请求完成后,再将页面进行更新。
最后我们再通过一个时序图,将浏览器背后请求服务器的逻辑讲一下,具体的如下:
上面请求的具体的步骤如下:
- 从URL中解析出域名,同时服务器也会监听对应的端口(80,443)
- 根据域名查询DNS,DNS服务器会返回对应的域名的IP地址。
- 浏览器和对应IP地址的服务器三次握手建立TCP连接,同时如果是HTTPS,会完成TLS/SSL握手
- 浏览器构造HTTP请求,填充上下文至HTTP头部,然后发起对应的HTTP请求
- 服务器响应完,浏览器接收到携带HTML页面作为包体的HTTP响应
- 浏览器引擎解析响应,渲染包体至用户界面,根据超链接构造其他HTTP请求
- 浏览器发送获取页面内资源的HTTP请求。
最后HTTP协议的定义是什么呢?
HTTP协议一种无状态的、应用层的、以请求/应答方式运行的协议,它使用扩展的语义和自描述消息格式,与基于网络的超文本信息系统灵活的互动。
要抓住几个关键字:
- 无状态:两个连续的请求中,后一个请求不能依赖前一个的请求中相应的字段。
- 请求/应答:一定是一个连接,首先有客户端发起请求,服务端进行响应的模式。
- 扩展的语义:老的服务器只支持HTTP 1.0的协议,那么新的浏览器是HTTP1.1的协议,两者之间仍然是可以通信的。
- 自描述的消息:从一个请求中,我们就知道是文本,还是图片,还是视频。
- 超文本系统:支持不单单是文档,还有就是图片,视频,音频等等。
3.基于ABNF的HTTP协议的格式
ABNF:扩充巴科斯-瑙尔范式操作符
- 空白字符:用来分隔定义中的各个元素
- 选择/:表示多个规则都是可供选择的规则 start-line = request-line/status-line
- 值范围 %c##-## OCTAL = “0” / “1”/ “2” / “3”/“4” / “5”/ “6” / "7"与OCTAL = %x30-x37等价
- 序列组合():将规则组合起来,视为单个元素
- 不定量重复m*n:*元素表示零个或更多元素*(header-field CRLF) 1*元素表示一个或更多的元素,2*4元素表示两个至四个元素
- 可选序列[]:[message-body]
核心规则:
规则 | 形式定义 | 意义 |
---|
ALPHA | %41-5A / %x61-7A | 大写和小写ASCII字母(A-Z,a-z) | DIGIT | %x30-39 | 数字(0-9) | HEXDIG | DIGIT/“A”/“B”/“C”/“D”/“E”/“G” | 十六进制数字(0-9,a-f,A-F) | DQUOTE | %x22 | 双引号 | SP | %x20 | 空格 | HTAB | %x09 | 横向制表符 | WSP | SP/HTAB | 空格或横向制表符 | LWSP | *(WSP / CRLF WSP) | 执行空白(晚于换行) | VCHAR | %x21-7E | 可见(打印)字符 | CHAR | %x01-7F | 任何7-位US-ASCII字符,不包括NUL(%x00) | OCTET | %x00-FF | 8位数据 | CTL | %x00-1F / %x7F | 控制字符 | CR | %x0D | 回车 | LF | %x0A | 换行 | CRLF | CR LF | 互联网标准换行 | BIT | “0” / “F” | 二进制数字 |
看完了ABNF的核心的规则后,我们来看下基于ABNF描述的HTTP的协议格式,具体的如下:
HTTP-message = start-line *(header-field CRLF) CRLF [message-body]
start-line = request-line / status-line
request-line = method SP request-target SP HTTP-version CRLF
status-line = HTTP-version SP status-code SP reason-phrase CRLF
header-field = field-name ":" OWS field-value OWS
OWS = *(SP / HTAB)
field-name = token
field-value = *(field-conent / obs-fold)
message-body = *OCTET
我们通过telnet 命令,来查看对应的http-message ,具体的如下:
可以看到我们的http-message 和ABNF 定义的HTTP格式是一样的,但是我们的换行是看不见,那么我们有没有什么办法可以获取到呢?我们可以使用wireshark 抓包工具来看到,具体的如下:
这样我们就可以看到我们不可见的编码了。
4.网络为什么要分层:OSI模型和TCP-IP模型
我们先来看下OSI的七层的概念模型,具体的如下:
应用层:解决的是我们的业务的问题
表示层:负责将网络中的消息转换成用户可以读取的消息
会话层:建立会话,握手等等
传输层:解决进程和进程之间的通信问题
网络层:从一个主机上将报文发送到另一个主机上
数据链路层:使用MAC地址连接到相应的交换机,路由器。
物理层:物理介质
OSI模型与TCP/IP模型的对照:
分层的好处:相互不影响
分层的坏处:分的层数多,数据延迟比较大,性能不够好。
报文头部:
物理层:传输的是Bit
数据链路层:传输的是Frame
网络层:传输的是Packet
5.HTTP协议解决了什么问题?
HTTP协议为什么是现在这个样子?
HTTP主要作者:Roy Thomas Fielding Rest架构作者
URI:统一资源标识符
解决人与机器交流的问题
解决WWW信息交互必须面对的需求:
- 低门槛
- 可扩展性:巨大的用户群体,超长的寿命
- 分布式系统的Hypermedia:大粒度数据的网络传输
- internet规模 无法控制的scalability 不可预测的负载、恶意消息 客户端不能保持所有服务器信息,服务器不能保持多个请求间的状态信息。 独立的组件部署:新老组件并存
- 向前兼容:自1993年起HTTP0.9、1.0(1996)已经被广泛使用
6.评估Web架构的关键属性
HTTP协议应当在以下属性中取得可接受的均衡:
- 性能Performance:影响高可用的关键因素
- 可伸缩性Scalability:支持部署可以互相交互的大量组件
- 简单性Simplicity:易理解、易实现、易验证
- 可见性Visiable:对两个组件间的交互进行监视或者仲裁的能力。如缓存、分层设计等
- 可移植性Portability:在不同的环境下运行的能力
- 可靠性Reliability:出现部分故障时,对整体影响的程度
- 可修改性Modifiability:对系统做出修改的难易程度,由可进化性、可定制性、可扩展性、可配置性、可重用性构成。
我们再来更细化的分析:
性能:
- 网络性能 Network Performance Throughput 吞吐量 小于等于带宽 bandwidth。Overhead 开销:首次开销,每次开销
- 用户感知到的性能 Use-perceived Performance 延迟Latency:发起请求到接收到响应的时间 Completion 完成时间:完成一个应用动作所花费的时间
- 网络效率 Network Efficiency 重用缓存、减少交互次数、数据传输距离更近、COD
可修改性:
- 可进化性 Evolvability:一个组件独立升级而不影响其他组件
- 可扩展性 Extensibility:向系统添加功能,而不会影响到系统的其他部分
- 可定制性 Customizability:临时性、定制性地更改某一要素来提供服务,不对常规客户产生影响
- 可配置性 Configurability:应用部署后可通过修改配置提供新的功能。
- 可重用性Reusabilit:组件可以不做修改在其他应用中使用
REST架构下的WEB
7.从五种架构风格推导出REST架构
5中架构风格
- 数据流风格 Data-flow Styles 优点:简单性、可进化性、可扩展性、可配置性、可重用性。
- 复制风格 Replication Styles 优点:用户可觉察的性能、可伸缩性、网络效率、可靠性也可以得到提升。
- 分层风格 Hierarchical Styles 优点:简单性、可进化性、可伸缩性。
- 移动代码风格 Mobile Code Styles 优点:可移植性、可扩展性、网络效率。
- 点对点风格 Peer-to-Peer Styles 优点:可进化性、可重用性、可扩展性、可配置性。
数据流风格 Data-flow Styles
复制风格 Replication Styles
分层风格 Hierarchical Styles
-
客户端服务器Client-Server,CS 由Client触发请求,Server监听到请求后产生响应,Client一直等待收到响应后,会话结束。分离关注点隐藏细节,良好的简单性、可伸缩性、可进化性。 -
分层系统 Layered System,LS 每一层为其之上层的服务,并使用在其之下层的所提供的的服务,例如TCP/IP -
分层客户端服务器 Layered Client-Server,LCS LS+CS,例如正向代理和反向代理,从空间上分为外部层与内部层。 -
无状态、客户端服务器 Client-Stateless-Server CSS 基于CS,服务器上不允许有session state会话状态 提升了可见性、可伸缩性、可靠性。但重复数据导致降低网络性能。 -
缓存、无状态、客户端服务器Client-Cache-Stateless-Server C$SS 提升性能 -
分层、缓存、无状态、客户端服务器Layered-Client-Cache-Stateless-Server LC$SS -
远程会话 Remote Session,RS CS变体,服务器保存Application state应用状态 可伸缩性,可见性差 -
远程数据访问Remote Data Access ,RDA CS变体,Application state应用状态同时分布在客户端与服务端 巨大的数据集有可能通过迭代而减少 简单性、可伸缩性差。
移动代码风格 Mobile Code Styles
-
虚拟机 Virtual Machine,VM 分离指令与实现 -
远程求值Remote Evaluation,REV 基于CS的VM,将代码发送至服务器执行。 -
按需代码 Code On Demand, COD 服务器在响应中发回处理代码,在客户端执行 优秀的可扩展性和可配置性,提升用户可察觉性能和网络效率 -
分层、按需代码、缓存、无状态、客户端服务器Layered-Code-On-Demand-Client-Cache-Stateless-Server LCODC$SS -
移动代理 Mobile Agent ,MA 相当于REV+COD
点对点风格 Peer-to-Peer Styles
- Event-based Integration,EBI:基于事件集成系统,如由类似Kafka这样的消息系统+分发订阅来消除耦合 优秀的可重用性、可扩展性、可进化性 缺乏可理解性 由于消息广播等因素造成的消息风暴,可伸缩性差
- Chiron-2,C2 相当于EBI+LCS,控制了消息的方向。
- Distributed Objects ,DO 组件结对交互
- Brokered Distributed Objects, BDO 引入名字解析组件来简化DO,例如CORBA
8.写在最后
由于文章的篇幅的问题,我们这儿只简单的介绍了一下HTTP的协议,后面会继续介绍剩余的内容。
|