Apache
本文最后更新于306 天前,其中的信息可能已经过时,如有错误请发送邮件到3063503032@qq.com

常用的网站服务软件

  • https://w3techs.com/technologies/overview/web_server
  • Apache是什么
    • Apache HTTP Server简称为Apache,是Apache软件基金会的一个高性能、功能强大、健壮可靠、又灵活的开放源代码的web服务软件,它可以运行在广泛的计算机平台上如Linux、Windows。因其平台性和很好的安全性而被广泛使用,是互联网最流行的web服务软件之一
  • 特点
    • 功能强大
    • 高度模块化
    • 采用MPM多路处理模块
    • 配置简单
    • 速度快
    • 应用广泛
    • 性能稳定可靠
    • 可做代理服务器或负载均衡来使用
    • 双向认证
    • 支持第三方模块
  • 应用场合
    • 使用Apache运行静态HTML网页、图片
    • 使用Apache结合PHP、Linux、MySQL可以组成LAMP经典架构
    • 使用Apache作代理、负载均衡等
  • MPM工作模式
    • prefork:多进程I/O模型,一个主进程,管理多个子进程,一个子进程处理一个请求。
    • worker:复用的多进程I/O模型,多进程多线程,一个主进程,管理多个子进程,一个子进程管理多个线程,每个线程处理一个请求。
    • event:事件驱动模型,一个主进程,管理多个子进程,一个进程处理多个请求。

apache安装

  • centos7的软件仓库中存在此软件包,可以直接通过yum进行安装

[root@localhost ~]# firewall-cmd --add-port=80/tcp --permanent [root@localhost ~]# firewall-cmd --reload [root@localhost ~]# yum -y install httpd [root@localhost ~]# systemctl start httpd [root@localhost ~]# systemctl enable httpd [root@localhost ~]# httpd -v Server version: Apache/2.4.6 (CentOS) Server built: Nov 16 2020 16:18:20

  • 使用curl或者浏览器测试网页是否正常

[root@localhost ~]# curl -I 127.0.0.1 HTTP/1.1 403 Forbidden Date: Sun, 02 May 2021 02:00:32 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

img

httpd命令

httpd为Apache HTTP服务器程序。直接执行程序可启动服务器的服务httpd [-hlLStvVX][-c<httpd指令>][-C<httpd指令>][-d<服务器根目录>][-D<设定文件参数>][-f<设定文件>]

选项

  • -c:在读取配置文件前,先执行选项中的指令。
  • -C:在读取配置文件后,再执行选项中的指令。
  • -d<服务器根目录>:指定服务器的根目录。
  • -D<设定文件参数>:指定要传入配置文件的参数。
  • -f<设定文件>:指定配置文件。
  • -h:显示帮助。
  • -l:显示服务器编译时所包含的模块。
  • -L:显示httpd指令的说明。
  • -S:显示配置文件中的设定。
  • -t:测试配置文件的语法是否正确。
  • -v:显示版本信息。
  • -V:显示版本信息以及建立环境。
  • -X:以单一程序的方式来启动服务器。

httpd -t -D DUMP_MODULES # 查看有哪些安装的模块

指定服务器名字

  • 服务器名指定了之后,需要保障域名能够解析到这台服务器上,不然将无法访问

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf #ServerName www.example.com:80 ServerName 192.168.175.10:80 [root@localhost ~]# httpd -t # 检查语法 Syntax OK

  • 指定服务器监听地址,默认是80端口

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf Listen 80 [root@localhost ~]# systemctl reload httpd

持久连接

Persistent Connection:连接建立,每个资源获取完成后不会断开连接,而是继续等待其它的请求完成,默认关闭持久连接 断开条件:时间限制:以秒为单位, 默认5s,httpd-2.4 支持毫秒级 副作用:对并发访问量大的服务器,持久连接会使有些请求得不到响应折中:使用较短的持久连接时间

  • 相关配置

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf KeepAlive On|Off KeepAliveTimeout 15 #连接持续15s,可以以ms为单位,默认值为5s #MaxKeepAliveRequests 500 #持久连接最大接收的请求数,默认值100

  • 测试方法
    • 默认情况下响应完请求信息后连接就断开了,用telnet测试长短连接

[root@localhost ~]# yum -y install telnet [root@localhost ~]# telnet 127.0.0.1 80 GET / HTTP/1.1 Host:127.0.0.1* 修改默认的超时时间 [root@localhost ~]# telnet 127.0.0.1 80 GET / HTTP/1.1 Host:127.0.0.1

  • 特殊场景下,可以设置超时时间为毫秒级,指定 ms 时间单位即可

[root@localhost ~]#cat /etc/httpd/conf/httpd.conf|grep Keepalive Keepalive on Keepalivetimeout 30000ms

apache功能模块

  • httpd 有静态功能模块和动态功能模块组成,分别使用 httpd -l 和 httpd -M 查看
  • Dynamic Shared Object,加载动态模块配置,不需重启即生效
  • 动态模块所在路径:/usr/lib64/httpd/modules/
  • 主配置/etc/httpd/conf/httpd.conf文件中指定加载模块配置文件
  • apache模块功能介绍
  • 加载模块示例

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf Include conf.modules.d/*.conf

  • 配置指定实现模块加载格式

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf LoadModule <mod_name> <mod_path>

模块文件路径可使用相对路径:相对于ServerRoot(默认/etc/httpd) 范例:查看模块加载的配置文件[root@localhost ~]# ls /etc/httpd/conf.modules.d/ 00-base.conf 00-dav.conf 00-lua.conf 00-mpm.conf 00-proxy.conf 00-systemd.conf 01-cgi.conf # 可以指定加载的模块 [root@localhost ~]# cat /etc/httpd/conf.modules.d/00-base.conf # # This file loads most of the modules included with the Apache HTTP # Server itself. # LoadModule access_compat_module modules/mod_access_compat.so LoadModule actions_module modules/mod_actions.so LoadModule alias_module modules/mod_alias.so LoadModule allowmethods_module modules/mod_allowmethods.so LoadModule auth_basic_module modules/mod_auth_basic.so LoadModule auth_digest_module modules/mod_auth_digest.so LoadModule authn_anon_module modules/mod_authn_anon.so LoadModule authn_core_module modules/mod_authn_core.so LoadModule authn_dbd_module modules/mod_authn_dbd.so LoadModule authn_dbm_module modules/mod_authn_dbm.so LoadModule authn_file_module modules/mod_authn_file.so LoadModule authn_socache_module modules/mod_authn_socache.so LoadModule authz_core_module modules/mod_authz_core.so LoadModule authz_dbd_module modules/mod_authz_dbd.so LoadModule authz_dbm_module modules/mod_authz_dbm.so LoadModule authz_groupfile_module modules/mod_authz_groupfile.so LoadModule authz_host_module modules/mod_authz_host.so LoadModule authz_owner_module modules/mod_authz_owner.so LoadModule authz_user_module modules/mod_authz_user.so LoadModule autoindex_module modules/mod_autoindex.so LoadModule cache_module modules/mod_cache.so LoadModule cache_disk_module modules/mod_cache_disk.so LoadModule data_module modules/mod_data.so LoadModule dbd_module modules/mod_dbd.so LoadModule deflate_module modules/mod_deflate.so LoadModule dir_module modules/mod_dir.so LoadModule dumpio_module modules/mod_dumpio.so LoadModule echo_module modules/mod_echo.so LoadModule env_module modules/mod_env.so LoadModule expires_module modules/mod_expires.so LoadModule ext_filter_module modules/mod_ext_filter.so LoadModule filter_module modules/mod_filter.so LoadModule headers_module modules/mod_headers.so LoadModule include_module modules/mod_include.so LoadModule info_module modules/mod_info.so LoadModule log_config_module modules/mod_log_config.so LoadModule logio_module modules/mod_logio.so LoadModule mime_magic_module modules/mod_mime_magic.so LoadModule mime_module modules/mod_mime.so LoadModule negotiation_module modules/mod_negotiation.so LoadModule remoteip_module modules/mod_remoteip.so LoadModule reqtimeout_module modules/mod_reqtimeout.so LoadModule rewrite_module modules/mod_rewrite.so LoadModule setenvif_module modules/mod_setenvif.so LoadModule slotmem_plain_module modules/mod_slotmem_plain.so LoadModule slotmem_shm_module modules/mod_slotmem_shm.so LoadModule socache_dbm_module modules/mod_socache_dbm.so LoadModule socache_memcache_module modules/mod_socache_memcache.so LoadModule socache_shmcb_module modules/mod_socache_shmcb.so LoadModule status_module modules/mod_status.so LoadModule substitute_module modules/mod_substitute.so LoadModule suexec_module modules/mod_suexec.so LoadModule unique_id_module modules/mod_unique_id.so LoadModule unixd_module modules/mod_unixd.so LoadModule userdir_module modules/mod_userdir.so LoadModule version_module modules/mod_version.so LoadModule vhost_alias_module modules/mod_vhost_alias.so #LoadModule buffer_module modules/mod_buffer.so #LoadModule watchdog_module modules/mod_watchdog.so #LoadModule heartbeat_module modules/mod_heartbeat.so #LoadModule heartmonitor_module modules/mod_heartmonitor.so #LoadModule usertrack_module modules/mod_usertrack.so #LoadModule dialup_module modules/mod_dialup.so #LoadModule charset_lite_module modules/mod_charset_lite.so #LoadModule log_debug_module modules/mod_log_debug.so #LoadModule ratelimit_module modules/mod_ratelimit.so #LoadModule reflector_module modules/mod_reflector.so #LoadModule request_module modules/mod_request.so #LoadModule sed_module modules/mod_sed.so #LoadModule speling_module modules/mod_speling.so

main server文档页面路径

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf DocumentRoot "/var/www/html" #文档根路径 <Directory "/var/www"> Require all granted </Directory>

  • DocumentRoot指向的路径为URL路径的起始位置
  • 路径必须显式授权后才可以访问

[root@localhost ~]# httpd -M |grep dir dir_module (shared) #由本模块控制授权主页文件 [root@localhost ~]# vim /etc/httpd/conf/httpd.conf <IfModule dir_module> DirectoryIndex index.html </IfModule>

  • 关于dir_mod可以查看中文手册
  • 当访问的URL只是指定的一个目录,并没有给出具体访问的文件的时候,这个模块会在/后面自动加上index.html(默认的行为是重定向到index.html上面)
  • 可以修改httpd的配置文件来修改这个默认的首页文件

案例

  • 默认情况下主页存放于/var/www/html目录下,下面修改默认资源存放路径,指定为/data/html

[root@localhost ~]# mkdir -p /data/html [root@localhost ~]# echo "<h1>hello world</h1>" > /data/html/index.html [root@localhost ~]# vim /etc/httpd/conf/httpd.conf DocumentRoot "/data/html" # 修改资源存放路径 <Directory "/data/html"> # 给权限 AllowOverride None Require all granted </Directory> [root@localhost ~]# systemctl restart httpd [root@localhost ~]# chcon -R -t httpd_sys_content_t /data/html # 设置selinux权限

[root@localhost ~]# curl 127.0.0.1 <h1>hello world</h1>

  • 在dir_mod中添加index.htm

[root@localhost ~]# echo "<h1>hello linux</h1>" > /data/html/index.htm [root@localhost ~]# vim /etc/httpd/conf/httpd.conf <IfModule dir_module> DirectoryIndex index.html index.htm </IfModule> [root@localhost ~]# systemctl restart httpd

  • 访问这个页面,发现index.html优先于index.htm

[root@localhost ~]# curl 127.0.0.1 <h1>hello world</h1>

  • 修改index.html和index.htm的顺序

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf <IfModule dir_module> DirectoryIndex index.htm index.html </IfModule> [root@localhost ~]# systemctl restart httpd

  • 可以看到优先顺序发生了变化

[root@localhost ~]# curl 127.0.0.1 <h1>hello linux</h1>

默认页面

  • 如果在DocumentRoot目录下没有任何文件,会发现有一个默认的页面,也就是显示Testing 123..的那个页面,这个是因为有一个welcome.conf的配置文件导致的

[root@localhost ~]# cat /etc/httpd/conf.d/welcome.conf <LocationMatch "^/+$"> Options -Indexes ErrorDocument 403 /.noindex.html </LocationMatch> [root@localhost ~]# vim /usr/share/httpd/noindex/index.html

  • 上面的配置显示,当访问服务器时,提示的 http 错误代码为 403 时,使用/.noindex.html页面响应用户请求。
  • 如果将其注释,或者修改这个文件,将会就会显示apache的403报错页面
  • 如果我们想自定义报错页面,可以修改这个文件

访问控制

URI匹配规则

  • apache支持针对文件系统和URI的资源进行访问匹配

#基于目录 <Directory “/path"> ... </Directory> #基于文件 <File “/path/file”> ... </File> #基于文件通配符 <Files “/path/*file*”> ... </Files> #基于正则表达式 <FileMatch “regex”> ... </FileMatch>

  • 案例

<FilesMatch ".+\.(gif|jpe?g|png)$"> #匹配图片xxx.gif|jepg|jpg|png Require all denied </FilesMatch> <FilesMatch "\.(gif|jpe?g|png)$"> </FilesMatch> <Files ".ht*"> #禁止直接打开.ht* eg:.htaccess文件 Require all denied </Files> [root@localhost ~]# vim /etc/httpd/conf/httpd.conf <FilesMatch ".+\.(gif|jpe?g|png)$"> Require all denied </FilesMatch> #下载图片至http的目录,访问测试 [root@localhost ~]# systemctl restart httpd #配置生效再测试访问

  • apache对URL的匹配

<Location "URL"> ... </Location> <LocationMatch "regex"> ... </LocationMatch>

URL匹配规则

#/private1, /private1/,/private1/file.txt 匹配 #/private1other 不匹配 <Location "/private1"> # ... #注意斜线 </Location> #/private2/,/private2/file.txt 匹配 #/private2,/private2other 不匹配 <Location "/private2/"> # ... </Location>

Options指令

  • 后跟1个或多个以空白字符分隔的选项列表, 在选项前的+,- 表示增加或删除指定选项
  • 常见选项(默认是全部禁用):
    • Indexes:指明的URL路径下不存在与定义的主页面资源相符的资源文件时,返回索引列表给用户
    • FollowSymLinks:允许访问符号链接文件所指向的源文件
    • None:全部禁用
    • All: 全部允许
  • 在html目录下产生如下目录和文件,然后通过浏览器访问这个目录

[root@localhost ~]vim /etc/httpd/conf/httpd.conf <Directory "/var/www/html"> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> 把/var/www/html改到/data/html[root@localhost ~]# mkdir -p /data/html/dir [root@localhost ~]# cd /data/html/dir [root@localhost dir]# touch f1 f2

img
  • 这样是不安全的。因为如果没有index.html文件就会把其他的目录显示出来。所以要修改配置

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf <Directory "/data/html"> #Options Indexes FollowSymLinks 注释掉,默认就会关闭 [root@localhost html]# systemctl restart httpd

img
  • 创建一个软连接,把/etc的软连接放到html/dir中,同时取消上述的options Indexes注释

[root@localhost dir]# ln -s /etc/hosts /data/html/dir/hosts

img
  • 可以访问软连接指定文件中的内容。这样也会导致很大的安全风险。
  • 关闭FollowSymLinks选项后再次查看,发现软链接文件已经不显示了

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf <Directory "/data/html"> Options Indexes #把FollowSymLinks删掉 [root@localhost html]# systemctl restart httpd

img

AllowOverride指令

AllowOverride指令与访问控制相关的那些指令可以放在指定目录下的.htaccess(由AccessFileName 指令指定,AccessFileName .htaccess 为默认值)文件中,覆盖之前的配置指令,只对语句有效,直接在对应的文件目录中新建一个.htaccess的文件,主要作用是允许在指定路径下的配置与主配置不一样

  • 常见用法:
    • AllowOverride All:.htaccess中所有指令都有效
    • AllowOverride None:.htaccess 文件无效,此为httpd 2.3.9以后版的默认值
    • AllowOverride AuthConfig:.htaccess 文件中,除了AuthConfig 其它指令都无法生效,指定精确指令

案例

  • 在主配置文件中禁止IndexesFollowSymLinks,但是在.htaccess中打开

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf <Directory "/data/html"> Options -Indexes -FollowSymLinks AllowOverride options=FollowSymLinks,Indexes [root@localhost ~]# systemctl reload httpd

  • 创建.htaccess文件,然后发现主配置文件中的设置被修改了

[root@localhost ~]# echo "Options FollowSymLinks Indexes" > /data/html/dir/.htaccess [root@localhost ~]# systemctl reload httpd

  • 因为有主配置文件中设置了.htaccess对应的文件拒绝全部访问,所以相对是安全的

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf <Files ".ht*"> Require all denied </Files>

基于IP地址的访问控制

  • 针对各种资源,可以基于以下两种方式的访问控制
    • 客户端来源地址
    • 用户账号
  • 基于客户端的IP地址的访问控制
    • 无明确授权的目录,默认拒绝
    • 允许所有主机访问:Require all granted
    • 拒绝所有主机访问:Require all denied
    • 授权指定来源的IP访问:Require ip <IPADDR>
    • 拒绝特定的IP访问:Require not ip <IPADDR>
    • 授权特定主机访问:Require host <HOSTNAME>
    • 拒绝特定主机访问:Require not host <HOSTNAME>
  • 黑名单

[root@localhost dir]# vim /etc/httpd/conf/httpd.conf <Directory "/data/html"> <RequireAll> Require all granted Require not ip 192.168.175.1 #拒绝特定IP </RequireAll> # Require all granted 这一行记得注释掉,要不然里面写的生效不了 </Directory>

  • 白名单

<RequireAny> Require all denied require ip 192.168.175.1 #允许特定IP </RequireAny>

  • 只允许特定的网段访问

<directory "/data/html"> <requireany> require all denied Require ip 192.168.175.0/24 </requireany> </directory>

  • 只允许特定的主机访问

<Directory "/data/html"> <Requireany> Require all denied Require ip 192.168.175.10 #只允许特定的主机访问 </Requireany> </Directory>

基于用户的访问控制

  • 认证质询:WWW-Authenticate,响应码为401,拒绝客户端请求,并说明要求客户端需要提供账号和密码
  • 认证:Authorization,客户端用户填入账号和密码后再次发送请求报文;认证通过时,则服务器发送响应的资源
  • 认证方式两种
    • basic:明文
    • digest:消息摘要认证,兼容性差
  • 安全域:需要用户认证后方能访问的路径;应该通过名称对其进行标识,以便于告知用户认证的原因用户的账号和密码
  • 虚拟账号:仅用于访问某服务时用到的认证标识

配置方法

  • 定义安全域
    • 允许账号文件中的所有用户登录访问:
      • Require valid-user #表示只要在这个文件里面的用户都是有效用户,都可以访问

<Directory “/path"> Options None AllowOverride None AuthType Basic AuthName "String“ #文字提示描述 AuthUserFile "/PATH/HTTPD_USER_PASSWD_FILE" #指定存放密码文件 Require user username1 username2 ... #限制特定的人才能访问 </Directory>

  • 提供账号和密码存储(文本文件) 使用专用命令完成此类文件的创建及用户管理

htpasswd [options] /PATH/HTTPD_PASSWD_FILE username

  • 选项
    • -c:自动创建文件,仅应该在文件不存在时使用,不然就会覆盖
    • -p:明文密码
    • -d:CRYPT格式加密,默认
    • -m:md5格式加密
    • -s:sha格式加密
    • -D:删除指定用户

案例:修改主配置文件

  • 先取消掉权限控制
  • 生成文件并且创建用户

[root@localhost ~]# htpasswd -c /etc/httpd/conf.d/.httpuser user01 New password: Re-type new password: Adding password for user user [root@localhost ~]# htpasswd /etc/httpd/conf.d/.httpuser user02 New password: Re-type new password: Adding password for user user02 [root@localhost ~]# cat /etc/httpd/conf.d/.httpuser user01:$apr1$yE3jfs2/$77r76q0l6lTtREczR6uQf1 user02:$apr1$gpNpvZZr$acEh6USVYPR6/WboOMUl91

  • 在配置文件中引用这个文件

[root@localhost ~]# mkdir /data/html/admin [root@localhost ~]# echo "<h1>Hello Linux</h1>" > /data/html/admin/index.html [root@localhost ~]# vim /etc/httpd/conf.d/test.conf <directory /data/html/admin> AuthType Basic AuthName "FBI warning" AuthUserFile "/etc/httpd/conf.d/.httpuser" Require user user01 </directory> [root@localhost ~]# systemctl reload httpd

  • 在访问的时候就需要输入密码
img

案例:修改.htaccess文件

  • 生成文件并且创建用户

[root@localhost ~]# htpasswd -c /etc/httpd/conf.d/.httpuser user01 New password: Re-type new password: Adding password for user user [root@localhost ~]# htpasswd /etc/httpd/conf.d/.httpuser user02 New password: Re-type new password: Adding password for user user02 [root@localhost ~]# cat /etc/httpd/conf.d/.httpuser user01:$apr1$yE3jfs2/$77r76q0l6lTtREczR6uQf1 user02:$apr1$gpNpvZZr$acEh6USVYPR6/WboOMUl91

  • 设置AllowOverride选项为All

[root@localhost ~]# vim /etc/httpd/conf.d/test.conf <Directory "/data/html/admin"> AllowOverride Authconfig Require all granted </Directory>

  • 写入.htaccess文件

[root@localhost ~]# vim /data/html/admin/.htaccess AuthType Basic AuthName "FBI warning" AuthUserFile "/etc/httpd/conf.d/.httpuser" Require user user01 [root@localhost ~]# systemctl reload httpd

  • 最后测试是否成功
img

基于组账号进行认证

  • 可以对htpasswd产生的虚拟用户进行分组管理

<Directory “/path"> AuthType Basic AuthName "String“ AuthUserFile "/PATH/HTTPD_USER_PASSWD_FILE" AuthGroupFile "/PATH/HTTPD_GROUP_FILE" Require group grpname1 grpname2 ... </Directory>

案例

  • 创建用户

[root@localhost ~]# htpasswd -c /etc/httpd/conf.d/.httpuser user01 New password: Re-type new password: Adding password for user user [root@localhost ~]# htpasswd /etc/httpd/conf.d/.httpuser user02 New password: Re-type new password: Adding password for user user02 [root@localhost ~]# cat /etc/httpd/conf.d/.httpuser user01:$apr1$yE3jfs2/$77r76q0l6lTtREczR6uQf1 user02:$apr1$gpNpvZZr$acEh6USVYPR6/WboOMUl91

  • 创建组

[root@localhost ~]# vim /etc/httpd/conf.d/.httpgroup webadmin: user01 user02

  • 修改httpd配置文件

[root@localhost ~]# vim /etc/httpd/conf.d/test.conf <Directory “/data/html/admin"> AuthType Basic AuthName "FBI warning" AuthUserFile "/etc/httpd/conf.d/.httpuser" AuthGroupFile "/etc/httpd/conf.d/.httpgroup" Require group webadmin </Directory>

日志配置

  • httpd有两种日志类型
    • 访问日志
    • 错误日志
  • 日志等级:debug, info, notice, warn,error, crit, alert,emerg

日志格式

  • 日志格式可以自定义,查看主配置文件

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf <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>

  • 变量参考
    • %h 客户端IP地址
    • %l 远程用户,启用mod_ident才有效,通常为减号“-”
    • %u 验证(basic,digest)远程用户,非登录访问时,为一个减号“-”
    • %t 服务器收到请求时的时间
    • %r First line of request,即表示请求报文的首行;记录了此次请求的“方法”,“URL”以及协议版本
    • %>s 对于已在内部重定向的请求,这是原始请求的状态。使用%>s 的最终状态。类型脚本中的exit 数字
    • %b 响应报文的大小,单位是字节;不包括响应报文http首部
    • %{Referer}i 请求报文中首部“referer”的值;即从哪个页面中的超链接跳转至当前页面。 { }里面内容就是报文中的一个键值对
    • %{User-Agent}i 请求报文中首部“User-Agent”的值;即发出请求的应用程序,多数为浏览器型号
  • 日志存放位置

[root@localhost ~]# ls /var/log/httpd/ access_log error_log

  • 这个文件夹默认是软连接过来的

[root@localhost ~]# ll -d /etc/httpd/logs lrwxrwxrwx. 1 root root 19 5月 2 09:30 /etc/httpd/logs -> ../../var/log/httpd

别名模块alias_module

alias 别名,可以隐藏真实文件系统路径。这里实现的目的是用news文件目录来替代newsdir/index.html访问文件路径,从而起到隐藏真实文件系统路径的目的。

  • 我们让dir目录隐藏,让其可以被news路径访问

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf <IfModule alias_module> ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" Alias /news/ /data/html/dir/ </IfModule> [root@localhost ~]# systemctl reload httpd

img

httpd服务状态信息显示

  • 当我们需要获取 httpd 服务器在运行过程中的实时状态信息时可以使用该功能

[root@localhost ~]# vim /etc/httpd/conf.d/test.conf <Location "/status"> <requireany> require all denied require ip 192.168.175.0/24 #定义特定的网段能够访问 </requireany> SetHandler server-status #指定状态信息 </Location> ExtendedStatus On [root@localhost ~]# systemctl reload httpd

  • 获取 httpd 服务状态信息成功
img

虚拟主机

  • 虚拟主机,就是把一台物理服务器划分成多个“虚拟”的服务器,这样我们的一台物理服务器就可以当做多个服务器来使用,从而可以配置多个网站。
  • httpd 支持在一台物理主机上实现多个网站,即多虚拟主机
  • 网站的唯一标识
    • IP相同,但端口不同
    • IP不同,但端口均为默认端口
    • FQDN不同
  • 多虚拟主机有三种实现方案
    • 基于ip:为每个虚拟主机准备至少一个ip地址
    • 基于port:为每个虚拟主机使用至少一个独立的port
    • 基于FQDN:为每个虚拟主机使用至少一个FQDN,域名
  • 虚拟主机的基本配置方法

<VirtualHost IP:PORT> ServerName FQDN DocumentRoot “/path" </VirtualHost> # 建议:上述配置存放在独立的配置文件中

  • 其它常用可用指令

ServerAlias:虚拟主机的别名;可多次使用 ErrorLog: 错误日志 CustomLog:访问日志 <Directory “/path"> </Directory>

基于端口的虚拟主机

[root@localhost ~]# mkdir /data/website{1,2,3} [root@localhost ~]# echo "This is NO.1 website" > /data/website1/index.html [root@localhost ~]# echo "This is NO.2 website" > /data/website2/index.html [root@localhost ~]# echo "This is NO.3 website" > /data/website3/index.html [root@localhost ~]# tree /data/ /data/ ├── website1 │ └── index.html ├── website2 │ └── index.html └── website3 └── index.html 3 directories, 3 files [root@localhost ~]#vim /etc/httpd/conf.d/test.conf [root@localhost ~]#cat /etc/httpd/conf.d/test.conf listen 8001 listen 8002 listen 8003 #指定端口 <virtualhost *:8001> documentroot /data/website1/ #指定定义的路径 CustomLog logs/website1_access.log combined #增加对应的日志 <directory /data/website1> #对于文件给与访问权限 require all granted </directory> </virtualhost> <virtualhost *:8002> documentroot /data/website2/ CustomLog logs/website2_access.log combined <directory /data/website2> require all granted </directory> </virtualhost> <virtualhost *:8003> documentroot /data/website3/ CustomLog logs/website3_access.log combined <directory /data/website3> require all granted </directory> </virtualhost> [root@localhost ~]# systemctl restart httpd [root@localhost ~]# ll /var/log/httpd/ #各有各的访问日志 total 24 -rw-r--r-- 1 root root 2084 Dec 12 21:41 access_log -rw-r--r-- 1 root root 4441 Dec 12 21:40 error_log -rw-r--r-- 1 root root 506 Dec 12 21:42 website1_access.log -rw-r--r-- 1 root root 506 Dec 12 21:43 website2_access.log -rw-r--r-- 1 root root 570 Dec 12 21:44 website3_access.log [root@localhost ~]# curl 192.168.175.10:8001 This is NO.1 website! [root@localhost ~]# curl 192.168.175.10:8002 This is NO.2 website! [root@localhost ~]# curl 192.168.175.10:8003 This is NO.3 website!

基于IP的虚拟主机

nmtui添加ip 192.168.175.20 自行搜索添加一个IP systemctl restart network [root@localhost data]# vim /etc/httpd/conf.d/site.conf <Directory "/data/"> Require all granted </Directory> <VirtualHost 192.168.175.10:80> Servername www.site1.com DocumentRoot "/data/site1/" </VirtualHost> <VirtualHost 192.168.175.20:80> Servername www.site2.com DocumentRoot "/data/site2/" </VirtualHost> [root@localhost data]# mkdir site1 [root@localhost data]# mkdir site2 [root@localhost data]# echo "site1" >> site1/index.html [root@localhost data]# echo "site2" >> site2/index.html [root@localhost ~]# curl 192.168.175.10 <h1>This is site1</h1> [root@localhost ~]# curl 192.168.175.20 <h1>This is site2</h1>

基于FQDN虚拟主机

FQDN:完全限定域名(英语:Fully qualified domain name),缩写为FQDN,又译为完全资格域名、完整领域名称

例如www.baidu.com这个就是一个FQDN,而www是这台服务器的主机名,但是可以看到网上很多台服务器主机名都是www,所以这个是它自己取的别名,即CNAME。 域名:例如baidu.com这个就是一个域名了。[root@localhost ~]# cat /etc/httpd/conf.d/site.conf <Directory "/data/"> Require all granted </Directory> <VirtualHost 192.168.175.10:80> Servername www.site111.com DocumentRoot "/data/site1/" </VirtualHost> <VirtualHost 192.168.175.10:80> Servername www.site222.com DocumentRoot "/data/site2/" </VirtualHost> [root@localhost ~]# cat /etc/hosts 192.168.175.10 www.site1.com 192.168.175.10 www.site2.com [root@localhost ~]# curl www.site1.com [root@localhost ~]# curl www.site2.com

网页压缩

  • 压缩原理:文本VS视频?为什么视频更难压缩,大部分情况下压缩比例更高
  • 使用mod_deflate模块压缩页面优化传输速度
  • 适用场景
    • 节约带宽,额外消耗CPU;同时,可能有些较老浏览器不支持
    • 压缩适于压缩的资源,例如文本文件
  • 确认是否加载浏览器压缩模块

[root@localhost ~]# httpd -M |grep deflate deflate_module (shared)

  • 压缩指令

#可选项 SetOutputFilter DEFLATE # 指定对哪种MIME类型进行压缩,必须指定项 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 #压缩级别 (Highest 9 - Lowest 1) ,默认gzip 默认级别是有库决定 DeflateCompressionLevel 9 #排除特定旧版本的浏览器,不支持压缩 #Netscape 4.x 只压缩text/html BrowserMatch ^Mozilla/4 gzip-only-text/html #Netscape 4.06-08 三个版本 不压缩 BrowserMatch ^Mozilla/4\.0[678] no-gzip #Internet Explorer标识本身为“Mozilla / 4”,但实际上是能够处理请求的压缩。如果用户代理首部

压缩对比实验

[root@localhost ~]# vim /etc/httpd/conf.d/site.conf <virtualhost *:80> documentroot /data/website1/ servername www.site1.com <directory /data/website1/> require all granted </directory> CustomLog "logs/a_access_log" combined AddOutputFilterByType DEFLATE text/plain #增加压缩机制 AddOutputFilterByType DEFLATE text/html #增加压缩机制 DeflateCompressionLevel 9 #选择默认压缩级别 </virtualhost> <virtualhost *:80> documentroot /data/website2/ servername www.site2.com <directory /data/website2/> require all granted </directory> CustomLog "logs/b_access_log" combined #AddOutputFilterByType DEFLATE text/plain #注释掉 形成对比 #AddOutputFilterByType DEFLATE text/html #注释掉 形成对比 #DeflateCompressionLevel 9 #注释掉 形成对比 </virtualhost> [root@localhost ~]# vim /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.175.10 www.site1.com 192.168.175.10 www.site2.com #新增DNS解析 [root@localhost ~]# cp blog.txt /data/website1/blog_test1.html #拷贝一个测试文件到网页 [root@localhost ~]# cp blog.txt /data/website2/blog_test2.html [root@localhost ~]# cd /data/website1 [root@localhost website1]#ll total 20 -rw-r--r-- 1 root root 15422 Dec 13 10:14 blog_test1.html #注意大小为15422 -rw-r--r-- 1 root root 22 Dec 13 09:25 index.html [root@localhost website1]#cd /data/website2 [root@localhost website2]#ll total 20 -rw-r--r-- 1 root root 15422 Dec 13 10:14 blog_test2.html #注意大小为15422 -rw-r--r-- 1 root root 22 Dec 13 09:25 index.html 如果文件的权限不是644则需要增加对应的权限: chmod 644 blog_testX.html [root@localhost website2]# cd [root@localhost ~]# systemctl restart httpd [root@localhost ~]# curl www.site1.com This is NO.1 website! [root@localhost ~]# curl www.site2.com This is NO.2 website! [root@localhost ~]# curl -I --compressed www.aaa.com/blog_test1.html #默认curl没有压缩,需要加参数--compressed HTTP/1.1 200 OK Date: Fri, 13 Dec 2019 02:22:29 GMT Server: Apache/2.4.37 (centos) Last-Modified: Fri, 13 Dec 2019 02:14:32 GMT ETag: "3c3e-5998c6c2c195b-gzip" Accept-Ranges: bytes Vary: Accept-Encoding Content-Encoding: gzip #压缩机制工具gzip Content-Length: 2155 #压缩后的大小 Content-Type: text/html; charset=UTF-8 [root@localhost ~]# curl -I --compressed www.bbb.com/blog_test2.html HTTP/1.1 200 OK Date: Fri, 13 Dec 2019 02:22:45 GMT Server: Apache/2.4.37 (centos) Last-Modified: Fri, 13 Dec 2019 02:14:45 GMT ETag: "3c3e-5998c6ce8741a" Accept-Ranges: bytes Content-Length: 15422 #没有压缩的大小,配置文件中website2压缩被注释 Content-Type: text/html; charset=UTF-8

HTTPS实验

  • SSL是基于IP地址实现,单IP的httpd主机,仅可以使用一个https虚拟主机
  • 实现多个虚拟主机站点,apache不能支持,nginx支持
  • SSL实现过程
    • 客户端发送可供选择的加密方式,并向服务器请求证书
    • 服务器端发送证书以及选定的加密方式给客户端
    • 客户端取得证书并进行证书验证,如果信任给其发证书的CA
      • 验证证书来源的合法性;用CA的公钥解密证书上数字签名
      • 验证证书的内容的合法性:完整性验证
      • 检查证书的有效期限
      • 检查证书是否被吊销
      • 证书中拥有者的名字,与访问的目标主机要一致
    • 客户端生成临时会话密钥(对称密钥),并使用服务器端的公钥加密此数据发送给服务器,完成密钥交换
    • 服务用此密钥加密用户请求的资源,响应给客户端
  • 安装 mod_ssl 软件包,并且检查443端口是否开放

SSL证书颁发:自己跟自己玩 1.安装mod_ssl和openssl [root@node1 ~]# yum install mod_ssl openssl -y 2.生成2048位的加密私钥 [root@node1 ~]# openssl genrsa -out server.key 2048 3.生成证书签名请求(CSR) [root@node1 ~]# openssl req -new -key server.key -out server.csr 4.生成类型为X509的自签名证书。有效期设置3650天,即有效期为10年 [root@node1 ~]# openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt 5.复制文件到相应的位置 [root@node1 ~]# cp server.crt /etc/pki/tls/certs/ [root@node1 ~]# cp server.key /etc/pki/tls/private/ [root@node1 ~]# cp server.csr /etc/pki/tls/private/ 生产环境中需要去权威机构进行申请: 6.修改配置文件 [root@node1 ~]# vim /etc/httpd/conf.d/ssl.conf Servername 192.168.175.10:443 # SSLCertificateFile /etc/pki/tls/certs/server.crt # 指定证书的存储位置 # SSLCertificateKeyFile /etc/pki/tls/private/server.key # 加密密钥的存储位置 [root@node1 ~]# systemctl restart httpd

  • 可以使用curl命令查看证书,可以看到一个非权威机构的证书

[root@localhost ~]# curl -kv https://127.0.0.1 #k表示支持https #v表示显示详细的信息

https功能

Web网站的登录页面都是使用https加密传输的,加密数据以保障数据的安全,HTTPS能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议,HTTPS其实是有两部分组成: HTTP + SSL/ TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。

img

https 实现过程如下:

  1. 客户端发起HTTPS请求
    1. 客户端访问某个web端的https地址,一般都是443端口
  2. 服务端的配置
    1. 采用https协议的服务器必须要有一套证书,可以通过权威机构申请,也可以自己制作,目前国内很多⽹站都⾃⼰做的,当你访问⼀个⽹站的时候提示证书不可信任就表示证书是⾃⼰做的,证书就是⼀个公钥和私钥匙,就像⼀把锁和钥匙,正常情况下只有你的钥匙可以打开你的锁,你可以把这个送给别⼈让他锁住⼀个箱⼦,⾥⾯放满了钱或秘密,别⼈不知道⾥⾯放了什么⽽且别⼈也打不开,只有你的钥匙是可以打开的。对称加密与非对称加密区别 对称加密只有密钥 非对称加密有公私钥,公钥加密,私钥解密
  1. 传送证书
    1. 服务端给客户端传递证书,其实就是公钥,⾥⾯包含了很多信息,例如证书得到颁发机构、过期时间等等。
  2. 客户端解析证书
    1. 这部分⼯作是有客户端完成的,⾸先回验证公钥的有效性,⽐如颁发机构、过期时间等等,如果发现异常则会弹出⼀个警告框提示证书可能存在问题,如果证书没有问题就⽣成⼀个随机值,然后⽤证书对该随机值进⾏加密,就像2步骤所说把随机值锁起来,不让别⼈看到。
  3. 传送4步骤的加密数据
    1. 就是将⽤证书加密后的随机值传递给服务器,⽬的就是为了让服务器得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值进⾏加密解密了。
  4. 服务端解密信息
    1. 服务端用私钥解密5步骤加密后的随机值之后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进⾏对称加密,对称加密就是将信息和私钥通过算法混合在⼀起,这样除非你知道私钥,不然是⽆法获取其内部的内容,而正好客户端和服务端都知道这个私钥,所以只要机密算法够复杂就可以保证数据的安全性。
  5. 传输加密后的信息
    1. 服务端将⽤私钥加密后的数据传递给客户端,在客户端可以被还原出原数据内容
  6. 客户端解密信息
    1. 客户端⽤之前⽣成的私钥获解密服务端传递过来的数据,由于数据⼀直是加密的,因此即使第三⽅获取到数据也⽆法知道其详细内容。

URL重定向

  • URL重定向,即将httpd 请求的URL转发至另一个的URL
  • 重定向指令

Redirect [status] URL-path URL

  • status状态
    • permanent: 返回永久重定向状态码 301
    • temp:返回临时重定向状态码302. 此为默认值

MPM多路处理模块

httpd 支持三种MPM工作模式:prefork, worker, event

  • MPM工作模式
    • prefork:多进程I/O模型,一个主进程,管理多个子进程,一个子进程处理一个请求。
    • worker:复用的多进程I/O模型,多进程多线程,一个主进程,管理多个子进程,一个子进程管理多个线程,每个线程处理一个请求。
    • event:事件驱动模型,一个主进程,管理多个子进程,一个进程处理多个请求(实际是线程处理请求)。跟worker差不多,但是区别在于,如果发生长连接情况下会单独起子进程去处理长连接,防止队列排的过长,一个子进程可以处理多个长连接请求,在长连接发起请求的时候,相当于触发了事件,进行处理。
  • 查看centos7中默认的mpm

[root@localhost ~]# cat /etc/httpd/conf.modules.d/00-mpm.conf |grep mpm #默认是prefork 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

  • 查看进程

[root@localhost ~]# ps aux |grep httpd root 7116 0.0 0.2 224072 5016 ? Ss 10:39 0:00 /usr/sbin/httpd -DFOREGROUND apache 7124 0.0 0.1 224072 2960 ? S 10:39 0:00 /usr/sbin/httpd -DFOREGROUND apache 7125 0.0 0.1 224072 2960 ? S 10:39 0:00 /usr/sbin/httpd -DFOREGROUND apache 7126 0.0 0.1 224072 2960 ? S 10:39 0:00 /usr/sbin/httpd -DFOREGROUND apache 7127 0.0 0.1 224072 2960 ? S 10:39 0:00 /usr/sbin/httpd -DFOREGROUND apache 7128 0.0 0.1 224072 2960 ? S 10:39 0:00 /usr/sbin/httpd -DFOREGROUND root 7214 0.0 0.0 112724 984 pts/0 S+ 10:50 0:00 grep --color=auto httpd [root@localhost ~]# yum -y install psmisc [root@localhost ~]# pstree -p 7116 httpd(7116)─┬─httpd(7124) ├─httpd(7125) ├─httpd(7126) ├─httpd(7127) └─httpd(7128)

  • 修改MPM工作模式为mod_mpm_worker.so

[root@localhost ~]# cat /etc/httpd/conf.modules.d/00-mpm.conf |grep mpm #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 [root@localhost ~]# systemctl restart httpd [root@localhost ~]# ps aux |grep httpd root 7231 0.2 0.2 224276 5224 ? Ss 10:52 0:00 /usr/sbin/httpd -DFOREGROUND apache 7232 0.0 0.1 224024 2928 ? S 10:52 0:00 /usr/sbin/httpd -DFOREGROUND apache 7233 0.0 0.3 576640 7560 ? Sl 10:52 0:00 /usr/sbin/httpd -DFOREGROUND apache 7234 0.0 0.3 511104 7564 ? Sl 10:52 0:00 /usr/sbin/httpd -DFOREGROUND apache 7235 0.0 0.3 576640 7568 ? Sl 10:52 0:00 /usr/sbin/httpd -DFOREGROUND root 7318 0.0 0.0 112724 984 pts/0 S+ 10:52 0:00 grep --color=auto httpd [root@localhost ~]# pstree -p 7231 httpd(7231)─┬─httpd(7232) ├─httpd(7233)─┬─{httpd}(7241) │ ├─{httpd}(7259) │ ├─{httpd}(7261) │ ├─{httpd}(7263) │ ├─{httpd}(7265) │ ├─{httpd}(7267)

prefork模式

img

默认的工作模式是Prefork MPM,这种模式采用的是预派生子进程方式,用单独的子进程来处理请求,

子进程间互相独立,互不影响,大大的提高了稳定性

但每个进程都会占用内存,所以消耗系统资源过高。

Prefork MPM 工作原理:控制进程Master首先会生成“StartServers”个进程,“StartServers”可以在Apache主配置文件里配置,然后为了满足“MinSpareServers”设置的最小空闲进程个数,会建立一个空闲进程,等待一秒钟,继续创建两个空闲进程,再等待一秒钟,继续创建四个空闲进程,以此类推,会不断的递归增长创建进程,最大同时创建32个空闲进程,直到满足“MinSpareServers”设置的空闲进程个数为止。Apache的预派生模式不必在请求到来的时候创建进程,这样会减小系统开销以增加性能,不过Prefork MPM是基于多进程的模式工作的,每个进程都会占用内存,这样资源消耗也较高。

  • 将apache切换到prefork的模式下,可以通过httpd -V来查看

[root@localhost ~]# httpd -V Server version: Apache/2.4.6 (CentOS) Server built: Nov 16 2020 16:18:20 Server's Module Magic Number: 20120211:24 Server loaded: APR 1.4.8, APR-UTIL 1.5.2 Compiled using: APR 1.4.8, APR-UTIL 1.5.2 Architecture: 64-bit Server MPM: prefork threaded: no forked: yes (variable process count)

  • 通过调整配置文件,可以修改prefork的参数,新建一个配置文件

[root@localhost ~]# vim /etc/httpd/conf.d/mpm.conf StartServers 5 #开始访问进程 MinSpareServers 5 #最小空闲进程,最少有多少个进程的意思 MaxSpareServers 10 #无人访问时,留下空闲的进程 ServerLimit 256 #最多进程数,最大值 20000 MaxRequestWorkers 256 #最大的并发连接数,默认256 MaxConnectionsPerChild 4000 #新版使用方式 #子进程最多能处理的请求数量。在处理MaxRequestsPerChild个请求之后,子进程将会被父进程终止,这时候子进程占用的内存就会释放(为0时永远不释放) #MaxRequestsPerChild 4000 #老版 #从 httpd.2.3.9开始MaxRequestsPerChild被MaxConnectionsPerChild代替 cat -A /etc/httpd/conf.d/mpm.conf [root@localhost ~]# systemctl restart httpd

  • 查看进程数

[root@localhost ~]# pstree -p|grep httpd httpd(7606)─┬─httpd(7607) ├─httpd(7608) ├─httpd(7609) ├─httpd(7610) └─httpd(7611)

  • 修改prefork参数

[root@localhost ~]# vim /etc/httpd/conf.d/mpm.conf StartServers 10 MaxSpareServers 15 MinSpareServers 10 MaxRequestWorkers 256 MaxConnectionsPerChild 4000 [root@localhost ~]# systemctl restart httpd

  • 查看是否生效

[root@localhost ~]# pstree -p 7628 httpd(7628)─┬─httpd(7629) ├─httpd(7630) ├─httpd(7631) ├─httpd(7632) ├─httpd(7633) ├─httpd(7634) ├─httpd(7635) ├─httpd(7636) ├─httpd(7637) └─httpd(7638)

  • 使用ab进行压力测试

[root@localhost ~]# ab -c 1000 -n 1000000 http://127.0.0.1/ # -c 即concurrency,用于指定的并发数 # -n 即requests,用于指定压力测试总共的执行次数

  • 测试过程中,可以看到最大进程数

另外启动一个窗口 [root@localhost ~]# watch -n 0.5 "ps aux |grep httpd |wc -l" [root@localhost ~]# ps aux |grep httpd |wc -l 256

  • 结束ab的压力测试,等待一段时间,可以看到进程数慢慢减少

[root@localhost ~]# watch -n 0.5 'pstree -p|grep httpd|wc -l' [root@localhost ~]# ps aux |grep httpd |wc -l 12

worker模式

img

Worker MPM是Apche 2.0版本中全新的支持多进程多线程混合模型的MPM,由于使用线程来处理HTTP请求,所以效率非常高,而对系统的开销也相对较低,Worker MPM也是基于多进程的,但是每个进程会生成多个线程,由线程来处理请求,这样可以保证多线程可以获得进程的稳定性;

Worker MPM工作原理: 控制进程Master在最初会建立“StartServers”个进程,然后每个进程会创建“ThreadPerChild”个线程,多线程共享该进程内的资源,同时每个线程独立的处理HTTP请求,为了不在请求到来的时候创建线程,Worker MPM也可以设置最大最小空闲线程,Worker MPM模式下同时处理的请求=ThreadPerChild*进程数,也就是MaxClients,如果服务负载较高,当前进程数不满足需求,Master控制进程会fork新的进程,最大进程数不能超过ServerLimit数,如果需要,可以调整这些对应的参数,比如,如果要调整StartServers的数量,则也要调整 ServerLimit的值

https://httpd.apache.org/docs/2.4/mod/
  • 修改mpm文件为官方提供的默认数值,然后切换模式到worker模式

[root@localhost ~]# vim /etc/httpd/conf.d/mpm.conf ServerLimit 16 StartServers 2 MaxRequestWorkers 150 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 #最大并发请求数150x75 [root@localhost ~]# cat /etc/httpd/conf.modules.d/00-mpm.conf |grep mpm #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 [root@localhost ~]# systemctl restart httpd [root@localhost ~]# httpd -V Server version: Apache/2.4.6 (CentOS) Server built: Nov 16 2020 16:18:20 Server's Module Magic Number: 20120211:24 Server loaded: APR 1.4.8, APR-UTIL 1.5.2 Compiled using: APR 1.4.8, APR-UTIL 1.5.2 Architecture: 64-bit Server MPM: worker threaded: yes (fixed thread count) forked: yes (variable process count)

  • 查看压力测试前后的进程数,查看线程数

[root@localhost ~]# ps aux |grep httpd |wc -l 5 [root@localhost ~]# pstree -p |grep httpd | wc -l 53 [root@localhost ~]# ab -c 1000 -n 1000000 http://127.0.0.1/ [root@localhost ~]# watch -n0.5 'pstree -p |grep httpd | wc -l'

event模式

img

这个是 Apache中最新的模式,在现在版本里的已经是稳定可用的模式。它和 worker模式很像,最大的区别在于,它解决了 keep-alive 场景下 ,长期被占用的线程的资源浪费问题(某些线程因为被keep-aleive,挂在那里等待,中间几乎没有请求过来,一直等到超时)。

event MPM中,会有一个专门的线程来管理这些 keep-alive 类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样,一个线程就能处理几个请求了,实现了异步非阻塞。

event MPM在遇到某些不兼容的模块时,会失效,将会回退到worker模式,一个工作线程处理一个请求。官方自带的模块,全部是支持event MPM的。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇