参考:

    http://httpd.apache.org/docs/

    http://www.cnblogs.com/huangye-dream/p/3550328.html(nginx和apache优缺点对比)

    http://www.kegel.com/c10k.html  (c10k问题)

    http://apr.apache.org/  (apr介绍)

    http://httpd.apache.org/docs/2.4/howto/auth.html(认证与授权)

  http://blog.csdn.net/flightsmallbird/article/details/72900817 CGI、服务器内置模块、FastCGI、php-fpm的区别)


简介:   

     httpd是世界上最流行的的web软件之一。一般人们也把它叫做apache,这是因为Apache源于NCSAhttpd服务器,NCSA在项目完成后解散了团队。但是团队里的成员对这个软件却有了感情,经常对其修修补补。 Apache取自“a patchy server”的读音,意思是充满补丁的服务器,后来apache发展成了一个软件基金会,维持很多开源项目。所以当提到apache的时候一般包含两个含义: 一个是apache软件基金会,一个是开源web软件httpd。

    另外一个很流行的web软件是nginx,nginx能解决“c10k” 问题,配置简单,高效,但是它的特性没有apache多,又不如apache稳定,所以一般用nginx作为前端处理静态请求,而apache作为后端,处理一些动态请求,两者占据了web市场的大量份额。


安装:

    我们知道一个电源,灯泡,开关组合的电路可以通过控制开关的闭合来控制灯泡的亮和灭,这是最简单的电路。后来人们可以设计更复杂的电路来控制灯泡的显示状态(比如2个开关控制四个灯的状态,电压的高低来控制灯泡亮的程度),但是它们都有一个共同点:输入一样,输出也一样。 人们在长期的实验中发现了“简单就是美”的真理。 于是都只用高低电平来控制灯泡的显示状态,并不管其亮的程度,也就是只管亮与否,不管有多亮,并结合到数学中,用0/1来标记两种状态,而计算机就是无数个这种简单的电子电路集成的一种东西。这也是为什么计算机只识别二进制的原因,其实可以做成十进制或其他进制,但是其他进制没有像二进制这样,容错率高(比如,要控制有没有电压,显然比控制电压到某个值要简单的多得多)。 

    所以,计算机最直接能识别的就是01代码。但是01代码毫无意义,不利于人类的识别记忆。所以人们给固定的01数字串赋予某个意义,抽象出一个层次,使其不同的数字串结合产生对应的计算机输入,编写程序让这些有意义的字符与01代码自动转换,也就是汇编语言。这样人类的工作量就大大降低了,但是汇源语言还是过于底层,所以人们在其之上根据自身需求还继续抽象出了各种各样的编程语言,比如c,perl等。 每个层次之间的交流通道叫做api(就相当于我扎你一下,你会疼,但是我可以用针扎,用手戳,用各种各样的方法。我这些方法就是所谓的封装,你允许我扎的地方就是所谓的接口,我还可以做个工具给别人,让别人也可以扎你,我给别人这个工具也是接口)

但是,每个硬件的厂商不一样,做出来的接口也就不一样。 httpd把web和底层的接口分开编译,用apr(apache portable runtime)为web的编译提供一模一样的接口,让其忽略底层硬件架构的不同,也就是httpd可以在任何平台上编译,只要那个平台装了apr,所以要装httpd,必须先装apr。

        wget  http://mirror.bit.edu.cn/apache//httpd/httpd-2.4.27.tar.bz2
	wget  http://mirrors.tuna.tsinghua.edu.cn/apache//apr/apr-1.6.2.tar.gz
	wget  http://mirrors.tuna.tsinghua.edu.cn/apache//apr/apr-util-1.6.0.tar.gz
	tar xf httpd-2.4.27.tar.bz2
	tar xf apr-1.6.2.tar.gz 
	mv  apr-1.6.2  /usr/local/src/httpd-2.4.27/srclib/apr  (httpd默认会在自己家目录的srclib/apr下找apr)
	tar xf apr-util-1.6.0.tar.gz 
	mv apr-util-1.6.0 /usr/local/src/httpd-2.4.27/srclib/apr-util(同apr)
	cd /usr/local/src/httpd-2.4.27/
	./configure --prefix=/usr/local/httpd --sysconfdir=/etc/httpd/conf   --with-included-apr   --with-included-apr-util --enable-mpms-shared=all  
		--sysconfdir:表示httpd的配置文件放在哪
		--enable-mpms-shared:表示把多处理模块编译成动态模块,如果静态编译的话只能默认使用某一个,rpm包中,redhat官方,在/usr/sbin下分别对应编译生成了httpd(prefork模型),httpd.worker httpd.event)
	make 
	make install
	#输出二进制文件路径
	[root@cqhdtest httpd]#vim /etc/profile.d/httpd.sh
	export  PATH=/usr/local/httpd/bin:$PATH
	[root@cqhdtest httpd]#. /etc/profile.d/httpd.sh
	#输出头文件和库文件
	[root@cqhdtest httpd]# ln -s /usr/local/httpd/include  /usr/include/httpd
	[root@cqhdtest httpd]# vi /etc/ld.so.conf.d/httpd.conf
	/usr/local/httpd/lib
	[root@cqhdtest httpd]# ldconfig -v (生成共享库缓存)
	/usr/local/httpd/lib:
	libaprutil-1.so.0 -> libaprutil-1.so.0.6.0
	libapr-1.so.0 -> libapr-1.so.0.6.2
	#生成服务脚本(源码包里默认有提供,只是需要修改下脚本)
	cp   /usr/local/src/httpd-2.4.27/build/rpm/httpd.init  /etc/init.d/httpd
	chmod +x /etc/init.d/httpd
	[root@cqhdtest]# vi /etc/sysconfig/httpd
	HTTPD=/usr/local/httpd/bin/httpd
	PIDFILE=/usr/local/httpd/logs/httpd.pid
	#最少必须修改这两个变量,/etc/sysconfig/httpd其实是/etc/init.d/httpd的配置文件,因为脚本默认会在/usr/sbin查找httpd可执行程序,所以必须修改这个变量,pidfile也可以不用/etc/sysconfig/httpd设置,直接httpd.conf修改为默认的pid文件位置。

这里贴上httpd脚本备用:

#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# httpd        Startup script for the Apache Web Server
#
# chkconfig: - 85 15
# description: The Apache HTTP Server is an efficient and extensible  \
#             server implementing the current HTTP standards.
# processname: httpd
# pidfile: /var/run/httpd.pid
# config: /etc/sysconfig/httpd
#
### BEGIN INIT INFO
# Provides: httpd
# Required-Start: $local_fs $remote_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Should-Start: distcache
# Short-Description: start and stop Apache HTTP Server
# Description: The Apache HTTP Server is an extensible server 
#  implementing the current HTTP standards.
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

# What were we called? Multiple instances of the same daemon can be
# created by creating suitably named symlinks to this startup script
prog=$(basename $0 | sed -e 's/^[SK][0-9][0-9]//')

if [ -f /etc/sysconfig/${prog} ]; then
        . /etc/sysconfig/${prog}
fi

# Start httpd in the C locale by default.
HTTPD_LANG=${HTTPD_LANG-"C"}

# This will prevent initlog from swallowing up a pass-phrase prompt if
# mod_ssl needs a pass-phrase from the user.
INITLOG_ARGS=""

# Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server
# with the thread-based "worker" MPM; BE WARNED that some modules may not
# work correctly with a thread-based MPM; notably PHP will refuse to start.

httpd=${HTTPD-/usr/sbin/httpd}
pidfile=${PIDFILE-/var/run/${prog}.pid}
lockfile=${LOCKFILE-/var/lock/subsys/${prog}}
RETVAL=0

# check for 1.3 configuration
check13 () {
	CONFFILE=/etc/httpd/conf/httpd.conf
	GONE="(ServerType|BindAddress|Port|AddModule|ClearModuleList|"
	GONE="${GONE}AgentLog|RefererLog|RefererIgnore|FancyIndexing|"
	GONE="${GONE}AccessConfig|ResourceConfig)"
	if grep -Eiq "^[[:space:]]*($GONE)" $CONFFILE; then
		echo
		echo 1>&2 " Apache 1.3 configuration directives found"
		echo 1>&2 " please read @docdir@/migration.html"
		failure "Apache 1.3 config directives test"
		echo
		exit 1
	fi
}

# The semantics of these two functions differ from the way apachectl does
# things -- attempting to start while running is a failure, and shutdown
# when not running is also a failure.  So we just do it the way init scripts
# are expected to behave here.
start() {
        echo -n $"Starting $prog: "
        check13 || exit 1
        LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd $OPTIONS
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && touch ${lockfile}
        return $RETVAL
}
stop() {
	echo -n $"Stopping $prog: "
	killproc -p ${pidfile} -d 10 $httpd
	RETVAL=$?
	echo
	[ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}
reload() {
	echo -n $"Reloading $prog: "
	check13 || exit 1
	killproc -p ${pidfile} $httpd -HUP
	RETVAL=$?
	echo
}

# See how we were called.
case "$1" in
  start)
	start
	;;
  stop)
	stop
	;;
  status)
        if ! test -f ${pidfile}; then
            echo $prog is stopped
            RETVAL=3
        else  
            status -p ${pidfile} $httpd
            RETVAL=$?
        fi
        ;;
  restart)
	stop
	start
	;;
  condrestart)
	if test -f ${pidfile} && status -p ${pidfile} $httpd >&/dev/null; then
		stop
		start
	fi
	;;
  reload)
        reload
	;;
  configtest)
        LANG=$HTTPD_LANG $httpd $OPTIONS -t
        RETVAL=$?
        ;;
  graceful)
        echo -n $"Gracefully restarting $prog: "
        LANG=$HTTPD_LANG $httpd $OPTIONS -k $@
        RETVAL=$?
        echo
        ;;
  *)
	echo $"Usage: $prog {start|stop|restart|condrestart|reload|status|graceful|help|configtest}"
	exit 1
esac

exit $RETVAL


httpd配置文件简介:

    httpd配置文件主要是httpd编译时设置的家目录下的conf里面的httpd.conf

    httpd.conf的是由一堆配置指令组成的,它的一个配置片段如下

# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
#DocumentRoot "/usr/local/httpd/htdocs"
DocumentRoot "/var/www/html"

    以#号+单空格开头的表示注释, #后不接空格,表示后面是可用的指令,但是并不启用(比如上面的#DocumentRoot)所有的指令都可以通过http://httpd.apache.org/docs/2.4/mod/quickreference.html 查看详细帮助

    非#开头的表示正式启用的配置。

httpd的虚拟主机简介:

    有时候我们会遇到这种情况:我们需要一个网站,但是这个网站访问量很小,用一个物理机太浪费,不用又不行。而且如果仅仅需要一两个这种网站浪费就浪费点也就算了,要是同时拥有多个这种站点,那么付出的代价就很客观了。

于是,虚拟主机就应运而生了。所谓虚拟主机,就是一台物理机同时开多个站点,因为一个站点对应一台主机,这个主机并不是真正意义上的主机,所以称之为虚拟主机。

    一台物理机开多个站点,这些站点必须要有唯一的标识符来标识它们。一般有以下三种类型:

    1.基于端口的虚拟主机

        使用相同的ip,以不同的端口来区分各站点

    2.基于ip的虚拟主机

        监听不同的ip,根据ip来区分各主机

    3.基于域名的虚拟主机

        因为1、2两种类型要么没有那么多ip,要么使用其他端口与我们习惯不符,所以催生了这一种类型的虚拟主机。

    这种类型的主机基于http协议的host头部,当数据包进来的时候,进程根据这个头部来区分各虚拟主机(因为tcp包的首部都一样,所以只能在http头部进行标识区分)


下面是vhost的一个案例:


    DocumentRoot "/var/www/a"
    ServerName www.a.com
    ServerAlias www.aa.com

    AllowOverride None
    Options None
    Require all granted





    DocumentRoot "/var/www/b"
    ServerName www.b.com


apache的虚拟主机配置是以指令开头和结尾的,中间可以包含许多指令。

    以上述段为例,DocumentRoot指定了网站的根目录,SeverName指定了网站的域名。apache的配置遵循“匹配范围小优先生效原则”,就是说,假设你在全局配置段也配置了DocumentRoot “/tmp/www" ,那么当访问www.a.com的时候,进程会去/var/www/a找web文件,当没匹配到www.a.com或者www.b.com的时候就会到全局配置里面的/tmp/www里面找。

    这里www.a.com的virtualhost还加了Directory的原因是为了和www.b.com对比区分。apache 2.4默认没有设置对目录权限的话会禁止访问,提示403错。


apache的模块使用简介:

    apache的一大特点是很多功能都可以通过模块动态加载,模块的使用方法也很简单,使用LoadModule指令加载,再利用IfModule指令配置模块的使用参数即可

格式:

LoadModule    MODULE_NAME   MODULE_PATH

指令1  参数

指令2  参数

...

MODULE_NAME:表示模块的名称(应该是可以自定义的,IfModule匹配的时候对应即可,未测试)

MODULE_PATH:模块所在的路径,可以使用相对路径,也可以使用绝对路径


httpd的认证与授权: http://httpd.apache.org/docs/2.4/howto/auth.html



    AllowOverride None

    Options Indexes

    AuthType Basic

    AuthName "test"

    AuthBasicProvider file

    AuthUserFile "/usr/local/httpd/passwords"

    Require user linzb


    options:指明在目录中允许的动作,indexes表示允许

    AuthType:表示认证类型,Basic表示使用mod_auth_basic模块的实现,类似的还有digest等

    AuthName:这个自己记忆用,随意取,可以不写

    AuthBasicProvider:认证的提供者,有file,dbm等,这里使用file这种简洁但是不安全的做法

    AuthUserFile:认证文件的位置

    Require:授权要求,有user,group等


    不难理解,在设置网站用户认证的时候,要事先用htpasswd -c /usr/local/httpd/passwords  linzb 命令生成用户名和密码的认证文件


httpd与php的结合:

1.基于模块的方式:http://php.net/manual/en/install.unix.apache2.php

    php的安装:

        wget  http://cn2.php.net/distributions/php-7.1.7.tar.bz2

        tar xf php-7.1.7.tar.bz2

        cd php-7.1.7

        ./configure  --with-apxs2=/usr/local/httpd/bin/apxs   && make && make install

        cp php.ini-development /usr/local/lib/php.ini

    httpd的配置:

    vi  /etc/httpd/conf/httpd.conf # 增加以下几行

     ---------------------------------------------------

        LoadModule php7_module        modules/libphp7.so

        

        SetHandler application/x-httpd-php

        

    ----------------------------------------------------

2.基于fastcgi的方式:

    这里使用mod_proxy_fcgi.so, 用mod_fastcgi.so配置起来比较繁琐

    php的安装:

    wget  http://cn2.php.net/distributions/php-7.1.7.tar.bz2

    tar xf php-7.1.7.tar.bz2

    cd php-7.1.7

    ./configure  --with-apxs2=/usr/local/httpd/bin/apxs  --enable-fpm  && make && make install

    cp php.ini-development /usr/local/lib/php.ini

    cp sapi/fpm/init.d.php-fpm.in  /etc/init.d/php-fpm

    chmod +x /etc/init.d/php-fpm

    vi /etc/init.d/php-fpm  # 修改三个地方

----------------------------------------------

    prefix=

    php_fpm_BIN=/usr/local/sbin/php-fpm

    php_fpm_CONF=/usr/local/etc/php-fpm.conf

    php_fpm_PID=/var/run/php-fpm.pid

----------------------------------------------

    vi /usr/local/etc/php-fpm.conf

;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;

[global]
pid = /var/run/php-fpm.pid
error_log = /var/log/php-fpm.log
log_level = warning
emergency_restart_threshold = 30
emergency_restart_interval = 60s
process_control_timeout = 5s
daemonize = yes

;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
;;;;;;;;;;;;;;;;;;;;

[www]
listen = 127.0.0.1:9000
listen.backlog = -1
listen.owner = www
listen.group = www
user = www
group = www

pm = dynamic
pm.max_children = 256
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 32
pm.max_requests = 2048
pm.process_idle_timeout = 10s
request_terminate_timeout = 120
request_slowlog_timeout = 20

pm.status_path = /php-fpm_status
slowlog = log/slow.log
rlimit_files = 51200
rlimit_core = 0

catch_workers_output = yes
;env[HOSTNAME] = your_uname
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

    /etc/init.d/php-fpm start

httpd的配置:

    vi  /etc/httpd/conf/httpd.conf # 增加以下几行

--------------------------------------------------------

    LoadModule proxy_module modules/mod_proxy.so   #mod_proxy_fcgi.so依赖于这个模块

    LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

    

    SetHandler  "proxy:fcgi://127.0.0.1:9000"

    

----------------------------------------------------------

3.基于cgi的方式

    不好用,而且操作复杂,这里不写,只是提醒自己还有这么一种


cgi、fastcgi和基于模块方式的对比:

    以我个人看过的文档和视频,我的理解是这样:

    使用cgi的时候,当一个动态页面请求到来的时候,http都要请求操作系统生成一个cgi进程去解释执行动态脚本,这种方式资源消耗大,执行效率低,所以,后来人们把执行动态脚本的功能做成模块。模块的方式,系统消耗变小了,执行效率也比较高,但是这种方式有个缺点,对php配置的修改,要重启httpd才能生效,而且当执行php出现了问题的时候,httpd进程也随之受到影响,所以就有了第三种:fastcgi。   fastcgi其实是在cgi的基础上,多了个进程专门管理cgi解释器的生成执行销毁等,以后当有请求进来的时候,httpd直接把请求交给fastcgi管理进程,这样httpd和php的执行效率都得到了提高,而且故障发生时互不影响,所以一般建议使用fastcgi的方式

具体可以参考:http://blog.csdn.net/flightsmallbird/article/details/72900817


httpd的ssl配置:

vi httpd.conf

---------------------------------

LoadModule ssl_module modules/mod_ssl.so

Include /etc/httpd/conf/extra/ssl.conf

---------------------------------------

[root@cqhdtest extra]# cat ssl.conf 

Listen 443

DocumentRoot "/usr/local/httpd/htdocs"

ServerName www.a.com:443

SSLEngine on

SSLCertificateFile "/etc/httpd/conf/httpd.crt"

SSLCertificateKeyFile "/etc/httpd/conf/httpd.key"

 

参考(个人笔记):http://linzb.blog.51cto.com/5192423/1870944  (CA)

    http://linzb.blog.51cto.com/5192423/1868280 (加密)