httpd是一款高效的服务器应用程序,是http协议的一种实现。在探讨httpd之前,我们来大概了解一下http协议吧,http协议实现了客户端和web服务器之间的通信,它是一种应用层协议。
http协议特性:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
http协议工作流程:
一次完整的http请求处理过程:
(1) 建立或处理连接:接收请求或拒绝请求
(2) 接收请求:接收来自于网络的请求报文中对某资源的一次请求的过程;
并发访问响应模型(Web I/O):
1单进程I/O结构:启动一个进程处理用户请求,而且一次只处理一个;多个请求被串行响应;
2多进程I/O结构:并行启动多个进程,每个进程响应一个请求;
3复用I/O结构:一个进程响应n个请求;
多线程模型:一个进程生成N个线程,每个线程响应一个用户请求;
事件驱动:event-driven
4复用的多进程I/O结构:启动多个(m)进程,每个进程响应n个请求;
(3) 处理请求:对请求报文进行解析,并获取请求的资源及请求方法等相关信息
元数据:请求报文首部
<method> <URL> <VERSION>
Host: www.magedu.com 请求的主机名称
Connection:
(4) 访问资源:获取请求报文中请求的资源
web服务器,即存放了web资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源;这些资源放置于本地文件系统某路径下,此路径通常称为DocRoot
web服务器资源路径映射方式:
(a) docroot
(b) alias
(c) 虚拟主机docroot
(d) 用户家目录docroot
例如:url与Docroot映射方式:/var/www/html/images/1.jpg --->http://www.lee.com/images/1.jpg
(5) 构建响应报文
资源的MIME类型:
显式分类
魔法分类
协商分类
URL重定向:
web服务构建的响应并非客户端请求的资源,而是资源另外一个访问路径;
(6) 发送响应报文
(7) 记录日
我们访问某站点,一定会在浏览器里输入站点的url地址,我们来分析一下url的格式
URL组成格式:基本语法:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
params参数示例:根据用户请求url传递的参数判定返回的内容(有过滤作用),例如负载均衡集群里可以通过设置params中"user=某用户"实现定向同一个用户请求到特特定服务器
http://www.magedu.com/bbs/hello;gender=f
query示例:指定查询条件(类似于mysql里WHERE子句),比如要与数据库等存储交互时用到
http://www.magedu.com/bbs/item.php?username=tom&title=abc
frag示例:用于定位而直接跳转到你感兴趣的地方
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html-single/Installation_Guide/index.html#ch-Boot-x86
相对url:同站引用(相对于当前位置定位资源,不完整的url)
绝对url:跨站引用
http报文格式:
1.request报文
<method> <request-URL> <version>
<headers>
<entity-body>
2.response报文
<version> <status> <reason-phrase>
<headers>
<entity-body>
解析:
1.method: 请求方法,标明客户端希望服务器对资源执行的动作
GET、HEAD、POST
2.version:HTTP/<major>.<minor> http协议的版本
3.status:
三位数字,如200,301, 302, 404, 502; 标记请求处理过程中发生的情况;
4.reason-phrase:
状态码所标记的状态的简要描述;
5.headers:
每个请求或响应报文可包含任意个首部;每个首部都有首部名称,后面跟一个冒号,而后跟上一个可选空格,接着是一个值;
6.entity-body:请求时附加的数据或响应时附加的数据----请求的资源;
详解:
1.method(方法):
GET:从服务器获取一个资源;
HEAD:只从服务器获取文档的响应首部;
POST:向服务器发送要处理的数据;
PUT:将请求的主体部分存储在服务器上;
DELETE:请求删除服务器上指定的文档;
TRACE:追踪请求到达服务器中间经过的代理服务器;
OPTIONS:请求服务器返回对指定资源支持使用的请求方法;
协议查看或分析的工具:
tcpdump, tshark, wireshark
2.status(状态码):
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: 与301相似,但在响应报文中通过Location指明资源现在所处临时新位置; Found
304: 客户端发出了条件式请求,但服务器上的资源未曾发生改变,则通过响应此响应状态码通知客户端;Not Modified
401: 需要输入账号和密码认证方能访问资源;Unauthorized
403: 请求被禁止;Forbidden
404: 服务器无法找到客户端请求的资源;Not Found
500: 服务器内部错误;Internal Server Error
502: 代理服务器从后端服务器收到了一条伪响应;Bad Gateway
headers:(列举了部分headers类型,再往下的首部分类中解释了这些headers)
格式:Name: Value
Cache-Control:public, max-age=600
Connection:keep-alive
Content-Type:image/png
Date:Tue, 28 Apr 2015 01:43:54 GMT
ETag:"5af34e-ce6-504ea605b2e40"
Last-Modified:Wed, 08 Oct 2014 14:46:09 GMT
Accept:image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:access.redhat.com
If-Modified-Since:Wed, 08 Oct 2014 14:46:09 GMT
If-None-Match:"5af34e-ce6-504ea605b2e40"
Referer:https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html-single/Installation_Guide/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36
首部的分类:
通用首部
请求首部
响应首部
实体首部(作用域body)
扩展首部
1.通用首部:
Date: 报文的创建时间
Connection:连接状态,如keep-alive, close
Via:显示报文经过的中间节点
Cache-Control:控制缓存
Pragma:缓存相关
2.请求首部:
Accept:通过服务器自己可接受的媒体类型;
Accept-Charset:
Accept-Encoding:接受编码格式,如gzip
Accept-Language:接受的语言
Client-IP: 客户端ip
Host: 请求的服务器名称和端口号,虚拟主机解析时用到
Referer:包含当前正在请求的资源的上一级资源;(从哪跳转来的)
User-Agent:客户端代理,就是浏览器类型
3.条件式请求首部:
Expect:通知服务器我能接受的媒体类型(MIME类型)
If-Modified-Since:自从指定的时间之后,请求的资源是否发生过修改;使用缓存
If-Unmodified-Since:与上面一条相反,覆盖缓存
If-None-Match:本地缓存中存储的文档的ETag(扩展标签)是否与服务器文档的Etag不匹配;
If-Match:和上一条相反,返回缓存就可以了,上一条必须覆盖原先缓存
4.安全请求首部:
Authorization:向服务器发送认证信息,如账号和密码;
Cookie: 客户端向服务器发送cookie
Cookie2:
5.代理请求首部:
Proxy-Authorization: 向代理服务器认证
6.响应首部:
信息性:
Age:响应持续时长
Server:服务器程序软件名称和版本
7.协商首部:某资源有多种表示方法时使用
Accept-Ranges:服务器可接受的请求范围类型
Vary:服务器查看的其它首部列表;
8.安全响应首部:
Set-Cookie:向客户端设置cookie;
Set-Cookie2: 向客户端设置第二版cookie
WWW-Authenticate:来自服务器的对客户端的质询认证表单
9.实体首部:描述主体的长度和内容,或者资源自身
Allow: 列出对此实体可使用的请求方法
Location:告诉客户端真正的实体位于何处
Content-Encoding:
Content-Language:
Content-Length: 主体的长度
Content-Location: 实体真正所处位置;
Content-Type:主体的对象类型
10.缓存相关:
ETag:实体的扩展标签;
Expires:实体的过期时间;
Last-Modified:最后一次修改的时间
http协议是无状态的,也就是说服务器无法持续追踪定位访问者来源
使用cookie:客户端第一次访问某个服务器时,每个服务器为了识别客户端,会发送一个唯一的标示数据给客户端,客户端浏览器保存这个数据到本地磁盘中,今后客户端访问这个服务器时会携带这个信息说明自己的身份,实现了服务器可以追踪客户端,胖cookie记录的用户个人信息很多,异常不安全,可适当使用轻cookie-----session。
session:我们需要跟踪客户端的同时又不能允许客户端缓存这些信息(不安全,可能我们输入了账号密码,不能让别人看见),就像淘宝的购物车,部分用户访问的行为会保存于服务器上,session是关联于cookie的
火狐浏览器F12键可以输出http报文信息:
有了这些基础概念,我们来了解一下httpd:
实验过程中关闭selinux和iptables(iptables -F)
1.httpd的配置文件
程序环境
配置文件:
/etc/httpd/conf/httpd.conf
/etc/httpd/conf.d/*.conf
服务脚本:
/etc/rc.d/init.d/httpd
MPM配置文件:/etc/sysconfig/httpd
主程序文件:
/usr/sbin/httpd
/usr/sbin/httpd.event
/usr/sbin/httpd.worker
日志文件目录:
/var/log/httpd
access_log: 访问日志
error_log:错误日志
站点文档目录:
/var/www/html
模块文件路径:
usr/lib64/httpd/modules
配置格式:directive value-------指令 值 格式
directive: 不区分字符大小写;
value: 为路径时,取决于文件系统;
配置监听的端口:(端口,套接字等相关概念请看上一篇博客)
省略ip表示监听本机所有IP; Listen可重复出现多次;
修改完成后重读配置文件service httpd restart
查看监听的端口:发现tcp80和8080都监听了
2.非持久连接:每请求一个资源都需要建立一次tcp/ip会话,浪费带宽
持久连接:连接建立,每个资源获取完成后tcp/ip会话不会断开连接,而是继续等待其它的请求完成;
副作用:对并发访问量较大的服务器,持久连接功能会使用有些请求得不到响应;
折衷:使用较短的持久连接时间;
httpd-2.4 支持毫秒级持久时间;
KeepAlive On|Off 持久连接开关
MaxKeepAliveRequests # 持久连接最大请求资源数量
KeepAliveTimeout # 持久连接超时时间
使用telnet测试http会话:因为开启了长连接,所以请求完没断开连接,可以继续请求资源
3.MPM:多道处理模块
prefork:多进程模型,每个进程响应一个请求;
一个主进程:负责生成n个子进程,子进程也称为工作进程,每个子进程处理一个用户请求;即便没有用户请求,也会预先生成多个空闲进程,随时等待请求到达;最大不会超过1024个;
worker:多线程模型,每个线程响应一个请求;
一个主进程:生成多个子进程,每个子进程负责生个多个线程,每个线程响应一个请求;
m进程,n线程:m*n
event:事件驱动模型,每个线程响应n个请求;
一个主进程:生成m个子进程,每个进程直接n个请求;
m*n
它把服务进程从连接中分离出来,在开启KeepAlive场合下相对worker模式能够承受的了更高的并发负载
httpd-2.2不支持同时编译多个模块,所以只能编译时选定一个;rpm安装的包提供三个二进制程序文件,分别用于实现对不同MPM机制的支持;确认方法:
更改默认使用的MPM:/etc/sysconfig/httpd文件
发现了httpd.worker和httpd.event程序,默认启动的是httpd,也就是prefork模型
httpd.conf配置文件中定义的MPM属性:
对于prefork模型:
StartServers 8
启动httpd时启动多少个主控进程生成的子进程进程
MinSpareServers 5
最小空闲进程数
MaxSpareServers 20
最大空闲进程数
ServerLimit 256
限定最多允许并发进来的活动用户连接个数,在线进程数量最大值
MaxClients 256
最多允许启动多少个进程
MaxRequestsPerChild 4000
一个进程最多响应多少个请求,多于4000就杀死这个进程
对于worker模型:
StartServers 4
启动httpd时启动多少子进程
MaxClients 300
最多允许启动多少个线程(最大并发请求数)
MinSpareThreads 25
最小的空闲线程数
MaxSpareThreads 75
最大的空闲线程数
ThreadsPerChild 25
允许每个进程最多生成多少个线程
MaxRequestsPerChild 0
设置一个独立的子进程将能处理的请求数量
300*86400/50=40W+,全负荷全天处理总的请求数/每个连接请求的资源数=pv
4.查看httpd的模块:
静态编译进httpd的模块
event程序的:
查看静态编译及动态装载的已在当前服务上被装载了的模块
5.pv和uv:
PV(访问量):PV反映的是浏览某网站的页面数,只算页面入口的访问量,就是说PV与来访者的数量成正比,但PV并不是页面的来访者数量,而是网站被访问的页面数量。 UV(独立访客):可以理解成访问某网站的电脑的数量。网站判断来访电脑的身份是通过来访电脑的cookies实现的。如果更换了IP后但不清除cookies,再访问相同网站,该网站的统计中UV数是不变的。 一台服务器:每个进程5秒响应1个请求,1024个进程5秒可以响应1024个请求,一分钟就是1024*12个,一天就是1024*12*1440(分钟)~=17000k个 但是每个网站有多个页面,每个页面又有N个资源,每个资源就是一个请求,假设每个页面包含100个资源,1700k/100=17k个,所以单台服务器一天最多也就17k个 带宽大小~=每个请求大小*并发数
6.DSO机制:
配置指令实现模块加载
LoadModule <mod_name> <mod_path>
模块路径可使用相对地址
相对于ServerRoot(/etc/httpd)指向的路径而言;
/etc/httpd/modules/
7.定义'Main' server的文档页面路径
文档路径映射:
DocumentRoot指向的路径为URL路径的起始位置;
DocumentRoot "/var/www/html"
/var/www/html/test/index.html --> http://HOST:PORT/test/index.html
8.站点访问控制
可基于两种类型的路径指明对哪些资源进行访问控制
文件系统路径:
<Directory ""> </Direcotry>
<File ""> </File>
<FileMatch ""> </FileMatch>
URL路径:
<Location ""> </Location>
可以限定对于那种方法进行控制,下面列举了http协议中的方法类型
访问控制机制:
基于来源地址;
基于账号;
9.Directory中一些安全机制:
(1) Options
所有可用特性:Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
None, All
Indexes: 索引;允许显示索引,如果输入的url下找不到可用网页,是否显示所有目录,不安全,生产环境应 该关闭,但是下载站常用
FollowSymlinks:允许跟踪符号链接文件;
SymLinksifOwnerMatch:允许符号链接,但是检查进程属主是否有权限
MultiViews:根据客户端浏览器语言环境判断显示网页应该哪种语言,性能差,不建议打开
AllowOverride: 访问控制,是否允许当前配置覆盖指定网页目录.htaccess定义的访问控制机制
每目录的访问控制:(会极大影响服务器性能)
定义不允许别人访问以.ht开头的文件
(2) 基于来源地址的访问控制机制
<Directory>
Options Indexes FollowSymLinks
Order
Allow from
Deny from
</Directory>
<Location>中也可以定义
Order:检查次序
Order allow,deny
Deny from
Order deny,allow
Allow from
来源地址:
IP ADDR
NetAddr:
172.16
172.16.0.0
172.16.0.0/16
172.16.0.0/255.255.0.0
10.定义默认主页面
DirecotryIndex index.html index.html.var
11.日志设定
错误日志:
ErrorLog logs/error_log
LogLevel warn
debug, info, notice, warn, error, crit, alert, emerg
访问日志:
CustomLog logs/access_log combined
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
%h:客户端IP地址;
%l: Remote logname (from identd, if supplied). -表示为空;
%u: Remote user, (from auth; may be bogus if return status (%s) is 401);
%t:Time the request was received (standard english format),服务器收到请求的时间;
%r:First line of request,请求报文的首行信息(method url version);
%>s: 响应状态码;
%b: 响应报文的大小,单位是字节,不包括响应报文首部;
%{Referer}i:请求报文当中"referer"首部的值;当前资源的访问入口,即从哪个页面中的超链接跳转而来;
%{User-Agent}i:请求报文当中"User-Agent"首部的值;即发出请求用到的应用程序;
详情:http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#formats
12.路径别名
DocumentRoot "/www/htocs"
http://www.magedu.com/download/bash-4.4.2-3.el6.x86_64.rpm
--> /var/www/htdocs/download/bash-4.4.2-3.el6.x86_64.rpm
Alias /URL/ "/PATH/TO/SOMEDIR/"
示例:
Alias /bbs/ "/forum/htdocs/bbs/"
http://www.magedu.com/bbs/index.html --> /forum/htdocs/bbs/
13.设定默认字符集
AddDefaultCharset UTF-8
GBK, GB2312, GB18030
14.基于用户的访问控制:
基于用户访问控制:
认证方式:basic, digest
AuthType Basic
AuthName ""
AuthUserFile
AuthGroupFile
Require user指定账号文件中某个用户可登陆,其他不允许登录
Require group
Require valid-user所有账号文件中的用户都可登录
配置实验:
在/var/www/html/下面创建admin目录作为安全域,下面存放index.html
http.conf配置:
生成账户密码文件:
htpasswd [options] passwordfile username
-c: 自动创建passwordfile,因此,仅应该在添加第一个用户时使用;
-m: md5加密用户密码;
-s: sha1加密用户密码;
-D: 删除指定用户
注意添加第二个用户不用-c选项
重启httpd服务通过并客户端访问就要求认证了:
基于组进行认证:
生成组文件:
httpd.conf配置:
重载httpd服务即可生效