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/p_w_picpaths/1.jpg --->http://www.lee.com/p_w_picpaths/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=abcfrag示例:用于定位而直接跳转到你感兴趣的地方 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:p_w_picpath/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:p_w_picpath/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:通知服务器我能接受的媒体类型(MIME类型)Accept-Charset:
Accept-Encoding:接受编码格式,如gzip Accept-Language:接受的语言 Client-IP: 客户端ip Host: 请求的服务器名称和端口号,虚拟主机解析时用到 Referer:包含当前正在请求的资源的上一级资源;(从哪跳转来的) User-Agent:客户端代理,就是浏览器类型3.条件式请求首部: Expect: 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 服务器进程的生命周期内进程最多响应多少个请求,应该大于等于maxclient
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.html8.站点访问控制
可基于两种类型的路径指明对哪些资源进行访问控制 文件系统路径: <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,denyDeny 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.010.定义默认主页面
DirecotryIndex index.html index.html.var11.日志设定
错误日志: 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).远程登录的用户名(使用mod_ident登录的才算,大多情况为空) -表示为空; %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#formats12.路径别名
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网页文件的文本编码应该与web服务器定义的文本编码保持一致
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服务即可生效