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地址。
  具体过程如下:

  1. 用户主机上运行着DNS的客户端,就是我们的PC机或者手机客户端运行着DNS客户端了
  2. 浏览器将接收到的url中抽取出域名字段,就是访问的主机名,比如http://www.baidu.com/, 并将这个主机名传送给DNS应用的客户端
  3. DNS客户机端向DNS服务器端发送一份查询报文,报文中包含着要访问的主机名字段(中间包括一些列缓存查询以及分布式DNS集群的工作)
  4. 该DNS客户机最终会收到一份回答报文,其中包含有该主机名对应的IP地址
  5. 一旦该浏览器收到来自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 都向表中插了一条新的记录

解决方法:
    在数据库中, 对 ‘请求方’ 和 ‘流水号’ 加唯一索引, 在请求来了之后,直接插入表,不进行查询操作,如果‘请求方’ 和 ‘流水号’已经存在,那么会插入失败, 这时我们再进行查询操作,确认是否已经存在,这样就能解决并发的问题了。

 

posted @ 2019-08-11 17:09  LeeJuly  阅读(134)  评论(0)    收藏  举报