一、何为httpd

    httpd是Apache超文本传输协议(HTTP)服务器的主程序。被设计为一个独立运行的后台进程,它会建立一个处理请求的子进程或线程的池。

    Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。


二、httpd-2.2的基本功能特征

    ①、高度模块化设计,并且支持模块的动态装载(DSO机制),所以httpd基本上可以理解为cord(核心)+各种模块组成。

    ②、支持插入式并行处理模块,称为多路处理模块(MPM)。在编译apache时必须选择也只能选择一个MPM,对类UNIX系统,有几个不同的MPM可供选择,它们会影响到apache的速度和可伸缩性。

        Prefork MPM :多进程模型,每个进程响应一个请求。当httpd服务启动时,启动一个主进程,主进程不负责响应客户请求,此主进程负责生成N个子进程。每一个子进程也称为工作进程,每个子进程处理一个用户请求。即便没有用户请求,也会预先生成多个空闲进程,随时等待请求到达。

        这个多路处理模块(MPM)实现了一个非线程型的、预派生的web服务器,它的工作方式类似于Apache 1.3。它适合于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求。


        Worker MPM :多线程模型,每个线程响应一个请求。一个主进程:生成多个子进程,每个子进程负责生个多个线程,每个线程响应一个请求。由于Linux线程并不比进程轻量级多少,而且内部调度线程跟进程也是一样的,所以,Worker MPM比起Prefork MPM性能并没有多大的提升。

        此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求,所以可以处理海量请求,而系统资源的开销小于基于进程的MPM。但是,它也使用了多进程,每个进程又有多个线程,以获得基于进程的MPM的稳定性。

        每个进程可以拥有的线程数每个子进程可以建立ThreadsPerChild数量的服务线程和一个监听线程,该监听线程监听接入请求并将其传递给服务线程处理和应答。

        不管是Worker模式或是Prefork 模式,Apache总是试图保持一些备用的(spare)或者是空闲的子进程(空闲的服务线程池)用于迎接即将到来的请求。这样客户端就不需要在得到服务前等候子进程的产生。


       Event MPM:基于事件驱动:event-driven。复用的多进程I/O结构:一个主进程,启动多个(m)进程,每个进程响应n个请求。

        Prefork MPM和Worker MPM在非常繁忙的服务器应用下都有些不足。尽管HTTP的Keepalive方式能减少TCP连接数量和网络负载,但是 Keepalive需要和服务进程或者线程绑定,这就导致一个繁忙的服务器会耗光所有的线程。 Event MPM是解决这个问题的一种新模型,它把服务进程从连接中分离出来。在服务器处理速度很快,同时具有非常高的点击率时,可用的线程数量就是关键的资源限 制,此时Event MPM方式是最有效的。一个以Worker MPM方式工作的繁忙服务器能够承受每秒好几万次的访问量(例如在大型新闻服务站点的高峰时),而Event MPM可以用来处理更高负载。值得注意的是,Event MPM不能在安全HTTP(HTTPS)访问下工作。 

注意事项:httpd-2.2:Event MPM为测试使用。httpd-2.4:Event MPM可生产使用。


三、httpd-2.2的配置文件

    配置文件:

        /etc/httpd/conf/httpd.conf

        /etc/httpd/conf.d/*.conf

    服务脚本:

        /etc/rc.d/init.d/httpd

        配置文件:/etc/sysconfig/httpd(修改MPM)

    主程序文件:

        /usr/sbin/httpd(Prefork MPM)

        /usr/sbin/httpd.event(Event MPM)

        /usr/sbin/httpd.worker(Worker MPM)

    日志文件目录:

        /var/log/httpd

            access_log: 访问日志

            error_log:错误日志

    站点文档目录(默认,可自行修改配置文件):

        /var/www/html

    模块文件路径:

        /usr/lib64/httpd/modules


    配置文件的组成:

        ~]# grep "Section" /etc/httpd/conf/httpd.conf 

            ### Section 1: Global Environment(全局环境)

            ### Section 2: 'Main' server configuration('主'服务器配置)

            ### Section 3: Virtual Hosts(虚拟主机)


四、httpd-2.2的常用配置

httpd的配置文件为:/etc/httpd/conf/httpd.conf

①、修改监听的IP和Port

#Listen 12.34.56.78:80
Listen 80
#监听的IP为可选,如果不填写的为本机所有IP监听在此端口上。可以添加多条Listen。端口默认为80,不建议修改,
#因为修改后需要添加端口才能访问。一般内部的某个功能网站可以使用其他端口来供内部使用。修改完此项需要重启httpd服务


②、持久连接或非持久连接的配置(持久连接:连接建立,每个资源获取完成后不会断开连接,而是继续等待其它的请求完成;一般配置为最大数量限制的时候断开或最大空闲时间断开。持久连接的副作用,对并发访问量较大的服务器,持久连接功能会使用有些请求得不到响应;折衷的方法使用较短的持久连接时间。httpd-2.4 支持毫秒级持久时间)

KeepAlive { On | Off } 
#设置是否允许持久连接,On为允许,Off为不允许
MaxKeepAliveRequests 100
#设置持久连接允许请求的最大资源数量。设置为0,表示允许无限量。
KeepAliveTimeout 15
#持久链接超时时间,这里单位为秒。

这里我们可以是用一下方法来测试:

    telnet IP/HOST PORT(telnet 192.168.0.105 80)回车后输入一下命令:

    GET /URL HTTP/1.1(使用GET方法请求/URL的资源,使用HTTP1.1协议)

    Host: HOSTNAME or IP(请求/URL资源的主机或IP)

[root@localhost ~]# telnet 192.168.0.105 80
Trying 192.168.0.105...
Connected to 192.168.0.105.
Escape character is '^]'.
GET / HTTP/1.1
Host: 192.168.0.105

HTTP/1.1 403 Forbidden
Date: Tue, 15 Sep 2015 03:06:47 GMT
Server: Apache/2.2.15 (CentOS)
Accept-Ranges: bytes
Content-Length: 4954
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
	<head>
		<title>Apache HTTP Server Test Page powered by CentOS</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
..........

                        </div>
		</div>
</body>
</html>
Connection closed by foreign host.
#这里我开启了持久链接,然后KeepAliveTimeout 15,可以看到,当我请求完一个页面后15s不做请求会给服务断开


③、Multipath Process Module:多路处理模块

httpd-2.2不支持同时编译多个模块,所以只能编译时选定一个;rpm安装的包提供三个二进制程序文件,分别用于实现对不同MPM机制的支持。确认当前使用的MPM的方法:

[root@localhost ~]# ps aux  | grep httpd
root       8558  5.2  0.3 184324  3868 ?        Ss   10:56   0:00 /usr/sbin/httpd
apache     8561  0.0  0.2 184324  2456 ?        S    10:56   0:00 /usr/sbin/httpd
..........
apache     8562  0.0  0.2 184324  2456 ?        S    10:56   0:00 /usr/sbin/httpd
#默认为/usr/sbin/httpd, 使用的是Prefork MPM
[root@localhost ~]# httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c
#查看静态编译的模块
root@localhost ~]# httpd -M
Loaded Modules:
 core_module (static)
 ..........
 dnssd_module (shared)
Syntax OK
#查看静态编译及动态装载的模块


当我们需要切换到不同MPM模式运行时,可以修改/etc/sysconfig/httpd更换使用的httpd程序。

HTTPD=/usr/sbin/httpd.worker
#在代码中找到HTTPD此项目。然后更换为对应的MPM模式即可,修改完需要重启服务。


下面介绍httpd-2.2中参见的两种MPM配置介绍

Prefork MPM

<IfModule prefork.c>
StartServers       8
#服务启动后默认开启的进程数
MinSpareServers    5
#最小数量的服务器进程,保存备用
MaxSpareServers   20
#最大数量的服务器进程,保存备用
ServerLimit      256
#最大活动进程数,一般此项会大于最大并发数
MaxClients       256
#最大并发数,最大数量的工作线程
MaxRequestsPerChild  4000
#每个子进程在生命周期内所能够服务的最大请求个数
</IfModule>


Worker MPM

<IfModule worker.c>
StartServers         4
#服务启动后默认开启的进程数
MaxClients         300
#最大并发数,最大数量的工作线程
MinSpareThreads     25
#最小数量空闲线程,保存备用
MaxSpareThreads     75
#最大数量空闲线程,保存备用
ThreadsPerChild     25
#每个进程可生产的线程数
MaxRequestsPerChild  0
#每个子进程在生命周期内所能够服务的最大请求个数,0代表不限制
</IfModule>
#这里有一个奇怪的特性,就是当我们重启完服务后立即查看可以看到服务启动了4个进程数没有错。为我们配置的默认开启进
#程数,但是,如果过了几秒再重启查看服务进程时,会发现只剩下3个进程数,这是因为默认ThreadsPerChild(每个服务
#器进程生成的线程数量)为25,而MaxSpareThreads(最大数量的工作线程)为75,所以就只剩下3个进程。


④、配置指令实现模块加载(DSO)

        LoadModule <mod_name> <mod_path>

LoadModule version_module modules/mod_version.so
#LoadModule asis_module modules/mod_asis.so
#需要开启某个模块只需要把注释的#号去掉然后重新加载配置文件即可。这里我们可以看到,模块路径使用的是相对路径,
#相对于ServerRoot(/etc/httpd)指向的路径而言。


⑤、定义'Main' server的文档页面路径

DocumentRoot "/var/www/html"

文档路径映射:DocumentRoot指向的路径为URL路径的起始位置

例如:DocumentRoot "/var/www/html"

    /var/www/html/test/index.html --> http://HOST:PORT/test/index.html


⑥、站点访问控制,可基于两种类型的路径指明对哪些资源进行访问控制

    文件系统路径:

        <Directory ""> </Direcotry>

        <File ""> </File>

        <FileMatch ""> </FileMatch>

    URL路径:

        <Location ""> </Location>

            ...


访问控制机制:基于来源地址,基于账号(以下做详细说明)


⑦、Directory中“基于来源地址”实现访问控制

    (1) Options

        所有可用特性:Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews:

            Indexes: 索引;

            FollowSymlinks:允许跟踪符号链接文件;

            AllowOverride:在 AllowOverride 设置为 None 时, .htaccess 文件将被完全忽略。当此指令设置为 All 时,所有具有 “.htaccess” 作用域的指令都允许出现在 .htaccess 文件中。

<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
#这是比较常用的三个Options


    (2) 基于来源地址的访问控制机制

        Order:检查次序

            Order allow,deny(设置白名单)

            Order deny,allow(设置黑名单)

    这里的检查机制是这样的,以Order allow,deny说明。先把定义的所有Allow整合为一个,然后把所有定义的Deny整合为一个。然后先检查Order次序的allow有没有匹配的,如果仅有allow匹配则直接通过,如果allow没有,deny有则直接deny,如果allow,deny都有则以Order默认的deny掉,如果两个都没有匹配则以默认的deny为准。

<Directory "/var/www/icons">
    Order allow,deny
    Allow from all
</Directory>
#Allow from all:所有人可以访问
#Deny from 192.168.0.123:禁用一个IP访问
#Allow from 192.168.1.0/24:允许一个网段访问
Order Allow,Deny 
Allow from 192.168.1.0/24 
(Deny from all)
#只允许192.168.1.0/24这个网段访问
Order Deny,Allow 
Deny from 192.168.1.123
#不允许192.168.1.123这个IP访问。其它都允许


⑧、定义默认主页面

DirectoryIndex index.html index.php



⑨、日志设定

    错误日志:

            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

金步国翻译文档  :http://www.jinbuguo.com/apache/menu22/logs.html


⑩、路径别名

    Alias /URL/ "/PATH/TO/SOMEDIR/"

        Alias /bbs/ "/forum/htdocs"

            http://www.wlw.com/bbs/index.html --> /forum/htdocs/

Alias /wlw/icons/ '/var/www/icons/'


十一、设定默认字符集

AddDefaultCharset UTF-8


十二、基于用户的访问控制

    认证质询:WWW-Authenticate,响应码为401,拒绝客户端请求,并说明要求客户提供账号和密码;

    认证:Authorization,客户端用户填入账号和密码后再次发送请求报文;认证通过,则服务器发送响应的资源;

    认证类型:basic:明文。digest:消息摘要。

    安全域:需要用户认证后方能访问的路径;应该通过名称对其进行标识,并用于告知用户认证的原因;


    用户的账号和密码存储于何处?

        虚拟账号:仅用于访问某服务时用到的认证标识;

        存储:文本文件,SQL数据库,ldap,nis


basic认证:

    (1)提供账号和密码存储(文本文件)

        使用htpasswd命令进行管理

        htpasswd [options] passwordfile username

            -c: 自动创建passwordfile,因此,仅应该在添加第一个用户时使用;

            -m: md5加密用户密码;

            -s: sha1加密用户密码;

            -D: 删除指定用户

[root@localhost admin]# htpasswd -c -m /var/www/html/.htpasswd wlw
New password: 
Re-type new password: 
Adding password for user wlw
[root@localhost admin]# htpasswd -m /var/www/html/.htpasswd wlw1
New password: 
Re-type new password: 
Adding password for user wlw1
#这里我们添加了两个用户供后面做测试使用,第一次因为文件不存在使用-c选项生成,后面添加用户只需要指定-m,用md5加密即可


    (2) 定义安全域

<Directory "/var/www/html/admin">
        Options None
        AllowOverride None
        AuthType Basic
        AuthName "Admin private"
        AuthUserFile "/var/www/html/.htpasswd"
        Require user wlw
</Directory>
#这里我们AuthType认证方式为Basic,AuthName认证名为Admin private,AuthUserFile认证的用户名密码文本为,
#Require user指定允许生效的用户,如果需要文件中的所有用户都生效,可以是用Require valid-user。

当我们对某个目录定义了安全区域后,当我们打开页面后可以看到以下信息

wKiom1X66mfyVQk7AAJ69Fn4Vww287.jpg


如果我们不输入账号密码按取消的话这会,响应码为401,拒绝客户端请求,并说明要求客户提供账号和密码

wKioL1X67T2CM5ghAAIzRENQAn4649.jpg


只有当我们输入允许登录的账号密码的时候才能查访问到admin的文件

wKiom1X660uD--92AAFthGCK340200.jpg


    (3) 实现基于组进行认证

<Directory "/var/www/html/admin">
        Options None
        AllowOverride None
        AuthType Basic
        AuthName "Admin private"
        AuthUserFile "/var/www/html/.htpasswd"
        AuthGroupFile "/etc/httpd/conf.d/.htgroup"
        equire group wlwadmin
</Directory>
#这里需要提供:用户账号文件和组文件;账号文件:使用htpasswd命令生成。组文件:使用touch生成一个文件,
#然后在文件中每一行定义一个组:GRP_NAME:user1 user2 user3 ...


十三、虚拟主机

    有三种实现方案:

        基于ip:为每个虚拟主机准备至少一个ip地址;

        基于port:为每个虚拟主机准备至少一个专用port;实践中很少使用;

        基于hostname:为每个虚拟主机准备至少一个专用hostname(互联网上最为常用的实现虚拟主机方法)

        可混合使用上述三种方式中任意方式;

注意:一般虚拟主机不要与中心主机混用,所以,要使用虚拟主机,先禁用中心主机,禁用中心主机:注释DocumentRoot。

    每个虚拟主机都有专用配置:      

<VirtualHost "IP:PORT">
    SeverName:虚拟主机的别名
    DocumentRoot "":虚拟主机根目录
    ErrorLog:错误日志
    CustomLog:访问日志
    <Directory "">:虚拟主机站点访问控制
    Options FollowSymLinks
    AllowOverride None
    </Directory>
</VirtualHost>


    示例1:基于ip

<VirtualHost 192.168.0.105:80>
    ServerName web1.wlw.com
    DocumentRoot "/vhosts/web1/htdocs"
</VirtualHost>

<VirtualHost 192.168.0.105:80>
    ServerName web2.wlw.com
    DocumentRoot "/vhosts/web2/htdocs"
</VirtualHost>


    示例2:基于port

<VirtualHost 192.168.0.105:80>
    ServerName web2.wlw.com
    DocumentRoot "/vhosts/web2/htdocs"
</VirtualHost>

<VirtualHost 192.168.0.105:8080>
    ServerName web3.wlw.com
    DocumentRoot "/vhosts/web3/htdocs"
</VirtualHost>


    示例3:基于hostname

<VirtualHost 192.168.0.105:80>
    ServerName web1.wlw.com
    DocumentRoot "/vhosts/web1/htdocs"
</VirtualHost>

<VirtualHost 192.168.0.105:80>
    ServerName web3.wlw.com
    DocumentRoot "/vhosts/web3/htdocs"
</VirtualHost>


十四、内置的status页面

<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from 192.168.0.0/24
</Location>	
#此status页面能看到httpd的各信息,建议只开放内网,如果需要外网连接建议基于账号实现访问控制,添加完此配置后重新
#加载配置文件。这里我们可以使用http: //192.168.0.109/server-status?refresh=3 给页面传递每三秒刷新一次的需求。

wKiom1X99o7CpPVGAAewH38OsvQ832.jpg


十五、MIME类型文件和指定缺省MIME类型

TypesConfig /etc/mime.types
#TypeConfig用于设置保存有不同的MIME类型数据的文件名
[root@wlw3 wlw]vim /etc/mime.types
text/plain                              asc txt text pm el c h cc hh cxx hxx f90
........
application/octet-stream                bin lha lzh exe class so dll img iso
DefaultType text/plain
#如果Web服务器不能决定一个文档的缺省类型,这通常表示文档使用了非标准的后缀,那么服务器就使用 DefaultType定义的MIME类型将文档发送给客户浏览器。这里的设置为text/plain,如果服务器不能判断出文档的MIME,那么大部分情况下这个文档为一个二进制文档,但使用 text/plain格式发送回去,浏览器将在内部打开它而不会提示保存。因此建议将这个设置更改为 application/octet-stream,这样浏览器将提示用户进行保存。


十六、为特定后缀的文件指定MIME类型

AddType application/x-httpd-php3 .phtml
#AddType参数可以为特定后缀的文件指定MIME类型,这里的设置将覆盖mime.types中的设置


十七、错误页是否输出服务器操作系统名称

ServerTokens OS
#在出现错误页的时候是否显示服务器操作系统的名称,ServerTokens Prod为不显示