HTTP协议
HTTP协议主要包括post请求和get请求
get是从服务器上获取数据,get方式提交的数据最多只能有1024字节,而post则没有此限制,get使用URL或Cookie传参。而post将数据放在BODY中。
post是向服务器传送数据,post比get安全,因为数据在地址栏上不可见。
get产生一个TCP数据包;post产生两个TCP数据包。
对于get方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于post,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)
缓存回退:get在浏览器回退时是无害的,而post会再次提交请求,get请求浏览器有缓存,回退时读取的是缓存中的数据。但是post没有浏览器缓存会再次发送请求,消耗服务器性能。
关于HTTP报文组成
请求报文: 有请求行,请求头, 空行,请求体
request
GET /mix/76.html?name=kelvin&password=123456 HTTP/1.1//请求类型 要访问的资源 协议版本 Host: www.fishbay.cn //目的地 主机域名 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 //客户端信息 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 //可以接受的数据类型 Accept-Encoding: gzip, deflate, sdch Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
响应报文: 有状态行,响应头,空行,响应体
response
HTTP/1.1 200 OK //版本号 状态码 状态消息 Server: nginx Date: Mon, 20 Feb 2017 09:13:59 GMT Content-Type: text/plain;charset=UTF-8 //body类型 Vary: Accept-Encoding Cache-Control: no-store //是否缓存
关于http1.0和http2.0之间的区别?
http1.0:无状态、无连接。
http1.1:持久连接,默认Connection:keep-alive,增加了host字段,增加了缓存处理:cache-control,根据客户端请求的先后顺序来返回相应的结果,以保证客户端能够区分每次请求的响应内容。
注意这里http的keep-alive和tcp中的keep-alive是有区别的:
HTTP协议的Keep-Alive意图在于TCP连接复用,当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。同一个连接上串行方式传递请求-响应数据;
TCP的Keepalive机制(保活探测)意图在于探测连接的对端是否存活。
http2.0:
1.引入二进制和流的概念,帧对数据进行顺序标识,浏览器接收到数据以后根据序列对数据进行合并,不会出现数据错乱的情况。因此有了序列,服务器可以并行的传输数据。
2.多路复用:
1、所有的HTTP2.0通信都在一个TCP连接上完成,这个连接可以承载任意数量的双向数据流。
2、每个数据流以消息的形式发送,而消息由一或多个帧组成。这些帧可以乱序发送,然后再根据每个帧头部的流标识符(stream id)重新组装。
举个例子,每个请求是一个数据流,数据流以消息的方式发送,而消息又分为多个帧,帧头部记录着stream id用来标识所属的数据流,不同属的帧可以在连接中随机混杂在一起。接收方可以根据stream id将帧再归属到各自不同的请求当中去。
3、另外,多路复用(连接共享)可能会导致关键请求被阻塞。HTTP2.0里每个数据流都可以设置优先级和依赖,优先级高的数据流会被服务器优先处理和返回给客户端,数据流还可以依赖其他的子数据流。
4、可见,HTTP2.0实现了真正的并行传输,它能够在一个TCP上进行任意数量HTTP请求。而这个强大的功能则是基于“二进制分帧”的特性。
3.头部压缩
在HTTP1.x中,头部元数据都是以纯文本的形式发送的,通常会给每个请求增加500~800字节的负荷。
HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。高效的压缩算法可以很大的压缩header,减少发送包的数量从而降低延迟。
4.服务器推送:
服务器除了对最初请求的响应外,服务器还可以额外的向客户端推送资源,而无需客户端明确的请求。
在浏览器输入url地址->显示主页的过程?
1.浏览器查找域名的ip地址(可以通过浏览器缓存,路由器缓存,DNS缓存)使用DNS协议获取域名对应的IP
2.浏览器向远程web服务器发送一个HTTP请求(cookie也会随着请求发送给服务端)(2-4的过程中,会使用TCP协议,与服务器建立TCP连接,建立TCP连接需要发送数据,发送数据在网络层使用IP协议
IP数据报在路由器之间,路由选择使用OPSF协议,路由器在与服务器通信时,需要将ip地址转换为MAC地址,使用ARP协议)
可能会有这个过程,服务器的永久重定向响应(从 http://example.com 到 http://www.example.com)
3.服务器处理请求,根据传过来的参数,cookie信息生成一个HTML响应
4.服务器发回一个HTML响应
5.浏览器解析并渲染页面(TCP建立以后,使用HTTP协议来访问网页)
6.连接结束
DNS解析的过程:
DNS是应用层协议,事实上他是为其他应用层协议工作的,包括不限于HTTP和SMTP以及FTP,用于将用户提供的主机名解析为ip地址。
具体过程如下:
- 用户主机上运行着DNS的客户端,就是我们的PC机或者手机客户端运行着DNS客户端了
- 浏览器将接收到的url中抽取出域名字段,就是访问的主机名,比如
http://www.baidu.com/, 并将这个主机名传送给DNS应用的客户端 - DNS客户机端向DNS服务器端发送一份查询报文,报文中包含着要访问的主机名字段(中间包括一些列缓存查询以及分布式DNS集群的工作)
- 该DNS客户机最终会收到一份回答报文,其中包含有该主机名对应的IP地址
- 一旦该浏览器收到来自DNS的IP地址,就可以向该IP地址定位的HTTP服务器发起TCP连接
常见的状态码:
1XX:接受的请求正在处理
2XX:请求正常处理完毕
3XX:重定向状态码
4XX:客户端错误,服务器无法处理请求
5XX:服务器错误,服务器处理请求出错
具体的:
200:服务器成功处理了请求,并且提供了请求的网页
201:请求成功并且服务器创建了新的资源,一般是数据库操作成功,新建修改
202: 服务器已接受请求,但尚未处理。(异步任务进入排队)
204:一般是删除数据成功。
300:(多种选择) 针对请求,服务器可执行多种操作。
301:(永久移动) 请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302:(临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来响应以后的请求。
304 :Not Modified 未修改,比如本地缓存的资源文件和服务器上比较时,发现并没有修改,服务器返回一个304状态码。说到304,那么就要说到浏览器缓存机制,包含强缓存和协商缓存,而304就是协商缓存,资源没有改变之后,服务端返回的状态码
303:See Other
该状态码表示由于请求对应的资源存在着另一个URI,应使用GET方法定向获取请求的资源,
303和302状态码有着相同的功能,但是303明确表示客户端应当采用get方法获取资源,这点与302状态码有区别。
比如,当使用post方法访问CGI程序,其执行后的处理结果为希望客户端能以get方法重定向到另一个uri上去时,返回303状态码。虽然302也可实现相同的功能,但这里使用302状态码是最理想的。
当301、302、303响应状态码返回时,几乎所有浏览器都会把post改成get,并删除请求报文内的主体,之后请求会自动再次发送。
301、302标准是禁止将post方法改变成get方法的,但实际使用时大家都会这么做。
307 Temporary Redirect
临时重定向。该状态码与302有相同的含义。尽管302标准禁止post变化get,但实际使用时大家不遵守。
307会遵照浏览器标准,不会从post变为get。但是对于处理响应时的行为,各种浏览器有可能出现不同的情况。
400:(错误请求) 服务器不理解请求的语法。
401:(未授权) 请求要求身份验证。对于登录后请求的网页,服务器可能返回此响应。
403:(禁止) 服务器拒绝请求。(偶然看到了这个报错403,是当时我们链接地址是https://www.ceshi.com; 但是却被谁谁谁配置成了http://www.ceshi.com;最后就会导致403的报错。解决办法:就是将http改成https。)
404:(未找到)
服务器找不到请求的网页。例如,对于服务器上不存在的网页经常会返回此代码。
408:(请求超时) 服务器等候请求时发生超时。
500:(服务器内部错误) 服务器遇到错误,无法完成请求。
额外补充:
RPC和Rest协议:
Rest:严格意义上说接口很规范,操作对象即为资源,对资源的四种操作(post、get、put、delete),并且参数都放在URL上,但是不严格的说Http+json、Http+xml,常见的http api都可以称为Rest接口。
RPC:我们常说的远程方法调用,就是像调用本地方法一样调用远程方法,通信协议大多采用二进制方式
RPC 框架的职责是: 让调用方感觉就像调用本地函数一样调用远端函数、让服务提供方感觉就像实现一个本地函数一样来实现服务
几种协议:
Socket使用时可以指定协议tcp,udp等;
RIM使用Jrmp协议,Jrmp又是基于TCP/IP;
RPC底层使用Socket接口,定义了一套远程调用方法;
HTTP是建立在TCP上,不是使用Socket接口,需要连接方主动发数据给服务器,服务器无法主动发数据个客户端;
幂等性好处:get,delete,put都符合幂等性
bool get_money(id, amount)
参数:
id:用户的账户
amount: 表示取多少钱
返回值:
true: 表示取钱成功
false: 表示取钱失败
情景一:
1、一位用户A 取100块钱, 这个请求,发送到了服务器
2、服务器正常的处理了这个请求,把用户A的总额,减去了100块钱, 这时,服务器把处理结果返回给客户端。
3、服务器把处理结果,返回给客户端,可是这时,由于网络不稳定, 导致客户端没有接受到服务器返回的处理结果,这时,用户(或者客户端)进行重试,同样的请求又到服务器,服务器又在用户A的总额中,减去了100块钱
用户A 取了100块钱, 银行却扣了 200
解决方案:
在调用接口的时候传入一个流水号:
bool get_money(id, amount, serial_number)
对于同一个操作(同一笔业务)流水号不变(在不同操作中,必须保证流水号的唯一性),
这时,如果服务器遇到上面那种情况,只需要判断客户端传过来的这个流水号,是否已经操作(处理)过了,如果已经处理过了,就直接把处理结果返回给客户端
这样,就不存在上面的问题了
幂等性并发问题:
在服务端,一般情况下,对于每次请求,我们都会把 请求方、流水号、处理结果 存储在数据库中
如:
流水号 请求方 处理结果
20160311xxxx jiangxi0001 1
情景一:
1、客户端(请求方) jiangxi0002,过来一个请求,流水号是:20160311jiangxi0002xxxx
2、一般情况下,我们会先根据 ‘请求方’ 和 ‘流水号’ 取所在表查一下,看是否存在
3、假如,由于用户操作失误,服务端,同时接收到两个请求 A 和 B,请求A 和 请求 B的 ‘客户端(请求方)’ 和 ‘流水号’ 都相同。这时,两个请求同时处理,就可能碰到并发的问题了,导致这请求 A 和 请求 B 都向表中插了一条新的记录
解决方法:
在数据库中, 对 ‘请求方’ 和 ‘流水号’ 加唯一索引, 在请求来了之后,直接插入表,不进行查询操作,如果‘请求方’ 和 ‘流水号’已经存在,那么会插入失败, 这时我们再进行查询操作,确认是否已经存在,这样就能解决并发的问题了。
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/11335631.html

浙公网安备 33010602011771号