http协议及httpd基础
——以下内容摘自马哥教育课堂
HTTP/2.0 目前没有大规模应用
可以查看相关rfc文档
一次完整的http工作过程浅析:
(1)处理连接
处理客户端请求——接收/拒绝请求
tcp连接怎么建立——三次握手
tcp连接怎么断开——四次断开
tcp连接有两种,持久连接和非持久连接
tcp连接建立以后,请求第一个资源完成后不会立刻断开,可以基于该连接请求第二个资源,这样可以避免频繁的创建和断开连接
而如果连接建立以后长时间没有传输web资源则会浪费服务器的连接资源,因为web服务可以维持的连接数是有上限的。所以tcp连接应该设定超时时长,连接超过一定时间没有传输资源,应该断开以减少资源占用。
(2)接收请求
接收来自于网络的请求报文中的对某一资源的一次请求过程
深入讲解服务器端程序如何同时响应多个客户端的请求?——并发访问响应模型(WEB I/O)。有多种类型
①单进程I/O结构:服务器端只启动一个进程且只能一次响应一个用户请求,多个客户端只能串行访问,具体来说就是当服务进程在处理第一个客户端请求访问时,第二个客户端只能等待直至服务器处理完第一个请求。
②多进程I/O结构:并行启动多个进程,每个进程一次只能响应一个用户请求。但进程数多了造成频繁的内存切换,并且进程的个数毕竟是有限的,而且进程更加占用内存资源,所以响应能力是有限的。
③复用I/O复用结构:
多线程模型:一个进程内部生成多个线程,一个线程可以响应一个用户请求,这样一个进程就可以响应多个请求了,这是突破C10K的访问模型
事件驱动机制event-driven:一个进程内部维持一个事件监控器,监控管理多个I/O,这样一个进程就可以同时接入多个请求了。那么一个进程如何维持不同进程的连接状态呢?进程内部基于事件回调机制来完成连接状态的追踪,也就是IO的追踪,并基于事件回调来完成客户端的响应。因而实现了一个进程同时与多个进程进行通信。
④复用的多进程I/O结构:启动多个进程,每个进程响应多个请求。
(3)处理请求:对请求报文进行解析,并获取请求的资源及请求方法等相关信息
请求报文有特定格式,首部包含元数据
<method><URL><VERSION>:get下载,put上传,post提交表单
Host:例如www.magedu.com 请求的主机名称
Connection:
(4)获取本地资源:获取请求报文中请求的资源
web服务器:存放了web资源的服务器,负责向请求者提供对方请求的静态资源/动态资源,这些资源放置于本地文件系统某系统路径下,此路径通常称为DocRoot
httpd默认的DocRoot是/var/www/html/,其目录下有images/1.jpg,那么访问URL为http://www.abc.com/images/1.jpg
web服务器资源路径映射方式
1.docroot
2.alias
3.虚拟主机docroot
4.用户家目录docroot
(5)把资源构建成响应报文
MIME可以对每种可以被访问的类型进行标记和分类,分类方式有:
显示分类:php等代码中显示指明类型
魔法分类:web服务器自行判定文件类型
协商分类:服务器和客户端协商分类?
资源访问重定向:当访问A资源时,服务器回应的是另外一个路径,于是重新发起访问请求。重定向有多种方式:临时重定向和永久重定向
重定向还能实现负载均衡的效果,例如CDN可以基于重定向到新位置
(6)发送响应报文
(7)记录日志
把请求者IP和访问资源和处理办法记录到日志文件中
http是协议,应该有相关的实现程序实现其功能。那么http协议的实现程序有:
httpd(apache)
nginx
lighttpd,性能接近nginx,社区活跃程度没有nginx高
(web服务器程序)
应用程序服务器:既是web服务器,又能解析动态资源
IIS:解析ASP页面
tomcat,jetty,jboss,resin:jsp容器,解析JSP页面
重量级企业应用webshpere,weblogic,oc4j(oracle,少)
www.netcraft.com 定期更新每种web服务器程序占有的市场份额
回顾:
httpd配置文件的常见配置
Listen指令 Listen [IP:]PORT
KeepAlived {ON|OFF} 持久链接:http协议无状态的——它无法记录访问用户身份信息,默认情况下,资源获取彼此是隔离,毫无联系的,例如一个页面每个资源的获取都要三次握手四次断开来进行的。这是非持久连接。频繁的建立和断开连接会浪费大量的网络资源和系统资源。所以才有持久链接,只建立一次连接就完成多个资源的传输。相关设定参数,除了KeepAlived这个指令外还有相关指令MaxKeepAlivedRequests和KeepAlivedTimeout两个指令。
MPM:prefork,worker,event并发响应模型
DSO:LoadModule指令, httpd -M|-l查看装载的模块
DocumentRoot 指定站点访问的根目录,也是文件系统上某个指定的目录
站点访问路径控制可以使用Directory Location来定义
<Directory "">
Options 对目录中资源访问属性的设定,常见有Indexes FollowSymLinks,但一般都不建议启用,使用None即可
Order Allow,Deny 先检查Deny
Allow from
Deny from
</Directory>
<Location "">
</Location>
DirectoryIndex 定义默认的主页面的
ErrorLog 错误日志
CustomLog 访问日志,需要指明日志的格式
LogFormat %{Referer}i 引用Referer首部的值,Referer是指当前页面之前的跳转链接
Alias /URL/ "/PATH/TO/SOMEDIR/"
是另外一种映射方式,还有一种是DocumentRoot
设定默认字符集
基于用户的访问控制
认证方式:basic,digest(很多浏览器不支持?)
可以基于URL,可以基于文件系统路径
相关指令是
AuthType Basic
AuthName ""
AuthUserFile "/path/to/.htpasswd"
AuthGroupFile
Require user
Require valid-user
Require group
AuthUserFile使用htpasswd命令来创建,也可以使用mysql。
虚拟主机:三种类型,基于ip,基于端口,基于域名
===
http协议进阶
URL统一资源定位符,其组成部分:
URL方案:scheme---http://,https://
服务地址:FQDN/IP:PORT---www.abc.com[:80]
资源路径:/bbs/index.php,通常是DocumentRoot下的子目录和子文件
URL语法进一步说明:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
<user>:<password> 登录的账号密码
;<params> 参数,用来指明填入表单的数据
例如http://www.abc.com/bbs/hello;gender=f,只查询女性用户
?<query> 数据库查询
动态站点中,有应用程序的脚本文件,这个脚本文件需要在服务器后台运行后才把结果返回。程序由指令+数据构成,指令存在于脚本文件中,而数据则在数据库中。query中含有数据库查询的语句。
例如 http://www.abc.com/bbs/item.php?username=tom&title=tiger
#<frag> 锚点
百度百科的很多文档都有#锚定符
URL有两种——
相对URL:相对当前路径获取下一个资源的路径指明方式,站内引用可以用
绝对URL:从DocumentRoot开始指明资源路径,跨站引用只能使用绝对URL
===
http协议
http/0.9
http/1.0
http/1.1,加强了缓存功能
http/2.0
http协议是stateless无状态的
无状态是指:服务器无法持续追踪访问者来源。具体来说,客户端基于http协议获取服务器多个资源时,服务器并不能识别获取这些资源的连接是否来自于同一个用户。例如,某个用户输入账号密码登录后,由于服务器无法判定请求是否来自同一用户,所以一刷新页面会要求用户再次输入账号密码。
所以http协议引入其他机制来追踪用户,比如cookie。当某客户端访问服务器时,服务器会发送一小段随机数据给用户。用户浏览器会将其接收下来并保存于本地文件系统的特定位置上。后续对该服务器的访问,客户端都会带着这小段数据,服务器以此来判定请求是来自同一个用户了。就不再会出现登录后的用户刷新页面需要重新登陆的情况了。那么,在浏览器关闭后,是否应该保留cookie信息呢?对于银行站点等敏感网站,不应该保留,否则下次无论什么用户打开浏览器便自动登陆银行网站了。
cookie分类
胖cookie:记录了用户访问的详细信息,很容易泄露用户隐私,不建议使用
瘦cookie:仅仅标识用户身份,而用户的更详细的浏览信息则保存在服务器中,比如用户购物车中的物品信息。session机制可以实现此功能,它能记录用户在网站的访问行为,session是关联到某个用户cookie上的。session是保存于内存中的一小段数据,记录了用户的操作。当用户带着cookie来访问时,服务器会查找与之对应的session信息,从而得知用户之前的浏览信息。
cookie和session是用来追踪用户访问行为的重要手段,从而弥补的http无状态的缺陷。
===
http事务
一次完成的http请求就是http事务
一次完整的http请求=一次请求+一次响应
http请求涉及非常多的细节,比如用什么方法,请求的主机,客户端支持的编码格式、http协议版本、支持的语言、浏览器类型等等,这些内容都需要通知服务器。那么这些信息应该添加到报文的哪一部分呢?那就是应用层的http首部了。
服务器收到请求后需要做分析,就是分析http请求首部的内容,才能决定如何做出回应。比如分析哪个URL,使用的方法,支持的编码,协议版本。然后构建响应报文。响应报文中除了请求的资源外也应该包含很多信息。比如,如果响应成功的话,响应内容应该包含响应状态码、过期时间、内容编码方式等。如果响应失败的,响应内容应该包含失败原因,失败的状态码信息。这么多的信息,是通过响应报文的响应首部来发给客户端的。
请求报文是http请求所需的载体,有特定语法格式
<method><request-URL> <http-version>
<headers>众多首部
两次换行
<entity-body>请求主体
响应报文是http响应所需的载体,有特定语法格式
<http-version> <status-code> <reason-phrase>
<headers>
两次换行
<entity-body>响应主体
method:请求方法,标明了客户端希望服务器对资源执行的动作,比如常见方法GET,POST,HEAD
version: HTTP/<major>.<minor> 分别为主版本号和次版本号
status-code:是响应结果的代号,由三位数字构成,如200,301,302,404,502
reason-phrase:状态码对应含义的简要描述
headers:标记请求或响应的属性,每个请求或响应报文可包含任意个首部;每个首部定义——首部名称:[空格]首部对应值
entity-body:请求或响应时附加的数据,请求报文的实体可能为空。
请求、响应报文组成部分详细说明
=
method详解——
GET:从服务器获取一个资源,此时entity-body部分为空
HEAD:只从服务器获取文档响应首部而无需实体部分的内容
POST:向服务器发送服务器需要处理的数据,entity-body部分包含这些数据。
PUT:将请求的主体部分存储在服务器上,例如上传一个文档到服务器上,entity-body部分包含需要上传文件。这是一个危险的方法。
DELETE:请求删除服务器上的通过URL指定的文档
TRACE:追踪请求到达服务器中间经过的代理服务器;
OPTIONS:请求服务器返回对指定资源支持使用的请求方法
谷歌浏览器F12进入调试模式可以看到请求首部和响应首部
http协议查看或分析的工具--报文嗅探器有tcpdump,tshark,wireshark
=
状态码详解——
状态码有五大类
1xx:100,101,额外信息提示
2xx:200-206,成功的响应
3xx:300-305,重定向的响应
4xx:400-415,因为客户端引起的错误类信息
5xx:500-505,因为服务器端引起的错误类信息
常用的状态码
200:成功响应,请求的所有数据通过响应报文的entity-body响应发送,原因短语是OK
301:永久重定向,请求的URL指向的资源被永久移动到新位置,并且在响应报文中通过首部Location指明了资源现在所处的新位置。原因短语是moved permanently
302:临时重定向,请求的URL指向的资源被临时移动到新位置,并且在响应报文中通过首部Location指明了资源现在所处的新位置。原因短语是Found
304:客户端发出了条件式请求指定资源,但服务器判定此资源未发生改变,则通过此响应码响应客户端。原因短语是Not Modified。
401:需要输入账号和密码认证才能访问资源,原因短语是unauthorized
403:请求被禁止,forbidden
404:服务器无法找到客户端请求的资源,not found
500: 服务器内部错误,internale server error
502: 代理服务器从后端服务器收到了一条伪响应;bad gateway。举例:客户端请求代理服务器,代理服务器中并没有缓存此资源,于是请求上游服务器,但上游服务器返回了一个错误信息,此时代理服务器无法进行响应了,于是返回502
=
headers首部详解
首部是键值对的格式--name: value
多个首部时,每行写一个header对,示例如下:
Request Headers
Referer:http://www.it168.com/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Response Headers
Date:Wed, 04 Jan 2017 14:31:57 GMT
Last-Modified:Wed, 21 Dec 2016 00:48:51 GMT
Server:Microsoft-IIS/7.5
首部的分类——五种
通用首部:可用于请求首部和响应首部
请求首部:
响应首部:
实体首部:用于描述实体部分的信息
扩展首部:
详解如下:
通用首部:
Date:请求/响应报文的创建时间
Connection:指明是否持久链接
Via:显示报文经过的中间节点
Cache-Control: 缓存控制
Pragma:和缓存相关
请求首部:
Accept: 客户端通知服务器可以接收的媒体类型;
Accept-Charset: 客户端可以允许接收的字符集,比如UTF-8,GBK,GB2312
Accept-Encoding: 客户端支持的编码格式,如gzip,deflate,sdch
Accept-Language: 客户端支持的语言
Client-IP: 客户端IP
Host:请求的服务器名称和端口号
Referer: 引用当前正在请求资源的上一级资源,-表示直接从浏览器地址栏输入地址
User-Agent: 客户端代理类型,比如手机浏览器,火狐浏览器
条件式请求首部:
Expect:
If-Modified-Since: 自从指定的时间之后,请求的资源是否发生过修改;如果未修改响应304,如果修改过响应200和更新后的资源;
If-Unmodified-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:告诉客户端实体的真正位置,响应状态码为301,302时附加该首部
Content-Encoding: 内容编码格式
Content-Language:
Content-Length: 主体的大小
Content-Location:实体真正所处的位置
Content-Type:主体的对象类型
缓存相关首部:
ETag: 实体的扩展标签
Expires:实体的过期时间
Last-Modified: 实体最后一次修改时间
===
httpd的介绍
美国的工信部?曾经发起一个项目——开发web服务器程序软件,所以召集了一批优秀的工程师,后来开发成功。这批工程师散入江湖各大互联网公司后又自行组织起来重新改进增强这个web服务器程序,这个程序就是apache(a patchy server = apache)
ASF: apache software foundation
httpd特性:
1、高度模块化设计(core+module)
2、DSO模块动态装载,dynamic shared object
3、MPM机制,多路处理模块,有如下三种类型:
prefork:多进程模型,每个进程响应一个请求。httpd会以root启动一个主进程,主进程监听80端口并负责生成和管理多个子进程。主进程会把用户请求交个子进程来处理,子进程为工作进程,每个子进程处理一个用户请求。而子进程并非使用80端口的而是使用随机端口。但是构建响应报文还是使用80端口。子进程响应了用户请求后,会回收到空闲进程池中而不是立刻销毁。另外,即使没有用户请求,也会预先生成多个空闲进程随时等待请求到来。子进程数<=1024个。这种架构,不能响应大量用户的访问,但是非常稳定。即使某个进程崩溃了,也只是影响一个用户访问罢了而不会影响很多用户。所以对于用户量不大的群体,prefork是非常好的选择。
越精细的东西,越容易出故障。
如果服务器可以同时响应1024个请求,处理每个请求需要2s,一分钟处理30*1024个请求。但是请注意,一个页面可能就包含了100个请求。每天page view(PV)是15万,中小型企业
worker:多线程响应模型,每个线程响应一个进程。一个主进程生成多个子进程,每个子进程生成多个工作线程,每个线程响应一个用户请求。
通过这种方式,可以突破1024子进程的限制,因为每个子进程可以生成更多线程来响应用户请求。这种模型下,子进程和工作线程和prefork一样也是预先生成以便快速响应用户请求。但请注意linux调度线程和调度进程方式是相似的,所以用户访问量大的时候,cpu上还是需要频繁的上下文切换。
event:事件驱动机制,一个进程响应多个请求
一个主进程生成多个子进程,每个子进程响应多个请求,可以突破C10k的访问模型。http2.2 event是测试使用,http2.4 event可生产使用
http的功能特性:
虚拟主机:支持基于IP,port,FQDN的主机
支持CGI:通用网关接口
反向代理
正向代理
负载均衡
路径别名
丰富的用户认证:basic,digest(file,mysql)
支持丰富的第三方模块
安装httpd
rpm: yum list all httpd*
源码编译安装:企业中更加常见