打算写一篇关于httpd的文档,不由得就想到了TCP/IP协议、http协议、socket、域名解析、负载均衡......
那就从这开始写吧,但是我又想到了更多:IPC、端口、httpd的工作模式、httpd的连接模式、虚拟主机、反向代理......
想了这么多,我居然不知道该如何下笔了。于是心里最底层的懒散就开始作祟了,进而一拖再拖,一度有索性不写的想法。
这不是个好的想法,最后决定,就从最直接的实战演练开始吧。
本来我觉得介绍httpd,应该有大量的篇幅来说明前期的理论。但是水平有限,不能系统分类的来说明。
以下就从具体的操作步骤入手,然后在配置中夹杂相关理论。
说明一点:Apache和httpd的区别
Apache:Apache软件基金会(也就是Apache Software Foundation,简称为ASF),是专门为运作一个开源软件项目的Apache 的团体提供支持的非盈利性组织,这个开源软件的项目就是 Apache 项目。
httpd:httpd是超文本传输协议(HTTP)服务器的主程序。被设计为一个独立运行的后台进程,它会建立一个处理请求的子进程或线程的池。说白了,httpd是Apache组织下维护的一个开源软件。
本文大纲:
1、前期准备
RHEL6.7、关闭ipables、selinux、yum源配置
2、安装
yum安装
安装包介绍
3、程序环境
配置文件
服务脚本
主程序文件
日志文件
模块文件路径
服务控制和启动
4、配置
修改监听的IP和PORT
持久连续
MPM
虚拟主机
......
1、前期准备
Linux系统版本为RHEL6.7
IP为10.10.10.4
[root@wlm yum.repos.d]# cat /etc/issue Red Hat Enterprise Linux Server release 6.7 (Santiago) Kernel \r on an \m
关闭ipables、selinux
修改selinux的配置文件,关闭selinux后重启电脑
[root@wlm yum.repos.d]# /etc/init.d/iptables stop iptables: Setting chains to policy ACCEPT: filter [ OK ] iptables: Flushing firewall rules: [ OK ] iptables: Unloading modules: [ OK ] [root@wlm yum.repos.d]# setenforce=0 # 不重启关闭selinux,这个设置只对当前shell有效,从新登陆或是切换用户、打开子shell,在开启 [root@wlm yum.repos.d]# chkconfig iptables off # 永久关闭iptables [root@wlm yum.repos.d]# sed -i s/=enforcing/=disabled/g /etc/selinux/config #从新启动电脑,selinux永久关闭
yum源配置
配置本地yum源
[root@wlm yum.repos.d]# rm -f /etc/yum.repos.d/* [root@wlm yum.repos.d]# vim /etc/yum.repos.d/yum.repo [yum] name=RHEL6.7 baseurl=file:///media/cdrom enabled=1 gpgcheck=0 [root@wlm yum.repos.d]# mkdir /media/cdrom [root@wlm yum.repos.d]# mount /dev/cdrom /media/cdrom/ mount: block device /dev/sr0 is write-protected, mounting read-only
2、安装
安装包介绍
安装版本httpd-2.2
yum安装
在安装前使用rpm -q httpd查看httpd-2.2是否被安装,若已经安装了其他版本的,
使用rpm -e httpd卸载
yum install httpd # RHEL6.7默认安装的是httpd-2.2
3、程序环境
配置文件:
/etc/httpd/conf/httpd.conf
/etc/httpd/conf.d/*.conf
服务脚本:
/etc/rc.d/init.d/httpd
脚本配置文件:/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
服务控制和启动:
chkconfig httpd on|off
service {start|stop|restart|status|configtest|reload} httpd
4、配置
1)修改监听的IP和PORT
套接字通信(Socket):IPC(进程间通信)的一种实现,允许位于不同主机(也可以是同一主机)上的进程之间进行通信;
Socket API(封装了内核中的socket通信相关的系统调用)
Web服务器就是C/S架构,基于套接字通信的机制。
配置说明:
Listen [IP:]PORT
(1) 省略IP表示为0.0.0.0,代表本机所有IP;
(2) Listen指令可重复出现多次;
Listen 80
Listen 8080
(3) 修改监听socket,重启服务进程方可生效;
实际操作:
[root@wlm yum.repos.d]# vim /etc/httpd/conf/httpd.conf # Listen 12.34.56.78:80 Listen 80 # 监听本机所有IP的80和8080端口 Listen 8080 [root@wlm ~]# httpd -t # 语法检测 httpd: apr_sockaddr_info_get() failed for wlm # #此错误忽略,是因为没有设置ServerName,后面会讲 httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName Syntax OK [root@wlm yum.repos.d]# /etc/init.d/httpd restart # 重启进程 Stopping httpd: [FAILED] Starting httpd: httpd: apr_sockaddr_info_get() failed for wlm #此错误忽略,是因为没有设置ServerName,后面会讲 httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName [ OK ]
测试:从浏览器访问,默认是访问80端口,出现的是默认测试页面
2)持久连续
保持连接(长连接):keep-alive通过特定的时间和请求资源数量来限制
非保持连接(短连接):一次资源请求一次连接(三次握手四次挥手)
tcp的短连接是每请求一次资源,就进行三次握手和四次挥手,这样太繁琐,所以httpd可以在服务器端设置持久连接。
持久连续(Persistent Connection):tcp连续建立后,每个资源获取完成后不全断开连接,而是继续等待其它资源请求的进行;
如何断开?
数量限制
时间限制
副作用:对并发访问量较大的服务器,长连接机制会使得后续某些请求无法得到正常 响应;
折衷:使用较短的持久连接时长,以及较少的请求数量;
配置说明:
KeepAlive On|Off #是否打开长连接
KeepAliveTimeout 15 #长连接时间,默认是S
MaxKeepAliveRequests 100 #数量限制,100个请求以内
测试方式:
telnet WEB_SERVER_IP PORT
GET /URL HTTP/1.1
Host: WEB_SERVER_IP
实际操作:
[root@wlm yum.repos.d]# vim /etc/httpd/conf/httpd.conf KeepAlive On # 开启 KeepAliveTimeout 15 # 15s的长连接 # 重新载入配置: [root@wlm yum.repos.d]# /etc/init.d/httpd reload Reloading httpd: # 测试: [root@ns1 named]# telnet 10.10.10.4 80 Trying 10.10.10.4... Connected to 10.10.10.4. Escape character is '^]'. GET /index.html HTTP/1.1 # 输入 Host:10.10.10.4 # 输入,然后两次回车,会连接15s后断开
3)MPM 模块
MPM:Multipath processing Modules (多路处理模块)
(1)prefork:多进程模型,每个进程响应一个请求;
一个主进程:负责生成子进程及回收子进程;负责创建套接字;负责接收请求,并将其派发给某子进程进行处理;
n个子进程:每个子进程处理一个请求;
工作模型:会预先生成几个空闲进程,随时等待用于响应用户请求;最大空闲和最小空闲;
(2)worker:多进程多线程模型,每线程处理一个用户请求;
一个主进程:负责生成子进程;负责创建套接字;负责接收请求,并将其派发给某子进程进行处理;
多个子进程:每个子进程负责生成多个线程;
每个线程:负责响应用户请求;
并发响应数量:m*n
m:子进程数量
n:每个子进程所能创建的最大线程数量;
(3)event:事件驱动模型,多进程模型,每个进程响应多个请求;
一个主进程 :负责生成子进程;负责创建套接字;负责接收请求,并将其派发给某子进程进行处理;
子进程:基于事件驱动机制直接响应多个请求;
httpd-2.2: 仍为测试使用模型;
httpd-2.4:event可生产环境中使用;
httpd-2.2不支持同时编译多个MPM模块,所以只能编译选定要使用的那个;CentOS 6的rpm包为此专门提供了三个应用程序文件,httpd(prefork), httpd.worker, httpd.event,分别用于实现对不同的MPM机制的支持;确认现在使用的是哪下程序文件的方法:
ps aux | grep httpd
默认使用的为/usr/sbin/httpd,其为prefork的MPM模块 ;
查看httpd程序的模块列表:
查看静态编译的模块:
# httpd -l
查看静态编译及动态编译的模块:
# httpd -M
更换使用httpd程序,以支持其它MPM机制;
vim /etc/sysconfig/httpd
HTTPD=/usr/sbin/httpd.{worker,event}
注意:重启服务进程方可生效
MPM配置:/etc/httpd/conf/httpd.conf
prefork的配置
StartServers 8 # 服务器刚启动是就启动多少个空闲进程
MinSpareServers 5 # 最小空闲进程数
MaxSpareServers 20 # 最大空闲进程数
ServerLimit 256 # 最大启动多少个进程
MaxClients 256 # 最大启动多少个进程响应客户端请求。最大并发数
MaxRequestsPerChild 4000 # 每个进程最多可以处理多少个请求,达到4000个就销毁一个进程
worker的配置:
StartServers 4 # 服务器刚启动是就启动多少个空闲进程
MaxClients 300 # 最大启动多少个进程响应客户端请求。最大并发数
MinSpareThreads 25 # 最小空闲进程数
MaxSpareThreads 75 # 最大空闲进程数
ThreadsPerChild 25 # 每个进程最大可生成多少个线程
MaxRequestsPerChild 0 # 进程处理的请求数量不受限制
PV:Page View:日点击量,有多少个页面被点击
实际操作:
[root@wlm yum.repos.d]# ps aux | grep httpd #默认为prefork模式 root 6236 0.0 0.4 186024 4340 ? Ss 17:04 0:01 /usr/sbin/httpd apache 6326 0.0 0.3 186024 2940 ? S 17:35 0:00 /usr/sbin/httpd apache 6327 0.0 0.2 186024 2584 ? S 17:35 0:00 /usr/sbin/httpd [root@wlm ~]# httpd -l Compiled in modules: core.c prefork.c http_core.c mod_so.c [root@wlm ~]# httpd -M httpd: apr_sockaddr_info_get() failed for wlm httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName Loaded Modules: core_module (static) mpm_prefork_module (static) http_module (static) so_module (static) auth_basic_module (shared) ... [root@wlm ~]# vim /etc/sysconfig/httpd HTTPD=/usr/sbin/httpd.worker # 默认是prefork模式,启用为worker模式 # 保存退出 [root@wlm ~]# vim /etc/httpd/conf/httpd.conf # 可以在这里优化,具体的介绍看上面的理论说明StartServers 4 MaxClients 300 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 # 保存退出,重启生效,切记,从起前要进行语法检测
4)DSO(dynamic shared object):动态共享对象
配置指定实现模块加载/etc/httpd/conf/httpd.conf
LoadModule
模块文件路径可使用相对路径:
相对于ServerRoot(默认/etc/httpd)
[root@wlm ~]# vim /etc/httpd/conf/httpd.conf # LoadModule foo_module modules/mod_foo.so #可以直接指定要加载的模块 # LoadModule auth_basic_module modules/mod_auth_basic.so LoadModule auth_digest_module modules/mod_auth_digest.so LoadModule authn_file_module modules/mod_authn_file.so LoadModule authn_alias_module modules/mod_authn_alias.so LoadModule authn_anon_module modules/mod_authn_anon.so LoadModule authn_dbm_module modules/mod_authn_dbm.so LoadModule authn_default_module modules/mod_authn_default.so LoadModule authz_host_module modules/mod_authz_host.so LoadModule authz_user_module modules/mod_authz_user.so
5)定义'Main' server的文档页面路径
在/etc/httpd/conf/http.conf
DocumentRoot ""
例如:
DocumentRoot "/web/host1"
文档路径映射:
DoucmentRoot指向的路径为URL路径的起始位置
其相当于站点URL的根路径;
(FileSystem) /web/host1/index.html --> (URL) /index.html
/web/host1/相当于是httpd服务的跟了,例如我们访问的是系统目录/web/host1/下的index.html,
在使用http协议访问时,直接写在:http://10.10.10.4/index.html
实际操作:
[root@wlm ~]# vim /etc/httpd/conf/httpd.conf DocumentRoot "/var/www/html" # 默认为/var/www/html目录 # 改为/web/目录下,首先得创建web目录,然后书写一个index.html文件 DocumentRoot "/web" ... # # Note that from this point forward you must specifically allow # particular features to be enabled - so if something's not working as # you might expect, make sure that you have specifically enabled it # below. # # # This should be changed to whatever you set DocumentRoot to. ## 这里一并改掉 # 保存退出 # 重新加载httpd服务器 [root@wlm ~]# httpd -t httpd: apr_sockaddr_info_get() failed for wlm httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName Syntax OK [root@wlm ~]# /etc/init.d/httpd reload Reloading httpd:
# 测试(确保selinux和iptables是关闭的,且/web目录下有index.html文件)
6)站点访问控制常见机制
中“基于源地址”实现访问控制:
(1) Options
后跟1个或多个以空白字符分隔的“选项”列表;
Indexes:指明的URL路径下不存在与定义的主页面资源相符的资源文件时,返回索引列表给用户;
Options Indexes FollowSymLinks
Options FollowSymLinks
FollowSymLinks:允许跟踪符号链接文件所指向的源文件;
None:
All:
Options #不要index,也不要符号链接文件
(2) AllowOverride
与访问控制相关的哪些指令可以放在.htaccess文件(每个目录下都可以有一个)中;
All: 所有的都放进去
None:都不放进去
(3) order和allow、deny:对源IP地址的访问控制
order:定义生效次序;写在后面的表示默认法则;
Allow from, Deny from
来源地址:
可以直接填写IP
也可以填写网段NetAddr:例如:
172.16
172.16.0.0
172.16.0.0/16
172.16.0.0/255.255.0.0
使用说明:这里我们一般不做更改,使用默认设置
Options Indexes FollowSymLinks AllowOverride None Order allow,deny Allow from all
7)定义站点主页面
DirectoryIndex index.html index.html.var
8)定义路径别名
格式:
Alias /URL/ "/PATH/TO/SOMEDIR/"
使用说明:
Alias /down/ "/var/www/html/" #定义down的别名路径是/var/www/html,当在浏览器访问http://10.10.10.4/down,实则是访问/var/www/html目录下
9)设定默认字符集和ServerName
AddDefaultCharset UTF-8
中文字符集:GBK, GB2312, GB18030
ServerName为要访问的域名,通过请求报文的头文件里包含的信息识别
ServerName www.wlm.com:80
10)日志设定
日志类型:访问日志 和 错误日志
错误日志:
ErrorLog logs/error_log # 错误日志,默认配置,在/etc/httpd/logs
LogLevel warn # 默认级别
访问日志
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog logs/access_log combined
LogFormat format strings:
http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#formats
%h:客户端IP地址;
%l:Remote User, 通常为一个减号(“-”);
%u:Remote user (from auth; may be bogus if return status (%s) is 401);非为登录访问时,其为一个减号;
%t:服务器收到请求时的时间;
%r:First line of request,即表示请求报文的首行;记录了此次请求的“方法”,“URL”以及协议版本;
%>s:响应状态码;
%b:响应报文的大小,单位是字节;不包括响应报文的http首部;
%{Referer}i:请求报文中首部“referer”的值;即从哪个页面中的超链接跳转至当前页面的;
%{User-Agent}i:请求报文中首部“User-Agent”的值;即发出请求的应用程序;
11)基于用户的访问控制
basic认证配置示例:
基于用户:
(1) 定义安全域
Options None
AllowOverride None
AuthType Basic
AuthName "String“
AuthUserFile "/PATH/TO/HTTPD_USER_PASSWD_FILE"
Require user username1 username2 ...
允许账号文件中的所有用户登录访问:
Require valid-user
(2) 提供账号和密码存储(文本文件)
使用专用命令完成此类文件的创建及用户管理
htpasswd [options] /PATH/TO/HTTPD_PASSWD_FILE username
-c:自动创建此处指定的文件,因此,仅应该在此文件不存在时使用;
-m:md5格式加密
-s: sha格式加密
-D:删除指定用户
基于组(非用户主,自定义组和组用户)账号进行认证;
(1)定义安全域
Options None
AllowOverride None
AuthType Basic
AuthName "String“
AuthUserFile "/PATH/TO/HTTPD_USER_PASSWD_FILE"
AuthGroupFile "/PATH/TO/HTTPD_GROUP_FILE"
Require group grpname1 grpname2 ...
(2)创建用户账号和组账号文件;
组文件:每一行定义一个组
GRP_NAME: username1 username2 ...
12)虚拟主机
有三种实现方案:
基于ip:
为每个虚拟主机准备至少一个ip地址;
基于port:
为每个虚拟主机使用至少一个独立的port;
基于FQDN(域名):通过请求报文中首部含有域名信息来识别请求
为每个虚拟主机使用至少一个FQDN(域名);
注意:一般虚拟机不要与中心主机混用;因此,要使用虚拟主机,得先禁用'main'主机;
禁用方法:注释中心主机的DocumentRoot指令即可;
虚拟主机的配置方法:
ServerName FQDN
DocumentRoot ""
其它可用指令:
ServerAlias:虚拟主机的别名;可多次使用;
ErrorLog:
CustomLog:
...
Alias
...
配置演示:
基于IP的虚拟主机示例:
(1)添加多个IP
[root@wlm web]# ifconfig eth0:0 10.10.10.101 up [root@wlm web]# ifconfig eth0:1 10.10.10.102 up # 在一块网卡上再添加两个IP
(2)要使用虚拟主机,得先禁用'main'主机;
禁用方法:注释中心主机的DocumentRoot指令即可;
#DocumentRoot "/web" # 加#禁用
(3)配置
ServerName www.a.com DocumentRoot "/web/a.com" ServerName www.b.net DocumentRoot "/web/b.net" ServerName www.c.org DocumentRoot "/web/c.org"
(4)创建/www/下的文件
[root@wlm web]# mkdir /web/ [root@wlm web]# echo "www.a.com" > /web/www.a.com/index.html [root@wlm web]# echo "www.b.net" > /web/ [root@wlm web]# echo "www.c.org" > /web/www.c.org/index.html
(5)语法检测,重新转载
[root@wlm web]# httpd -t Syntax OK [root@wlm web]# /etc/init.d/httpd restart Stopping httpd: [ OK ] Starting httpd:
(6)测试
通过不通地址从浏览器访问
基于端口的虚拟主机:
(1)修改配置如下
Listen 80 # 监听多个端口 Listen 808 Listen 8080 # 不通的端口对应不通的主页ServerName www.a.com DocumentRoot "/web/www.a.com" ServerName www.b.net DocumentRoot "/web/www.b.net" ServerName www.c.org DocumentRoot "/web/www.c.org"
(2)语法检测,重新装载
[root@wlm web]# httpd -t Syntax OK [root@wlm web]# /etc/init.d/httpd restart Stopping httpd: [ OK ] Starting httpd:
(3)测试
基于FQDN(域名)的虚拟主机:
(1)配置一个DNS服务器正在向区域文件里添加3个域名解析到该web主机(关于DNS配置见我另一篇文档http://afterdawn.blog.51cto.com/7503144/1420116)或是在hosts文件里面直接添加域名和映射的IP
如果没有现成的DNS服务器,这里建议直接写hosts文件
# DNS服务器里在向区域文件里的配置 $TTL 3600 $ORIGIN wlm.com. @ IN SOA ns1.wlm.com. dnsadmin.wlm.com. ( 2014100101 1H 10M 3D 1D ) IN NS ns1 IN NS ns2 IN MX 10 mx1 IN MX 20 mx2 ns2 IN A 10.10.10.10 ns1 IN A 10.10.10.3 a IN A 10.10.10.4 b IN A 10.10.10.4 c IN A 10.10.10.4 # 如果是hosts文件 直接写域名和对应的IP即可
(2)配置
NameVirtualHost 10.10.10.4:80 #声明10.10.10.4:80为该虚拟主机的IP端口ServerName a.wlm.com DocumentRoot "/web/www.a.com" ServerName b.wlm.com DocumentRoot "/web/www.b.net" ServerName c.wlm.com DocumentRoot "/web/www.c.org"
(3)语法检测,重载
[root@wlm web]# httpd -t Syntax OK [root@wlm web]# /etc/init.d/httpd reload Reloading httpd:
(4)测试,用不通域名访问
13)使用mod_deflate模块压缩页面优化传输速度
适用场景:
(1) 节约带宽,额外消耗CPU;同时,可能有些较老浏览器不支持;
(2) 压缩适于压缩的资源,例如文件文件;
实际配置
打开配置文件,添加以下内容:
[root@wlm ~]# vim /etc/httpd/conf/httpd.conf SetOutputFilter DEFLATE # mod_deflate configuration # Restrict compression to these MIME types AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE text/javascript AddOutputFilterByType DEFLATE text/css # Level of compression (Highest 9 - Lowest 1) DeflateCompressionLevel 9 # Netscape 4.x has some problems. BrowserMatch ^Mozilla/4 gzip-only-text/html # Netscape 4.06-4.08 have some more problems BrowserMatch ^Mozilla/4\.0[678] no-gzip # MSIE masquerades as Netscape, but it is fine BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html [root@wlm ~]# /etc/init.d/httpd restart # 从新加载服务
关于https的访问方式见:http://afterdawn.blog.51cto.com/7503144/1875173
好了,整个基于http协议访问的httpd程序站点就部署完了,下面再说说http访问的过程:
一次完整的http请求处理过程:
(1) 建立或处理连接:接收请求或拒绝请求;
(2) 接收请求:接收来自于网络上的主机请求报文中对某特定资源的一次请求的过程;
(3) 处理请求:对请求报文进行解析,获取客户端请求的资源及请求方法等相关信息;
(4) 访问资源:获取请求报文中请求的资源;
(5) 构建响应报文:
(6) 发送响应报文:
(7) 记录日志: