介绍
httpd是apache超文本传输协议(HTTP)服务器的主程序。被设计为一个独立运行的后台进程,它会建立一个处理请求的子进程或线程的池。
特性
高度模块化:core + modules
DSO:Dynamic Shared Object 动态加载/卸载
MPM:multi-processing module 多路处理模块
功能
虚拟主机:IP、Port、FQDN
CGI:Common Gateway Interface 通用网关接口
反向代理
负载均衡
路径别名
丰富的用户认证机制:basic、digest
支持第三方模块
MPM工作模式
prefork
多进程I/O模型,每个进程响应一个请求;Centos7默认模型。
一个主进程:生成和回收n个子进程,创建套接字,不响应请求。
多个子进程:工作work进程,每个子进程处理一个请求;系统初始时,预先生成多个空闲进程,等待请求。
Prefork MPM:预派生模式,有一个主控制进程,然后生成多个子进程,每个子进程有一个独立的线程响应客户的请求;相对比较占用内存,但是比较稳定,可以设置最大和最小进程数,最古老的一种模式,也是最稳定的模式,不擅长处理高并发请求,在这种场景下,它会将请求放进队列中,一直等到有可用进程,请求才会被处理。
优点:稳定
缺点:慢,占用资源,不适用于高并发场景
work
复用的多进程I/O模型,多进程多线程,IIS使用此模型。
一个主进程:生成m个子进程,每个子进程负责生成n个线程,每个线程响应一个请求,并发响应请求数:m*n
work MPM:是一种多进程和多线程混合的模型,有一个控制进程,启动多个子进程,每个子进程里面包含固定的线程,使用线程来处理请求,当线程不够用时会再启动一个新的子进程,然后在子进程里面再启动线程处理请求,由于使用线程处理请求,因此可承受更高的并发。
优点:相比Prefork占用的内存较少,可同时处理更多的请求
缺点:使用keep-alive的长连接方式,某个线程会被一直占据,即使没有传输数据,也需要一直等待超时才会被释放。如果过多的线程被这样占据,也会导致高并发场景下无线程可用。prefork模式下也存在此问题。
event
事件驱动模型,Centos8的默认模型
一个主进程:生成m个子进程,每个子进程负责生成n个线程,每个线程响应一个请求,并发响应请求数:m*n,有专门的监控线程来管理keep-alive类型线程,当有真实请求时,将请求传递给服务线程,执行完毕后,又允许释放。这样增强了高并发场景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。
缺点:没有线程安全控制
安装
httpd-2.2:centos6默认 httpd-2.4:centos7默认
rpm方式
dnf -y install httpd
systemctl enable --now httpd
编译安装
准备安装包 apr apr-util httpd
[root@wenzi httpd-2.4.57]# ls /root/
anaconda-ks.cfg apr-1.7.4.tar.bz2 apr-util-1.6.3.tar.bz2 httpd-2.4.57.tar.bz2 original-ks.cfg
解压缩
tar -jx -f httpd-2.4.57.tar.bz2 -C /usr/local/src/
tar -xj -f apr-1.7.4.tar.bz2 -C /usr/local/src/httpd-2.4.57/srclib/
tar -xj -f apr-util-1.6.3.tar.bz2 -C /usr/local/src/httpd-2.4.57/srclib/
修改apr apr-util文件夹名字
cd /usr/local/src/httpd-2.4.57/srclib/
mv apr-1.7.4 apr
mv apr-util-1.6.3 apr-util
[root@wenzi srclib]# ls
apr apr-util Makefile.in
编译安装
yum -y install gcc make pcre-devel openssl-devel expat-devel
cd /usr/local/src/httpd-2.4.57/
./configure --prefix=/usr/local/httpd24 --enable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --with-pcre --with-included-apr --enable-modules=most --enable-mpms-shared=all --with-mpm=prefork
make -j 2 && make install
创建apache用户,并使用apache启动httpd
[root@wenzi httpd-2.4.57]# useradd -r -s /sbin/nologin apache
[root@wenzi httpd-2.4.57]# id apache
uid=997(apache) gid=995(apache) groups=995(apache)[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
...
User apache
Group apache...
创建软链接,省去设置环境变量
ln -s /usr/local/httpd24/bin/* /usr/bin/
启动apache
apachectl
设置开机启动
[root@wenzi ~]# vim /etc/rc.d/rc.local
/usr/local/httpd24/bin/apachectl start
[root@wenzi ~]# chmod +x /etc/rc.d/rc.local
centos7及以上版本使用service unit
[root@wenzi ~]# vim /usr/lib/systemd/system/httpd.service
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)
[Service]
Type=forking
ExecStart=/usr/local/httpd24/bin/apachectl start
ExecReload=/usr/local/httpd24/bin/apachectl graceful
ExecStop=/usr/local/httpd24/bin/apachectl stop
KillSignal=SIGCONT
PrivateTmp=true
[Install]
WantedBy=mu1ti-user.target[root@wenzi ~]# systemctl daemon-reload
[root@wenzi ~]# systemctl start httpd
[root@wenzi ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: active (running) since Sun 2023-10-08 21:43:18 CST; 4s ago
Docs: man:httpd(8)
man:apachectl(8)
Process: 1245 ExecStart=/usr/local/httpd24/bin/apachectl start (code=exited, status=0/SUCCESS)
Main PID: 1248 (httpd)
CGroup: /system.slice/httpd.service
├─1248 /usr/local/httpd24/bin/httpd -k start
├─1249 /usr/local/httpd24/bin/httpd -k start
├─1250 /usr/local/httpd24/bin/httpd -k start
├─1251 /usr/local/httpd24/bin/httpd -k start
├─1252 /usr/local/httpd24/bin/httpd -k start
└─1253 /usr/local/httpd24/bin/httpd -k startOct 08 21:43:18 wenzi.localhost systemd[1]: Starting The Apache HTTP Server...
Oct 08 21:43:18 wenzi.localhost apachectl[1245]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using wenzi.localhost. Set the 'ServerN...his message
Oct 08 21:43:18 wenzi.localhost systemd[1]: Started The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.
配置man帮助文档
[root@wenzi ~]# vim /etc/man_db.conf
MANDATORY_MANPATH /usr/local/httpd24/man
[root@wenzi ~]# mandb 更新下
httpd-2.4相关文件
配置文件
- /etc/httpd/conf/httpd.conf 主配置文件
- /etc/httpd/conf.d/*.conf 子配置文件
- /etc/httpd/conf.d/conf.modules.d/ 模块加载的配置文件
检查配置语法
- httpd -t
服务单元文件
- /usr/lib/systemd/system/httpd.service
- 配置文件:/etc/sysconfig/httpd
web网站默认根目录
/var/www/html
模块文件路径
- /etc/httpd/modules
- /usr/lib64/httpd/modules
主服务器程序文件
/usr/sbin/httpd
主进程文件
/etc/httpd/run/httpd.pid
日志文件目录
/var/log/httpd
access_log:访问日志
error_log:错误日志
httpd配置文件
主要组成
Global Environment 全局配置
Main server configuration 主服务器配置
virtual host 虚拟主机
配置文件格式
directive value
格式说明:
directive 不区分字符大小写
value 为路径时,是否区分大小写,取决于文件系统
ServerRoot "/etc/httpd" 设置Apache服务器的主要目录路径。这个目录包含了服务器配置文件、日志文件和文档。
Listen 80 服务器监听的端口号
Include conf.modules.d/*.conf 包含哪些子配置文件
User apache 配置httpd进程用户,提高安全
Group apache 配置httpd进程用户组,提高安全ServerAdmin root@localhost 设置管理员邮箱
ServerName www.example.com:80 设置服务器的域名。当客户端请求访问时,服务器将使用这个域名来解析请求
<Directory /> 定义对特定目录的权限
AllowOverride none 不允许任何.htaccess文件覆盖这里的设置
Require all denied 除非被明确允许,否则所有的请求都会被拒绝
</Directory>DocumentRoot "/var/www/html" web网站默认根目录
<Directory "/var/www"> 定义对 /var/www 目录配置
AllowOverride None
Require all granted 表示对所有用户都允许访问这个目录
</Directory>
<Directory "/var/www/html"> 定义对 /var/www/html 目录配置
Options Indexes FollowSymLinks 表示这个目录下可以创建目录索引,并且允许服务器跟踪符号链接
AllowOverride None 表示在这个目录下,.htaccess文件(如果存在)将被忽略,Apache服务器将不会考虑里面的指令
Require all granted 表示对所有用户都允许访问这个目录
</Directory>
<IfModule dir_module> 一种控制结构,用于条件性地包含或排除配置指令;dir_module是 Apache 的一个模块;如果 Apache 服务器加载了这个模块(通过指令 LoadModule),那么这段在<IfModule dir_module> 和 </IfModule> 之间的配置指令就会被应用
DirectoryIndex index.html 指定了当一个请求没有指定具体的文件名时,Apache服务器应该默认显示哪个文件
</IfModule>
<Files ".ht*"> 控制指令,使用了<Files>和Requitre指令来控制对特定文件的访问;匹配所有以.ht开头的文件或目录
Require all denied 不允许任何用户访问这些文件或目录。
</Files>
ErrorLog "logs/error_log" 错误日志位置,此处为相对路径。
LogLevel warn 仅记录警告warn及以上级别错误
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>CustomLog "logs/access_log" combined
</IfModule>
第一行
加载 log_config_module 模块,如果此模块已加载,则执行后续配置。此模块提供了对服务器日志进行配置的功能。
第二行
此行定义了一个名为 combined 的日志格式。此格式包含访问者的IP地址(%h)、身份验证级别的信息(%l)、用户标识(%u)、请求接入的时间(%t)、请求的详细信息("%r")、响应的状态(%>s)、响应的大小(%b)、引用页的URL("%{Referer}i")以及用户代理的信息("%{User-Agent}i")
第三行
此行定义了一个名为 common 的日志格式。格式类似 combined 的格式
第四行
加载 logio_module 模块,如果此模块已加载,则执行后续的日志定义格式和记录功能。此模块为httpd服务器提供了对 I/O 活动的日志记录能力
第五行
此行定义了一个名为 combinedio 的日志格式。输入和输出的字节数(%I 和 %O)
第八行
将上述定义的'combined'日志格式应用于logs/access_log文件,这就意味着所有的HTTP请求都会按照'combined'格式记录在这个文件中
<IfModule alias_module>
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
开始一个条件模块块,如果alias_module模块已加载,则执行此块内的指令。ScriptAlias 指令定义了URL路径(/cgi-bin/)和服务器上的目录路径(/var/www/cgi-bin/)的映射,这样当访问/cgi-bin/ URL时,服务器就会在/var/www/cgi-bin/目录下查找并执行相应的脚本。这个指令通常用于支持Common Gateway Interface (CGI)脚本。
<Directory "/var/www/cgi-bin">
AllowOverride None
Options None 关闭在目录中所有可用的服务器配置选项
Require all granted
</Directory>
<IfModule mime_module>
TypesConfig /etc/mime.types 将.Z文件指定为application/x-compress MIME类型,这种类型通常用于表示压缩文件
AddType application/x-compress .Z 将.Z文件指定为application/x-compress MIME类型,这种类型通常用于表示压缩文件
AddType application/x-gzip .gz .tgz 将.gz和.tgz文件都指定为application/x-gzip MIME类型,这种类型通常用于表示gzip压缩的文件AddType text/html .shtml 将.shtml文件指定为text/html MIME类型,这表示服务器应将.shtml文件作为HTML页面处理
AddOutputFilter INCLUDES .shtml 将.shtml文件添加到包含过滤器中,这通常用于处理服务器端包含(SSI)</IfModule>
AddDefaultCharset UTF-8 设置默认的字符编码为UTF-8
<IfModule mime_magic_module>
MIMEMagicFile conf/magic 指定一个名为"magic"的文件,该文件位于"conf"目录中。这个文件包含有关文件类型和编码的魔法数字信息,这对于Apache服务器正确处理上传的文件和确定文件的MIME类型非常重要。
</IfModule>EnableSendfile on 启用Apache的sendfile系统调用;这个系统调用用于将文件内容直接从磁盘传输到网络套接字,而不是先读入内核缓冲区然后再从内核缓冲区写入到网络套接字,这可以提高大数据文件的传输效率。
IncludeOptional conf.d/*.conf 告诉Apache去
conf.d
目录下查找所有以.conf
结尾的文件
常见配置(以编译安装为基础)
修改网站默认根目录
[root@wenzi ~]# mkdir -p /var/www/html/
[root@wenzi ~]# echo 'This is new page' > /var/www/html/index.html
[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
...
DocumentRoot "/var/www/html/"
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
...
[root@wenzi ~]# systemctl restart httpd
设置服务器域名
[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
...
ServerName www.example.com:80
...
[root@wenzi ~]# systemctl reload httpd
本机配置host本地解析后访问
查看服务器版本信息
浏览器F12发现网页显示出服务器版本信息,需防范。
官方文档https://httpd.apache.org/docs/2.4/mod/core.html#servertokens
[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
...
ServerToken Prod
[root@wenzi ~]# systemctl reload httpd
[root@wenzi ~]# curl -I 192.168.28.156
HTTP/1.1 200 OK
Date: Sun, 08 Oct 2023 14:41:31 GMT
Server: Apache
Last-Modified: Sun, 08 Oct 2023 14:05:52 GMT
ETag: "11-60734f8ad3af0"
Accept-Ranges: bytes
Content-Length: 17
Content-Type: text/html
修改监听IP和端口
[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
listen 192.168.28.156:81
[root@wenzi ~]# systemctl reload httpd
[root@wenzi ~]# curl -I 192.168.28.156:81
HTTP/1.1 200 OK
Date: Sun, 08 Oct 2023 14:53:43 GMT
Server: Apache
Last-Modified: Sun, 08 Oct 2023 14:05:52 GMT
ETag: "11-60734f8ad3af0"
Accept-Ranges: bytes
Content-Length: 17
Content-Type: text/html
持久连接
Persisten Connection:连接建立,每个资源获取完成后不会断开连接,而是继续等待其它的请求完成,默认开启持久连接。
断开条件:
时间限制:以秒为单位,默认5s,httpd-2.4支持毫秒级
请求数量:请求数达到指定值,默认100
副作用:并发量访问大的服务器,持久连接会使得不分请求得不到响应
折中:使用较短的持久连接时间
持久连接相关指令:
KeepAlived On|Off
KeepAlivedTimeout 15 连接持续15s
MaxKeepAlivedRequests 500 持久连接最大连接数为500,
prefork模式相关配置
StartServers 2000
MinSpareServers 1000
MaxSpareServers 3000
ServerLimit 2550 最多进程数,最大值20000
MaxRequestWorkers 2560 最大的并发连接数,默认256
MaxConnectionsPerChild 4000 子进程最多能处理的请求数量,当处理次数达到之后,子进程会被父进程终止,子进程占用的内存会被释放(为0时永不释放)
MaxRequestPerChild 4000 从httpd2.3.9后被MaxConnectionsPerChild处理
worker和event模式相关配置
ServerLimit 16 启动的最大子进程数
StartServers 2 启动时默认启动的子进程数
MaxRequestWorkers 150 同时处理的最大请求量
MinSpareThreads 25 在任何给定时间需要保持空闲以接受新请求的最小线程数
MaxSpareThreads 75 在任何给定时间可以存在的最大空闲线程数
ThreadsPerChild 75 每个子进程中启动的线程数
定义网站首页
[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
<IfModule dir_module>
DirectoryIndex index.html index.php index.htm
</IfModule>
可实现访问控制的资源
基于目录
<Directory "/path">
...
</Directory>
基于文件
<File "/path/file">
...
</File>
基于文件通配符
<File "/path/*file*">
...
</File>
基于拓展正则表达式
<FileMatch "regex">
...
</FileMatch>
基于URL
<Location "URL">
...
</Location>
范例:
匹配 /private1 /private1/ /private1/file.txt
不匹配 /private1other
<Location "/private1">
...
</Location>
匹配 private1/ /private1/file.txt
不匹配 /private2 /private2other
<Location "/private1">
...
</Location>
<LocationMatch "regex">
...
</LocationMatch>
针对目录实现访问控制
Options指令
后面跟1个或多个空白字符分隔的选项列表,在选项前的 + 或 - 代表增加或删除指定选项。
常见选项:
- Indexes:指明URL路径下不存在与定义的主页面资源相符的资源文件时,返回索引列表给用户,页面类似于aliyun的软件仓库文件列表
- FollowSymLinks:允许访问符号链接文件所指向的源文件
- None:全部禁用
- All:全部允许
AllowOverride指令
与访问控制相关的指令可以放在指定目录下的.htaccess文件(由AccessFileName指令指定),覆盖之前的配置指令,只对<Directory>语句有效
常见用法:
- AllowOverride All:.htaccess中所有指令都有效
- AllowOverride None:.htaccess文件无效,此为httpd2.3.9后默认值
- AllowOverride AuthConfig:.htaccess文件中,除了AuthConfig其它指令都无效
基于客户端IP实现访问控制
无明确授权的目录,默认拒绝
允许所有主机访问:Require all granted
拒绝所有主机访问:Require all denied
控制特定的IP访问:
Require ip IPADDR:授权指定来源的IP访问
Require not ip IPADDR:拒绝特定的IP访问
控制特定主机访问:
Require host HOSTNAME:授权特定主机访问
Require not host HOSTNAME:拒绝特定主机访问
<RequireAll> 不能有失败,至少有一个成功匹配才成功,失败优先
<RequireAny> 多个语句有一个成功则成功,成功优先
关闭Trace
是否支持trace方法,默认on,基于安全风险,建议关闭
[root@wenzi ~]# curl -IX OPTIONS 192.168.28.156:81
HTTP/1.1 200 OK
Date: Sun, 08 Oct 2023 19:54:59 GMT
Server: Apache
Allow: GET,POST,OPTIONS,HEAD,TRACE
Content-Length: 0
Content-Type: text/html[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
...
TraceEnable off
[root@wenzi ~]# systemctl reload httpd
[root@wenzi ~]# curl -IX OPTIONS 192.168.28.156:81
HTTP/1.1 200 OK
Date: Sun, 08 Oct 2023 19:59:03 GMT
Server: Apache
Allow: POST,OPTIONS,HEAD,GET
Content-Length: 0
Content-Type: text/html
status状态页
[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
...
<Location "/status">
SetHandler server-status
<RequireAny>
Require all denied
Require ip 192.168.28.0/24
</RequireAny>
</Location>[root@wenzi ~]# systemctl restart httpd
访问 http://服务器IP/status
多虚拟主机
httpd支持一台物理主机上实现多个网站,即多虚拟主机
网站的唯一标识
- IP相同,但端口不同
- IP不同,但端口均为默认端口
- FQDN不同,IP和端口都相同
三种实现方案
- 基于IP:为每个虚拟主机准备至少一个IP地址
- 基于Port:为每个虚拟主机使用至少一个独立port
- 基于FQDN:为每个虚拟主机至少使用一个FQDN
基于不同端口
[root@wenzi ~]# vim /usr/local/httpd24/conf/httpd.conf
Listen 81
Listen 82
Listen 83
<virtualhost *:81>
documentroot /data/web1/
servername www.a.com
CustomLog "/data/logs/a.access_log" common
<directory /data/web1/>
require all granted
</directory>
</virtualhost><virtualhost *:82>
documentroot /data/web2/
servername www.b.com
CustomLog "/data/logs/b_access.log" common
<directory /data/web2/>
require all granted
</directory>
</virtualhost><virtualhost *:83>
documentroot /data/web3/
servername www.c.com
CustomLog "/data/logs/c_access.log" common
<directory /data/web3/>
require all granted
</directory>
</virtualhost>[root@wenzi ~]# echo 'web1' > /data/web1/index.html
[root@wenzi ~]# echo 'web2' > /data/web2/index.html
[root@wenzi ~]# echo 'web3' > /data/web3/index.html
基于不同IP
Listen 192.168.28.100:80
Listen 192.168.28.101:80
<virtualhost 192.168.28.100:80>
documentroot /data/web1/
servername www.a.com
</virtualhost><virtualhost 192.168.28.101:8>
documentroot /data/web2/
servername www.b.com
</virtualhost>
基于不同FQDN
Listen 192.168.28.100:80
<virtualhost 192.168.28.100:80>
servername www.a.com
documentroot /data/web1/
</virtualhost><virtualhost 192.168.28.100:80>
servername www.b.com
documentroot /data/web2/
</virtualhost>
设定默认字符集
AddDefaultCharset UTF-8 默认值
日志格式
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog "logs/access_log" combined
</IfModule>
压缩
使用mod_deflate模块压缩页面优化传输速度;节约带宽,额外消耗CPU;压缩适于压缩的文件,比如文本文件。
对所有文件启动压缩
AddOutputFilterByType DEFLATE *
对指定的MIME类型启动压缩
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json application/javascript
相关参数
压缩级别,从1-9,9的压缩比最高 DeflateCompressionLevel 9