HTTP 协议和IO模型

一:HTTP协议

http协议:HyperText Transfer Procotol超文本传输协议,http协议是无状态的,监听在80端口,TCP协议上。HTTP协议的特点有以下几点:

1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。
由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

在服务器不是持久连接的状况下,客户端在第一次访问服务器时服务器会记录客户端的个人标志信息,当客户端刷新或者再次访问时,服务器就要要求客户端输个人的标识信息,记录访问者的信息。也就是说在不是持久连接的状况下,服务器无法追踪访问者的来源。

于是就出现了 cookiesession

htmlHyperText Mark Language:超文标记语言

web资源:

       静态文件:.jpg .gif .html  .txt .js .css.mp3 .avi

       动态文件:.php  .jsp

http早期版本只能传输文本内容,到HTTP/1.0之后支持MIME。使HTTP协议支持传输多媒体信息。

MIMEMultipurpose Internet Mailextention

MIME类型:Major/minor

text/plain

p_w_picpath/jpeg

p_w_picpath/gif

URI:Uniform Resource Idetifier :统一资源标识符

       URLUniform Resource Locate:统一资源定位符

       用于描述某服务特定资源的位置

       Scheme://Server:Poert/Path/to/resource

       URNUniform Resource Naming:统一资源命名符。

       URL方案:scheme

       服务器地址:IPPort

       资源路径

    基本语法:               

            <scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

params:参数

        http://www.kk.com/bbs/hello;gender=f

query:查询

       http://www.kk.com/bbs/item.php?usesrname=tom&title=abc

frag:片段

request 报文语法格式:

       <method><request-URL> <http/Version>

       <headers>

       <entity-body>

reponse报文语法格式:

<http/version><status> <reason-phrase>

<headers>

<entity-body>

各个字段的介绍:

method:请求的方法:

常用请求的方法:

GET:从服务器获取一个资源

HEAD:只从服务器获取文档的响应首部

POST:向服务器发送要处理的数据

PUT:将请求的主题部分存储服务器上

DEETE:强求删除服务器上指定的文档

TRACE:追踪请求到达服务器中间经过的代理服务器

OPTIONS:请求服务器返回对指定资源支持使用的请求方法

wKiom1YuR1CAOOuRAAPq6JdvCEA938.jpg

status(状态码):告诉客户端的请求发生的结果:

1XX100-101,信息提示

2XX200-206,成功类型信息

3XX300-305,重定向的资源

4XX400-415,错误类型的信息,客户端的错误,

5XX500-505,错误类型错误,服务器端错误

常用的状态码:

200:成功响应,请求的所有数据通过相应报文的entity-body部分发送,OK

301:请求的URL执行的资源已经被删除;但在相应报文中通过首部Location指明了资源的所在位置;Moved Permanently (永久重定向)

302:与301相似,但在相应报文中通过首部Location指明了资源现在所处临时新位置;Found  (临时重定向)

304:客户端发出了条件式请求,但服务器的资源为曾发生改变,则通过相应此响应状态码通知客户端,Not Modified

401:需要输入账号和密码认证方能访问资源:Unauthorized

403:请求被禁止:Forbidden

404:服务器无法找到客户端请求的资源:Not Found

500:服务器内部错误:InternalServerError

502:代理服务器从后端服务器中收到的一条伪响应:Bad Gateway

hearders首部:

通用首部:

Date:报文的创建时间

Connection:连接状态,keep-alive,close

via:显示报文经过的中间节点

Cache-Control:控制缓存

no-cache

max-age

Transfer-Encoding

WEB 服务器表明自己对本响应消息体(不是消息体里面的对象)作了怎样的编码,比如是否分块(chunked),例如:Transfer-Encoding: chunked

pragma

请求首部:

wKioL1YuSDSwccByAAIF9PzfssA977.jpg

Accept:通过服务器自己能够接受的媒体类型

Accept_Charset

Accept_Encoding:告诉服务器自己能接受的编码格式,如gzip

Accept-Language:通知服务器自己能接受的语言

 

Host:请求的服务器名称或者端口号

Referer:包含了当前正在请求的资源的上一级资源。

User-Agent:客户端代理

条件式请求首部

       Expect

       If-Modified-Since:自从指定的时间之后,请求的资源是否发生过修改

       If-Unmodufied-Since

       If-None-Match:本地缓存中存储的文档的ETag标签是否与服务器文档的Etag不匹配。

If-Match;

安全请求首部:

       Authorization:向服务器发送认证信息,如账号密码

       Cookie:客户端向服务器发送cookie

       Cookie2

代理请求首部:

       Proxy-authorization:向代理服务器认证

响应首部:

信息性:

       Age:响应持续时长

       Server:服务器程序软件名称和版本

       协商首部:某资源有多种表示方法时使用

              Accept-Ranges:服务器可接受的请求范围类型

              Vary:服务器查看的其他首部列表

       安全响应首部:

              Set-Cookie:向客户端设置Cookie

              Set-Cookie2

              WWW-Authenticate:来自服务器的对客户端质询认证表单

实体首部

Allow:列出次实体可使用的请求方法:

Location:告诉客户端真正的实体位于何处

Content-encoding:编码格式

Content-language

Content-Length:实体的长度

Content-Location:实体真正所在的位置

Content-Type:主体的对象类型

缓存相关:

       Etag:实体的扩展标签

       Expires:实体的过期时间

web页面,多个资源:

浏览器自身的限制是针对于单一域名访问的限制,最多能打开几个线程进行访问,。而在一个公司网站使用多个域名的话,当用户使用浏览器访问时,浏览器会针对不同的域名开启多个线程来访问页面资源。如,在单一域名www.kkkkk.com进行访问,浏览器可能开启2个线程进行页面资源的访问。假如在www.kkkkk.com域名下的图片资源又单独使用一个域名www.p_w_picpath.com。那么浏览器会再次开启两个线程进行访问。所以在公司内部使用多个域名,这也是提升访问速度的一种方法。

1.web服务器的认证:

基于IP认证:

基于用户认证:

basic认证

digest认证

2.web服务器的资源映射

a.DocumentRoot

b.路径别名Alias

c.虚拟主机DocumentRoot

b.用户家目录DocumentRoot

3.支持第三方模块:支持模块的动态加载

 

一次完整的http请求过程

1)建立连接或处理连接:接收客户端请求或拒绝请求

2)接收请求

       接收来自网络的请求报文对某一个资源的请求

       并发服务器访问响应模型(Web I/O

单进程I/O机结构:启动一个进程处理用户请求,而且一次只处理一个请求,多个请求被串行响应。

多进程I/O结构:并行启动多个线程,每个进程响应一个请求,一个请求称为一个pv

复用I/O 结构:一个进程响应多个n个请求

                     多线程模型:一个进程生成多个线程,每个线程响应一个用户请求。

                     事件驱动机制:事件回调来完成事件请求:event-driven

                     复用的多进程I/O结构:启动多个(m)进程,每个进程响应n个请求。

                     c10K问题 :1w个并发连接:

3)处理请求:对请求报文进行解析,并获取请求的资源及请求方法等相关信息

              元数据:请求报文首部

              请求方法<method>

                     <method><URL><VerSion>

4)访问资源:获取请求报文中请求的资源

web服务器,即存放了web资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源,这些资源放置在本地文件系统某路径下,此路径通常为DocRoot

              web服务器资源路径的映射方式:

                     a.docroot

                     b.路径别名

                     c.虚拟主机docroot

                     b.用户家目录docroot

5)构建响应报文

              MIME类型:

                     显示分类

                     魔法分类

                     协商分类

              URL重定向:

                     cdn

                     web服务构建的响应并非客户端请求的资源,而是资源另一个访问路径。

                     游走重定向:

                     永久重定向:

6)发送响应报文

7)记录日志


二:I/O模型

I/O类型:

同步IO和异步IOsynchronous ,asyncronous:关注的是消息通知机制

同步:调用发出之后不会立即返回,但一旦返回,则返回最终结果。

异步:调用发出之后,被调用方立即返回消息,但返回的并不是最终结果被调用者通过状态,通知机制等通知调用者,或通过回调函数来处理结果。

阻塞IO和非阻塞IOnlocknonlock

关注的是调用者等待被调用者返回调用结果时的状态:(调用者的状态)

阻塞:调用结果返回之前,调用者会被挂起;调用真只有在得到调用结果之后才能继续。

非阻塞:调用者在调用结果返回之前,不会被挂起,即调用不会阻塞调用者

常用的IO模型:

blocking IO :阻塞型IO

noblocking IO

IO multiplexing:复用型IO

signal driven IO:事件驱动型IO

asynchronnous IO:异步型IO

通过磁盘IO总体解释:

一个用户进程发起一次磁盘IO调用时,将有两个阶段组成,一次是内核向磁盘取数据,存放到内存空间,另一次是数据从内存空间取出,将数据存到用户进程的内存中。真正被称为执行IO的阶段是:数据从内核内存到进程内存的过程。

1.阻塞型IO

 wKiom1YuSYHg555OAAFBdZqmgNw009.jpg

 

当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据(对磁盘read来说内核从磁盘获取数据)。对于network io来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包),这个时候kernel就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。

所以,blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了。

实际上,除非特别指定,几乎所有的IO接口 ( 包括socket接口 ) 都是阻塞型的。这给网络编程带来了一个很大的问题,如在调用send()的同时,线程将被阻塞,在此期间,线程将无法执行任何运算或响应任何的网络请求。

    一个简单的改进方案是在服务器端使用多线程(或多进程)。多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接。具体使用多进程还是多线程,并没有一个特定的模式。传统意义上,进程的开销要远远大于线程,所以如果需要同时为较多的客户机提供服务,则不推荐使用多进程;如果单个服务执行体需要消耗较多的CPU资源,譬如需要进行大规模或长时间的数据运算或文件访问,则进程较为安全。

2.非阻塞IO

wKiom1YuSs3wHW3AAAHDBGG0xOA373.jpg

从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回。

3.复用型IO

内核提供了两种调用,select(),poll(),当用户进程发起系统调用时,内核中的selecte会接受这个系统调用,并select自身将系统调用发送给内核,内核再进行准备数据和拷贝数据。当用户进程发起一次系统调用给select之后,用户进程在等待数据返回的过程中,还可以发起多次系统调用,每次系统调用都要经过select发送内核进行处理。也就是说,selects是一个代理。比如,(例子不是很恰当)公司老板向人事部发布通知要裁员,此时老板通过助理把裁员名单送给人事部。在发送和得到结果之前,公司老板还可以通过助理让销售部经理来老板办公室。其实这就相当于复用IO的模型,助理就相当于select

select不能超过1024个。

prefork模型和worker模型就是基于复用IO模型的。并发响应有限。

调用者被阻塞者select上,但可以处理其他请求或IO

4.事件驱动型IO

wKioL1YuTJWgT8LNAAEZOQlK9P8290.jpg    

事件驱动型IO

在第一阶段内:当用户进程发起系统调用时,内核会立即通知给用户进程系统调用已经收到,并且会在数据收集和准备完成时通知用户进程。此时用户进程就可以处理其他事物。

在第二阶段内:当系统将磁盘数据取到内存空间中后,通知调用者,调用者会使用回调函数进行处理,来获取数据。这个阶段会发生阻塞状况。

假如一个用户进程在第一次发送系统调用请求后,在第一阶段内,继续发送第二次系统调用请求。当用户进程第一次请求被阻塞第二阶段时,内核告知用户进程,第二次请求的数据也已经准备好了,让用户进程来获取。此时就出现了冲突状态

通知机制:

水平触发:多次通知

边缘触发:只通知一次:

event模型就是使用的此IO模型。

Nginx支持此IO模型,采用的通知机制为边缘触发。

5.异步型IO

wKioL1YuTOzQtsvEAAEzXnvaM10984.jpg

异步IO模型和复用IO模型区别之处就是:在数据准备第二阶段,内核将数据直接存放到用户进程的内存空间中,不需要用户进程使用回调函数从内核中获取数据。如当一个web服务进程发送请求后,后续过程直接交给内核,在内核处理的过程时间内,此进程可以响应其他的用户请求。当内核将数据返回到进程内存中后,进程就可以把数据直接返回给用户,这大大提高了响应的速度。

Nginx也支持异步IO模型,还可以基于内存映射的机制来完成数据的发放、所以说Nginx并发能力强。


几种IO模型的比较:

wKiom1YuTS3RosoLAALCyIceEfg549.jpg