浅谈Apache服务[壹]
apache 介绍
20世纪90年代初,国家超级计算机应用中心NCSA开发,1995年开源社区发布apache(a patchyserver)
- ASF: apache software foundation
- FSF:Free Software Foundation
apache特性: - 高度模块化:core + modules
- DSO:Dynamic Shared Object 动态加/卸载
- MPM:multi-processing module 多路处理模块
apache 功能:
- 虚拟主机:IP、Port、FQDN
- CGI:Common Gateway Interface,通用网关接口
- 反向代理
- 负载均衡
- 路径别名
- 丰富的用户认证机制:basic,digest
- 支持第三方模块
httpd-2.4新特性
- MPM支持运行为DSO机制;以模块形式按需加载
- event MPM生产环境可用
- 异步读写机制
- 支持每模块及每目录的单独日志级别定义
- 每请求相关的专用配置
- 增强版的表达式分析式
- 毫秒级持久连接时长定义
- 基于FQDN的虚拟主机不需要NameVirutalHost指令
- 新指令
- 支持用户自定义变量
- 更低的内存消耗
MPM multi-processing module 工作模式
- prefork:多进程I/O模型,每个进程响应一个请求,CentOS7 默认模型
- 一个主进程:生成和回收n个子进程,创建套接字,不响应请求
- 多个子进程:工作work进程,每个子进程处理一个请求;
- 系统初始时,预先生成多个空闲进程,等待请求
-
Prefork MPM: 预派生模式,有一个主控制进程,然后生成多个子进程,每个子进程有一个独立的线程响应用户请求,相对比较占用内存,但是比较稳定,可以设置最大和最小进程数,是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
- 优点:稳定
- 缺点:慢,占用资源,不适用于高并发场景
-
worker: 复用的多进程I/O模型,多进程多线程,IIS使用此模型
- 一个主进程:生成m个子进程
- 每个子进程负责生成n个线程,每个线程响应一个请求,故能够并发响应请求:m*n
- 比prefork模式节约资源,但一个线程出错会影响所在进程的其他线程
-
worker MPM:是一种多进程和多线程混合的模型,有一个控制进程,启动多个子进程,每个子进程里面包含固定的线程,使用线程程来处理请求,当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,由于其使用了线程处理请求,因此可以承受更高的并发。
- 优点:相比prefork 占用的内存较少,可以同时处理更多的请求
- 缺点:使用keep-alive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用。(该问题在prefork模式下,同样会发生)
-
event: 事件驱动模型(worker模型的变种),CentOS8 默认模型
-
一个主进程:生成m个子进程,每个子进程负责生个n个线程,每个线程响应一个请求,并发响应请求:m*n,有专门的监控线程来管理这些keep-alive类型的线程,当有真实请求时,将请求传递给服务线程,执行完毕后,又允许释放。这样增强了高并发场景下的请求处理能力
-
event MPM:Apache中最新的模式,属于事件驱动模型(epoll),每个进程响应多个请求,在现在版本里的已经是稳定可用的模式。它和worker模式很像,最大的区别在于,它解决了keep-alive场景下,长期被占用的线程的资源浪费问题(某些线程因为被keep-alive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)。
-
event MPM中,会有一个专门的线程来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力
-
event只在有数据发送的时候才开始建立连接,连接请求才会触发工作线程,即使用了TCP的一个选项,叫做延迟接受连接TCP_DEFER_ACCEPT,加了这个选项后,若客户端只进行TCP连接,不发送请求,则不会触发Accept操作,也就不会触发工作线程去干活,进行了简单的防攻击(TCP连接)
-
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
-
缺点:没有线程安全控制
-
httpd-2.4:event 稳定版,centos7以后默认
httpd-2.4 相关文件
- 配置文件:
/etc/httpd/conf/httpd.conf 主配置文件
/etc/httpd/conf.d/*.conf 子配置文件
/etc/httpd/conf.d/conf.modules.d/ 模块加载的配置文件 - 检查配置语法:
httpd –t
- 查看静态编译的模块:
httpd -l
- 查看静态编译及动态装载的模块:
httpd –M
- 服务单元文件:
- /usr/lib/systemd/system/httpd.service
- 配置文件:/etc/sysconfig/httpd
- 服务控制和启动
systemctl enable|disable httpd.service
systemctl {start|stop|restart|status|reload} httpd.service
- 站点网页文档根目录:/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-manual
httpd配置文件的组成
主要组成
- 全局配置:Global Environment
- 主服务器配置:Main server configuration
- 虚拟主机配置:virtual host
配置文件格式: directive value (指令 值)
- directive:不区分字符大小写
- value:当为路径时,是否区分大小写取决于文件系统
httpd 常见配置
显示服务器版本信息
ServerTokens Major|Minor|Min[imal]|Prod[uctOnly]|OS|Full
- ServerTokens Prod[uctOnly]: Server: Apache
- ServerTokens Major: Server: Apache/2
- ServerTokens Minor: Server: Apache/2.0
- ServerTokens Min[imal]: Server: Apache/2.0.41
- ServerTokens OS: Server: Apache/2.0.41 (Unix)
- ServerTokens Full (or not specified): Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2,被注释时默认状态为Full
- 建议将ServerTokens值设为Prod
/ 修改之前
[root@ansible ~]#curl -I 172.20.54.1
HTTP/1.1 403 Forbidden
Date: Sat, 07 Dec 2019 09:17:30 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Thu, 16 Oct 2014 13:20:58 GMT
ETag: "1321-5058a1e728280"
Accept-Ranges: bytes
Content-Length: 4897
Content-Type: text/html; charset=UTF-8
/ 开始修改配置文件,主配置文件最好别动,手动建立一个包含的子配置文件
vim /etc/httpd/conf.d/ceshi.conf
servertokens prod
/ 重启httpd服务即可
systemctl restart httpd
/ 修改之后测试
[root@ansible ~]#curl -I 172.20.54.1
HTTP/1.1 403 Forbidden
Date: Sat, 07 Dec 2019 09:35:54 GMT
Server: Apache
Last-Modified: Thu, 16 Oct 2014 13:20:58 GMT
ETag: "1321-5058a1e728280"
Accept-Ranges: bytes
Content-Length: 4897
Content-Type: text/html; charset=UTF-8
修改监听的IP和Port
-
设置格式:Listen [IP:]PORT
- 省略IP表示为0.0.0.0
- Listen指令至少一个,可重复出现多次
- Listen 80
- Listen 8080
- 修改监听socket,重载服务进程方可生效
-
注意:必须有端口号设置,否则服务启动失败
/ 修改服务器端口172.20.54.1只能通过8080端口访问
vim /etc/httpd/conf/httpd.conf
Listen 172.20.54.1:8080
/ 重启服务
systemctl reload httpd
/ 测试
[root@ansible ~]#curl -I 172.20.54.1
curl: (7) Failed connect to 172.20.54.1:80; Connection refused
[root@ansible ~]#curl -I 172.20.54.1:8080
HTTP/1.1 403 Forbidden
Date: Sat, 07 Dec 2019 09:48:02 GMT
Server: Apache
Last-Modified: Thu, 16 Oct 2014 13:20:58 GMT
ETag: "1321-5058a1e728280"
Accept-Ranges: bytes
Content-Length: 4897
Content-Type: text/html; charset=UTF-8
持久连接
- 定义:连接建立,每个资源获取完成后不会断开连接,而是继续等待其它的请求完
成,默认关闭持久连接 - 断开条件:时间限制:以秒为单位, 默认5s,httpd-2.4 支持毫秒级
- 副作用:对并发访问量大的服务器,持久连接会使有些请求得不到响应
- 折衷:使用较短的持久连接时间
- 设置格式
- KeepAlive On|Off
- KeepAliveTimeout 15 #连接持续15s,可以以ms为单位,默认值为5s
- MaxKeepAliveRequests 500 #持久连接最大接收的请求数,默认值100
- 测试方法
telnet WEB_SERVER_IP PORT
GET /URL HTTP/1.1
Host: WEB_SERVER_IP
- 测试实例
vim /etc/httpd/conf.d/mod.conf
keepalive on
keepalivetimeout 100 / 默认是5秒 为了测试效果
[root@ansible ~]#date
Sun Dec 8 09:20:39 CST 2019
[root@ansible ~]#telnet 172.20.54.1 80
Trying 172.20.54.1...
Connected to 172.20.54.1.
Escape character is '^]'.
GET /index.html HTTP/1.1
HOST 1.1.1.1
HTTP/1.1 408 Request Timeout
Date: Sun, 08 Dec 2019 01:20:39 GMT
Server: Apache
Content-Length: 221
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>408 Request Timeout</title>
</head><body>
<h1>Request Timeout</h1>
<p>Server timeout waiting for the HTTP request from the client.</p>
</body></html>
Connection closed by foreign host.
[root@ansible ~]#date
Sun Dec 8 09:21:40 CST 2019
MPM (Multi-Processing Module) 多路处理模块
1️⃣httpd 支持三种MPM工作模式:prefork, worker, event
- httpd-2.4不支持同时编译多个模块,所以只能编译时选定一个
- 查询当前MPM模式
[root@Centos7 ~]# httpd -M | grep mpm
mpm_prefork_module (shared)
- 切换正在使用的MPM模式
/ 启用要启用的MPM相关的LoadModule指令即可,其它未启用的两项需要在行首加#注释
vim /etc/httpd/conf.modules/00-mpm.conf
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
LoadModule mpm_event_module modules/mod_mpm_event.so
- 注意不要同时启用多个模块,否则会报错
AH00534: httpd: Configuration error: More than one MPM loaded.
- 范例:查看各个版本默认的MPM模式
/ Centos6 默认的模式
[root@Centos6 ~]#httpd -v
Server version: Apache/2.2.15 (Unix) / 默认使用的版本
Server built: Jun 19 2018 15:45:13
[root@Centos6 ~]#httpd -M |grep mpm
httpd: apr_sockaddr_info_get() failed for Centos6.localdomain
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
mpm_prefork_module (static)
/ Centos7 默认模式
[root@Centos7 ~]# httpd -v / 默认使用的版本
Server version: Apache/2.4.6 (CentOS)
Server built: Aug 8 2019 11:41:18
[root@Centos7 ~]# httpd -M | grep mpm
mpm_prefork_module (shared)
/ Centos8 默认模式
[root@Centos8 ~]#httpd -v
Server version: Apache/2.4.37 (centos) / 默认使用的版本
Server built: Oct 7 2019 21:42:02
[root@Centos8 ~]#httpd -M | grep mpm
mpm_event_module (shared)
- 示例:修改Centos6 7模式
/ Centos6修改 切换至work模式
vim /etc/sysconfig/httpd
HTTPD=/usr/sbin/httpd.worker / 将行前的注释符#删除
httpd -t
service httpd restart
[root@Centos6 ~]#ps aux| grep httpd
root 1926 0.0 0.3 177732 4072 ? Ss 10:27 0:00 /usr/sbin/httpd.worker
apache 1930 0.0 0.5 521992 5344 ? Sl 10:28 0:00 /usr/sbin/httpd.worker
apache 1931 0.0 0.5 521992 5348 ? Sl 10:28 0:00 /usr/sbin/httpd.worker
apache 1933 0.0 0.5 521992 5364 ? Sl 10:28 0:00 /usr/sbin/httpd.worker
[root@Centos7 ~]# vim /etc/httpd/conf.modules.d/00-mpm.conf
/ 启用event模块
LoadModule mpm_event_module modules/mod_mpm_event.so
[root@Centos7 ~]# systemctl restart httpd
[root@Centos7 ~]# httpd -M | grep mpm
mpm_event_module (shared)
2️⃣模块
- 查看静态编译的模块
httpd -l
- 查看静态编译及动态装载的模块
httpd -M
- 动态模块加载:不需重启即生效
- 动态模块路径:/usr/lib64/httpd/modules/
3️⃣切换正在使用的httpd模式
centos6 httpd-2.2 MPM设置
修改文件
/etc/sysconfig/httpd
HTTPD=/usr/sbin/httpd.worker
HTTPD=/usr/sbin/httpd.event
默认为prefork模式
配置后重启httpd server生效
centos7 httpd-2.4 MPM设置
修改文件 /etc/httpd/conf.modules.d/00-mpm.conf
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
LoadModule mpm_worker_module modules/mod_mpm_worker.so
LoadModule mpm_event_module modules/mod_mpm_event.so
4️⃣prefork默认设置
vim /etc/httpd/conf/httpd.conf / Centos6 httpd-2.2版本
vim /usr/share/doc/httpd-2.4.6/httpd-mpm.conf / Centos7 httpd-2.4版本
<IfModule prefork.c>
StartServers 8 / 启动开启的进程数
MinSpareServers 5 / 最少空闲进程数
MaxSpareServers 20 / 最大空闲进程数
ServerLimit 256 / 最多进程数,不能超过MaxClient,最大能设置为20000
MaxClients 256 / 最大并发数
MaxRequestsPerChild 4000 / 子进程最多能处理的请求,达到设置值子进程被父进程终止,释放内存
/ 从 httpd.2.3.9开始被MaxConnectionsPerChild代替
</IfModule>
5️⃣worker和event 模式相关的配置
vim /etc/httpd/conf/httpd.conf / Centos6 httpd-2.2版本
vim /usr/share/doc/httpd-2.4.6/httpd-mpm.conf / Centos7 httpd-2.4版本
<IfModule mpm_worker_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 220
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0 / 无限制永不释放
</IfModule>
- 启动时开启3个进程,每个进程开启75个线程,共225个线程,但最多空闲220个线程,需要结束1个进程共75个线程,故开启服务后实际只能开到2个进程共150个线程
- 示例修改启动进程以及线程数量
/ MPM各个模块相关设置文件在httpd-mpm.conf文件里面
locate httpd-mpm.conf
vim /usr/share/doc/httpd-2.4.6/httpd-mpm.conf
<IfModule mpm_prefork_module>
StartServers 100
MinSpareServers 50
MaxSpareServers 60
MaxRequestWorkers 250
MaxConnectionsPerChild 0
</IfModule>
/ 给主配置文件加载这个配置文件,因为它默认不加载这个文件,但是有默认配置
vim /etc/httpd/conf/httpd.conf
Include /usr/share/doc/httpd-2.4.6/httpd-mpm.conf
systemctl restart httpd
[root@Centos7 httpd]# pstree
systemd─┬─agetty
├─auditd───{auditd}
├─crond
├─dbus-daemon
├─httpd───98*[httpd]
/ 生效
DSO(Dynamic Shared Object):动态加载模块
- 加载动态模块配置文件:
vim /etc/http/conf/httpd.conf
ServerRoot "/etc/httpd"
Include conf.modules.d/*.conf
- 配置指定模块加载格式:
LoadModule <mod_name> <mod_path>
- 模块文件路径使用相对路径:
相对于ServerRoot(默认/etc/httpd) - 范例:取消加载模块
auth_basic_module
[root@Centos7 httpd]# vim /etc/httpd/conf.modules.d/00-base.conf
#LoadModule auth_basic_module modules/mod_auth_basic.so / 注释即可
[root@Centos7 httpd]# httpd -t
Syntax OK
[root@Centos7 httpd]# systemctl restart httpd
[root@Centos7 httpd]# httpd -M | grep auth_basic
.