1、http协议基础及IO模型

Nginx (web server,web reverse proxy):

http协议:80/tcp,HyperText Transfer Procotol

http协议版本:

HTTP/0.9:原型版本,功能简陋

HTTP/1.0:第一个广泛使用的版本,支持MIME

HTTP/1.1: 增强了缓存功能

spdy

HTTP/2.0  下一次流行

MIME:Multipurpose Internet Mail Extesion 多用途互联网邮件扩展

major/minor:text/plain, text/html, image/jpeg

URI: Uniform Resource Identifier  同一资源标识符

URL: Uniform Resorce Locator(统一资源定位符),用于描述某服务器某特定资源的位置;

URL包括三部分:

URL方案:scheme//

服务器地址:ip:port

资源路径:

http://www.magedu.com:80/bbs/index.php,

https://就表示scheme,表示用什么协议进行交换

Scheme://Server:Port/path/to/resource

http://www.magedu.com/images/logo.jpg

URN: Uniform Resource Naming

http事务:httpd一次请求和响应的过程

请求:request //请求是由请求报文来请求

响应:response//响应是由响应报文来构建

报文语法格式:

request报文

<method> <request-URL> <version>   //起始行

<headers>                         //有可能由众多的头部组成

<entity-body>                     //请求主体部分,有可能为空

Response响应报文

<version> <status> <reason-phrase>原因短语

<headers>

<entity-body>//响应实体

请求报文语法解析:

method:请求方法,标明客户端希望服务器对资源执行的动作

  GET(表示客户端希望服务器把资源打包发给客户端)HEADPOST

version://请求报文和响应报文都一样

HTTP/<major>.<minor>//主版本号.次版本号

status:

三位数字,如200301, 302, 404, 502; 标记请求处理过程中发生的情况;

reason-phrase

status状态码所标记的状态的简要描述;

headers:首部

每个请求或响应报文可包含任意个首部;每个首部都有首部名称,后面跟一个冒号,而后跟上一个可选空格,接着是一个值;

entity-body请求时附加的数据或响应时附加的数据;有用的数据块,请求报文entity-body可能为空

method(方法)

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

HEAD:只从服务器获取文档的响应首部,而不是响应内容;

POST:向服务器发送要处理的数据,放在<entity-body>中;

PUT:将请求的主体部分存储在服务器上,上传数据到服务器;

DELETE:请求删除服务器上指定的文档;

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

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

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 服务器内部错误,原因很多;Internal Server Error

502 代理服务器从后端服务器收到了一条伪响应;

504 Gateway Timeout 是一种HTTP协议的服务器端错误状态代码,表示扮演网关或者代理的服务器无法在规定的时间内获得想要的响应。

Bad Gateway表示客户端向代理服务器发送请求,代理服务器应该给客返回结果,但是代理服务器本地没有缓存,就像上游代理服务器请求,上游服务器给所请求的下游服务器发送了一个错误的,因此下游服务器就没办法响应客户端。

协议查看或分析的工具:tcpdump, tshark, wireshark

方法是客户端告诉服务器端应该做什么,状态码是服务器端告诉客户端的请求发生的状态

headers:

格式: Name:Value

首部的分类:

通用首部、请求首部、响应首部、实体首部、扩展首部

通用首部:

Date: 报文的创建时间

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

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

Cache-Control:控制缓存生效机制

Pragma

请求首部:

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

Accept-Charset

Accept-Encoding:接受编码格式,如gzip 

Accept-Language:接受的语言

 

Client-IP:

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

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

User-Agent:客户端代理

条件式请求首部:

Expect:期望发什么信息

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

If-Unmodified-Since:自从指定时间之后,请求的资源没有发生修改;

If-None-Match:本地缓存中存储的文档的ETag(扩展标签)标签是否与服务器文档的Etag不匹配;是:表示不匹配,否:表示匹配

If-Match:和If-None-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:实体的过期时间;

Last-Modified:最后一次修改的时间

 

http协议是文本编码的是无状态的

web资源

静态资源:静态内容;客户端从服务器获得的资源的表现形式与原文件相同;

动态资源:通常是程序文件,需要在服务器执行之后,将执行的结果返回给客户端;客户端拿到的内容依然是静态的,认识纯文本,跟服务器端不一样


Web服务器和程序解释器之间是如何协调工作的?即web服务器如何把客户端请求的动态资源让解释器去磁盘调用并进行运行?他们之间遵循一种协议:CGI

  


通俗的可以把服务器看作餐厅,用户请求看作来用餐的顾客,服务器处理请求看作解决顾客的就餐问题(响应输出一份饭)。

服务器上静态资源看作已做好的饭,只要放到餐盒里就可以返回给顾客,动态资源需要厨房大厨现成做份再放到餐盒里返回给顾客。

php_mod:这个大厨有个特点,看见有顾客进门就点火,不管顾客要不要现做的,有点浪费资源

php_fpm:这个大厨有好多小弟一直点着火(多个处理进程),等有顾客说要现做,大厨就安排小弟做份返回给客户

cgi:也是个大厨,不过他等到顾客要现做,他才点火,做饭,然后熄火。等待下一个要现做的到来

fastcgi:就是个大厨雇了一帮小弟,专门做需要现场做的饭,大厨只管分派任务,小弟真正操锅做饭

参考链接:https://www.zhihu.com/question/30672017/answer/53238751


程序=指令+数据


请求流程:Client --> (http) --> httpd服务 --> (cgi) --> application server (program file) --> (mysql驱动和协议) --> mariadb

1、首先客户端A通过http协议请求资源,web服务器端B接受协议之后,通过过滤器识别客户端请求的资源后缀,假如客户端请求的动态资源,发现是.php,那么就向后转发,通过CGI协议跟PHP解释器的应用程序C进行交互,这时web服务器是CGI的客户端,而php解释器的应用程序是CGI的服务器端。

2、CGI服务器C上面运行的程序发现代码中需要用到数据,服务器C会基于驱动D跟后面的数据存储打交道,这时假如后面的是mysql服务器(都是应用层协议),那么中间用到的协议就是mysql协议。这时候,应用程序C就MySQL协议的客户端,而MySQL服务器就成了MySQL协议的服务器端。

整个执行过程:客户端请求一个动态资源,请求先送到给web服务器,web服务器发现这是一个动态资源,那么web服务器就会转交给应用程序服务器-PHP程序,web服等待php程序响应,这个过程就被阻塞了,php程序就从磁盘上加载程序文件到php程序里面进行执行,在执行过程中,如果有结果就返回给web服务器,但是如果在执行过程中发现有数据,而数据在本地磁盘中并没有存放,需要到MySQL服务器中去调用,于是php程序就扮演成MySQL服务器的客户端发出请求,MySQL服务器经过对数据出来把结果返回给php应用程序,php程序对结果做进一步处理然后把结果返回给web服务器,web服务器把结果封装成http报文发送到客户端。

httpd的特性:

高度模块化:core + modules

DSO: Dynamic Shared Object

MPM:Multipath Processing Modules //多路处理模块

prefork:多进程模型,每个进程响应一个请求;

一个主进程:负责生成n个子进程,子进程也称为工作进程,每个子进程处理一个用户请求;即便没有用户请求,也会预先生成多个空闲进程,随时等待请求到达;最大不会超过1024个;

worker:多线程模型,每个线程响应一个请求;

一个主进程:生成多个子进程,每个子进程负责生成多个线程,每个线程响应一个请求;

m进程,n线程:m*n

event:事件驱动模型,每个进程响应n个请求;

一个主进程:生成m个子进程,每个进程直接n个请求;

m*n

 

httpd-2.2:event为测试使用

httpd-2.4:event可生产使用

pv:page view

uv: user view

    独立IP

一个域名打开的线程数是有限的,所以有些网站为了提高用户体验就在一个网站页面上布置多个域名

I/O类型:

参考:马哥视频、https://www.jianshu.com/p/786d351e06d8、https://www.jianshu.com/p/486b0965c296

同步和异步:synchronous, asyncrhonous

关注的是消息通知机制(被调用者即服务器端如何把已经完成的结果通知给调用者);  即服务器端

同步:调用发出不会立即返回,但一旦返回就可以返回最终结果;

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

阻塞和非阻塞:block, nonblock

关注的是调用者等待被调用返回结果(消息、返回值)时的状态  即客户端

阻塞:调用结果返回之前,调用者(调用线程)会被挂起;调用者只有在得到结果之后才会返回;

非阻塞:调用结果返回之前,调用者不会阻塞当前线程;

5种I/O模型:prefork和worker都是复用型I/O,并发能力有限,最多1024;event是事件驱动型I/O;

blocking IO       阻塞式IO

nonblocking IO    非阻塞式IO

                  以上两种IO模型中第二阶段需要调用者即进程等待内存把数据从内核内存中复制给进程内存,这个过程调用者是阻塞的

IO multiplexing   复用型IO   //把请求给内核代理,不是给内核,请求最多1024个,阻塞在select上,这样的好处调用者可以继续发送请求;

                select(),poll()

signal driven IO  事件驱动式IO  当用户请求的数据准备好之后,内核会通知进程取数据,如果这时进程在第二阶段被阻塞时,如何?内核通知进程后,过了指定时间就会消失。

                    之所以叫事件驱式IO,是因为一旦数据从磁盘到内核内存即数据准备好了之后,内核会通知调用者即调用进程,让调用者就会使用回调函数进行处理。

                    (第二段阻塞:因为内核把数据准备好后,会通知进程数据已准备好,这是进程就要准备接受数据,然后内核会把数据从内核内存复制到进程内存)

  通知机制:水平触发:通知一次没响应,再通知,直到你处理为止;

   边缘触发:只通知一次,如果没有响应,就把通知事件通过回调函数让调用者自行来获取,即把通知信息放在某处;

复用IO和事件驱动IO模型第二阶段之所以阻塞是因为第一阶段:在内核从磁盘把数据处理好后放到内核内存后,第二阶段就需要调用者即进程调用回调函数来内核内存中取数据,所以也是阻塞。

asyncrhonous IO   异步IO  第二阶段即内存把数据准备好后,不需要调用者再利用回调函数去内核内存中取数据,而是内存直接把数据复制到进程内存中。

例:一个read操作:

(1) 等数据准备好,从磁盘到内核内存;

(2) 从内核内存复制到进程内存;

一个磁盘IO分两步:

1、用户空间的进程没有权限直接访问硬件的,用户空间的进程发起IO调用时,只能向内核请求,数据只能在硬盘上,内核先把数据加载至内存内存中,

2、内核再把数据从内核内存复制到进程内存

这两步真正执行IO的是数据从内核内存到进程内存   真正称为IO的步骤是数据从内核内存到进程内存

       

    

 

没有消息通知的是同步I/O:阻塞式I/O、非阻塞式I/O、复用型IO

有消息通知的是异步I/O: 事件驱动式IO、异步IO

nginx用的是事件驱动式IO,而且基于边缘触发通知机制来实现,同时也支持异步IO,而且还能够完成基于内存映射机制来完成数据的发放。

MMAP知识:https://www.cnblogs.com/huxiao-tee/p/4660352.html

一次完整的HTTP事务是怎样一个过程?
http://blog.51cto.com/linux5588/1351007

tcp三次握手
https://blog.csdn.net/geecky/article/details/56275032  
原文地址:https://www.cnblogs.com/hanshanxiaoheshang/p/9540759.html