apache 调优
生产环境中,部署了 apache 之后,我们应该从安全还是性能角度,在 apache 服务上线之前,对其做诸多的优化调试才行。
- 隐藏 apache 版本信息
- 设置错误页面-开启压缩和缓存功能
- 开启长连接功能
-
实验环境:
操作系统: CentOS Linux release 7.6.1810
apache 版本:Apache HTTP Server 2.4.48 - 防火墙、SElinux、IPtables均为关闭状态
- wget https://mirrors.bfsu.edu.cn/apache//httpd/httpd-2.4.48.tar.gz
-
屏蔽 Apache 版本等敏感信息
为什么要屏蔽 Apache 版本信息?
答:因为黑客可以扫描出 Apache 版本信息,可以查看对应的版本信息的漏洞,然后攻击.
如何查 Apache 版本信息?
查看网站的版本信息: - curl -I baidu.com
- curl -I 163.com
-
要彻底将版本之类的信息进行改头换面,需要在编译之前修改源码包下 include/ap_release.h 文件
- tar xf httpd-2.4.48.tar.gz -C /opt/
- vim /opt/httpd-2.4.48/include/ap_release.h #修改源码中的版本信息,隐藏真实版本信息
- 默认信息
- 修改信息
- 注释:
#define AP_SERVER_BASEVENDOR "Apache Software Foundation" #服务的供应商名称
#define AP_SERVER_BASEPROJECT "Apache HTTP Server" #服务的项目名称
#define AP_SERVER_BASEPRODUCT "Apache" #服务的产品名
#define AP_SERVER_MAJORVERSION_NUMBER 2 #主要版本号
#define AP_SERVER_MINORVERSION_NUMBER 4 #小版本号
#define AP_SERVER_PATCHLEVEL_NUMBER 6 #补丁级别
#define AP_SERVER_DEVBUILD_BOOLEAN 0 #
注:上述列出的行,大家可以修改成自己想要的,然后编译安装之后,再对 httpd-default.conf 文件进行修改,对方就彻底不知道你的版本号了
- 开始编译安装
- 安装依赖包:
yum install apr-util apr-util-devel apr apr-devel pcre pcre-devel zlib zlib-devel openssl openssl-devel gcc -y - tar -xf httpd-2.4.48.tar.gz -C /opt/ && cd /opt/httpd-2.4.48/
- ./configure --prefix=/usr/local/apache2.4.48 --enable-so --enable-rewrite --enable-ssl --enable-deflate --enable-expires
- 检查安装环境并生成 Makefile 文件
配置参数用途:
--prefix=/usr/local/apache2.4.48 #指定安装路径
--enable-so #支持动态加载模块
--enable-rewrite #支持网站地址重写
--enable-ssl #支持 ssl 加密,比如: https 443
--enable-deflate #支持页面传输前进行压缩
--enable-expires #支持设置网页缓存的时间
- make clean && make -j 4 #把源代码编译成可执行的二进制文件。
- 扩展:如果 linux 服务器的 CPU 是 4 核, 那么使用 top 命令查看时,一服务使用 CPU 的百分比最高可以达到多少?
- 如果你的 4 核心的 cpu,你可以运行 400%
实战经验: 公司 mysql 数据库经常使用 CPU 达到 230%,正常吗? 服务器是 4 核的。
答:使用 cpu 达到 230%,还算正常。如果觉得不正常,可以使用以下思路进行排查
1、登陆 IDC 机房查看服务器流量图,流量正常,排除故障与流量无关。
2、为了快速解决问题,可以先直接重启 mysql 服务后,再查 sysql 进程 CPU 使用率依旧高居不下。
3. 登陆 mysql 数据库,执行 show processlist;查看当前正在执行的 sql 语句,发现几个表出现“sending data”状态,sql 执行时间过长。
4、通知开发人员检查这几个表有没有增加索引,让开发查看一下。
5、在 mysql 配置文件 my.cnf 中增加以下参数:tmp_table_size = 300M 和 query_cache_size = 1024M 希望通过增加临时表及查询缓存大小来解决问题,增加这两个参数后,发现 CPU 占用率有所下降,有一定效果,但还是超过 100%。网站打开依旧缓慢。
6、继续登陆 mysql,执行 show index from tablename,查询出现“sending data”的几个表,发现果然没有增加索引。
7、执行增加索引的语句,把出现“sending data”的几个表全部加上索引。
ALTER TABLE table_name ADD INDEX index_name (column_list) #增加普通索引
ALTER TABLE table_name ADD UNIQUE (column_list) #增加唯一性索引
ALTER TABLE table_name ADD PRIMARY KEY (column_list) #增加主键索引
注:Primary key 和 UNIQUE KEY 区别
1,Primary key 的 1 个或多个列必须为 NOT NULL,如果列为 NULL,在增加 PRIMARY KEY时,列自动更改为 NOT NULL。而 UNIQUE KEY 对列没有此要求
2,一个表只能有一个 PRIMARY KEY,但可以有多个 UNIQUE KEY - 总结:重启 mysql 服务后,mysql 进程的 CPU 占用率恢复正常,网站正常登陆,至此故障得到解决。通知同事验证。后期工作中,可以和开发人员说一下,需要大量查询的表中一定要加索引。
- make install
安装软件的本质: 就把二进制文件复制到对应的目录下并给权限。
- 启动 Apache:
配置 apache 可以开机启动并且可以使用 service 命令启动 apache 服务器
- cp /usr/local/apache-2.4.48/bin/apachectl /etc/init.d/apache
chmod +x /etc/init.d/apache
ll /etc/init.d/apache
-rwxr-xr-x 1 root root 3455 Jul 25 09:10 /etc/init.d/apache
/etc/init.d/apache start
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::20c:29ff:feb9:c770. Set the 'ServerName' directive globally to suppress this message
- 这里有个报错,ServerName 没有设置
- 编辑 apache 配置文件
- vim /usr/local/apache-2.4.48/conf/httpd.conf
- 修改完配置文件要生效,必须重启服务或者重新加载配置文件
- /etc/init.d/apache graceful #不重启服务加载配置文件
- 浏览器访问
- 测试:查看 Apache 版本信息
curl -I 192.168.2.40 #看不到 Apache 原来版本相关内容了
- 再次隐藏系统类型和模块的版本号
接下来再次修改: - 编辑 apache 配置文件
- vim /usr/local/apache-2.4.48/conf/httpd.conf
- 去掉 注释 引用 httpd-default.conf
- Include conf/extra/httpd-default.conf
- 打开 httpd-default.conf 文件,修改如下
- ServerTokens Prod #不显示服务器操作系统类型
ServerSignature Off #不显示 web 服务器版本号和模块版本。现在默认值就是 off 了,不用修改。在 apache2.4 之前的版本,默认值是 On,需要改成 Off
- 不重启服务,重新加载配置文件
- /etc/init.d/apache graceful
- 设置开机自动启动:
- chkconfig --add apache
service apache does not support chkconfig 报错 - vim /etc/init.d/apache
#!/bin/sh
# chkconfig:2345 80 30
- 重启测试
- 修改运行 apache 的默认用户
通过更改 apache 的默认用户,可以提升 apache 的安全性。这样,即使 apache 服务被攻破,黑客拿到 apache 普通用户也不会对系统和其他应用造成破坏。这里创建的 apache 用户,将用于对子进程和线程的控制。
注:默认使用 daemon 用户是安全的,也可以修改成其他用户 - 创建 apache 用户
useradd -M -s /sbin/nologin apache
-M:不要自动建立用户的登入目录。 - 编辑 Apache 配置文件,修改默认的用户:
vim /usr/local/apache2.4.48/conf/httpd.conf
改:165 User daemon
166 Group daemon
为:
165 User apache
166 Group apache
- 重新加载配置文件验证
- Apache 目录及文件权限设置
在生产环境的网站架构中,应把资源文件的权限合理的配置好,但不能给 777 权限。
例:用户上传的图片及附件等和程序做好分离。这样才能更方便我们做好授权,保证 apache 服务和整个服务器安全。
这里设置 Apache 的网站目录属主和属组是 apache: - chown -R apache. /usr/local/apache2.4.46/htdocs/
- 保护 Apache 日志、设置好 Apache 日志文件权限
对日志的授权,要将属主和属组都设置为 root:
- 注:由于 Apache 日志的记录是由 Apache 的主进程进行操作的,而 Apache 的主进程又是 root 用户启动的,所以这样不影响日志的输出。这也是日志记录的最安全的方法。
- 使用 Cronolog 分割 Apache 日志
apache 服务器,默认日志文件是不分割的,一个整文件既不易于管理,也不易于分析统计。 - cronolog 是一个简单的过滤程序,读取日志文件条目从标准输入和输出的每个条目并写入指定的日志文件的文件名模板和当前的日期和时间。 当扩展文件名的变化,目前的文件是关闭,新开辟的。
- cronolog 旨在和一个 Web 服务器一起使用,如 Apache,分割访问日志为每天或每月的日志
下载并安装 Cronolog: 需要 epel 源 - yum install cronolog -y
- 配置 Apache 使用 cronolog
- vim /usr/local/apache2.4.46/conf/httpd.conf
- CustomLog "|/usr/sbin/cronolog /usr/local/apache2.4.46/logs/access_%Y%m%d.log" combined
- ErrorLog "|/usr/sbin/cronolog /usr/local/apache2.4.46/logs/error_%Y%m%d.log"
- 更多日志格式参考:
按天轮询(生产环境常见用法,推荐使用):
CustomLog "|/usr/local/sbin/cronolog /app/logs/access_www_%Y%m%d.log" combined
按小时轮询(生产环境较常见用法):
CustomLog "|/usr/local/sbin/cronolog /app/logs /access_www_ %Y%m%d%H.log" combined
- 重新加载配置文件
- 访问日志没有被分割是因为没有新的访问
- 刷新页面然后再观察
-
设置错误页面、开启压缩和缓存功能
-
错误页面优雅显示
为了提升网站的用户体验,避免 404,403 之类的丑陋的默认错误提示出现。需要对错误页面进行优化,让他们变的漂亮一点。错误页面不仅在于告诉用户访问出现了问题,而且需要引导用户到正确的页面。
错误页面优雅化显示的实现方式主要有两种,下面主要以 404 错误为例: -
方法一:
vim /usr/local/apache2.4.46/conf/httpd.conf #在根目录的标签中添加以下内容。
<Directory "/usr/local/apache2.4.46/htdocs"> #在这行下面添加如下内容:
ErrorDocument 404 /404.html
注: #将 404 错误跳转到/usr/local/apache2.4.46/htdocs 下的 404.html 页面上。
创建 404 测试页:
echo "<h1>404 file is not found </h1>" > /usr/local/apache2.4.46/htdocs/404.html
- 打开浏览器访问不存在页面测试
- 注意:
如果重启 Apache 以后在地址栏里故意输入了一个不存在的页面,发现 IE 并没有打开如上所设置的404 页面,这种情况并不是如上所设置没起作。,而是 IE 里设置里有一个选项“显示友好的 HTTP 错误信息”,一般默认是选中的,这样错误文件要大于 512 个字节才会被显示。但是打开 Apache 的日志文件 access_log,可以看到 404 错误的响应只有 15 个字节,因此 IE 没有显示,解决的方法就是关掉 IE的这个选项,或者重写一个大一点的错误页面
- 第二种方法:遇到 404 错误后,直接跳转到一个 http 链接上
vim /usr/local/apache2.4.46/conf/httpd.conf #添加以下内容
改: 222 ErrorDocument 404 /404.html
为: ErrorDocument 404 https://www.baidu.com
- 总结:ErrorDocument 的命令格式如下:
ErrorDocument 错误代码 跳转到的页面或文件
另外这里需要注意,你若设置跳转到文件,必须要有这个文件才行。另外文件必须在站点目录内,不然会报错。
在跳转到文件的测试中,使用别名路径进行测试,当把 404 错误页面跳转文件放到其他目录的时候,不报错,但是页面跳转不过去。所以要使用全路径。 - 设置跳回主页
-
启用压缩模块 mod_deflate Deflate [dɪˈfleɪt] 压缩,紧缩
-
网站随着用户访问量的增加和内容量的增加,网站的带宽会不断的增加,随之就是网站成本的增加。 并且当内容量增大的时候,客户端如果带宽小,就会影响用户的体验。因此从这两方面考虑,网站的某些内容必须经过压缩之后再传给用户,然后在用户客户端进行解压,来实现双方共赢的效果。
-
Apache 的压缩要用到 mod_deflate 模块,该模块提供了 DEFLATE 输出过滤器,允许服务器在将输出内容发送到客户端以前进行压缩,以节约带宽。它的核心思想就是把文件先在服务器进行压缩,然后再进行传输,这样可以显著减少文件传输的大小。当传输完毕后,客户端游览器会重新对压缩过的内容进行解压缩。如果没特殊情况的话,所有的文本内容都应该能被 gzip 压缩,例如:html(php),js,css,xml,txt 等。
-
特殊情况就是像一些首页上有很多广告投放的 js 代码,由于需要每次加载进而进行来访信息统计,所以这些广告代码拥有者网站的 js 不会经过 gzip 压缩
- mod_deflate 模块检查及安装
检查:
/usr/local/apache2.4.46/bin/apachectl -M | grep deflate #如果没有弹出任何内容,说明没有安装。
- 安装了的话,就可以直接进行压缩配置了,如果没有安装,下面为安装方法
a)编译时安装方法
编译的时候跟上--enable-deflate 即可实现安装
b)DSO 方式安装。
扩展:DSO: Dynamic shared object 动态共享对象 。DSO 模块可以在编译服务器之后编译,也可以用 Apache 扩展工具(apxs)编译并增加
使用 DSO 方式安装,/usr/local/apache2.4-xuegod/bin/apxs 后跟的参数详解
-c 此选项表明需要执行编译操作。
-i 此选项表示需要执行安装操作,以安装一个或多个动态共享对象到服务器的 modules 目录。
-a 此选项自动增加一个 LoadModule 行到 httpd.conf 文件中,以激活此模块,或者,如果此行 已经存在,则启用之。 - /opt/httpd-2.4.48/modules/filters/ #apache源码包 mod_deflate 所在的目录
- /usr/local/apache2.4.46/bin/apxs -c -i -a /opt/httpd-2.4.48/modules/filters/mod_deflate.c #以 dso 的方式编译安装到apache 中
- ll /usr/local/apache2.4-xuegod/modules/mod_deflate.so #成功安装这里会显示出该文件 mod_deflate.so
- 查看是否安装了模块:
/usr/local/apache2.4.46/bin/apachectl -M |grep deflate
报错:
httpd: Syntax error on line 106 of /usr/local/apache2.4.46/conf/httpd.conf: Cannot load modules/mod_deflate.so into server: /usr/local/apache2.4.46/modules/mod_deflate.so: undefined symbol: inflate
解决方法:
vim /usr/local/apache2.4.46/conf/httpd.conf
LoadModule deflate_module modules/mod_deflate.so 上面一行,插入以下
内容:
LoadFile /usr/lib64/libz.so
- 压缩模块配置
vim /usr/local/apache2.4.46/conf/httpd.conf #在以下内容后,插入:
</IfModule> 之后添加以下内容: - <Ifmodule mod_deflate.c>
DeflateCompressionLevel 9
SetOutputFilter DEFLATE
DeflateFilterNote Input instream
DeflateFilterNote Output outstream
DeflateFilterNote Ratio ratio
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript
</Ifmodule>
- 注释:
<ifmodule mod_deflate.c>
DeflateCompressionLevel 9 #压缩等级,越大效率越高,消耗 CPU 也越高。
DeflateCompressionLevel 9 是指压缩程度的等级,从 1 到 9,9 是最高等级。据了解,这样做最高可以减少 8 成大小的传输量(看档案内容而定),最少也能够节省一半。
DeflateCompressionLevel 预设可以采用 6 这个数值,以维持耗用处理器效能与网页压缩质量的平衡。
注:一般压缩等级使用 6 或 8
SetOutputFilter DEFLATE #启用压缩
DeflateFilterNote Input instream #声明输入流的 byte 数量
DeflateFilterNote Output outstream #声明输出流的 byte 数量
DeflateFilterNote Ratio ratio #声明压缩的百分比
#LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate #声明日志类型
#CustomLog logs/deflate_log.log deflate #声明日志类型
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript #仅压缩,限制特定的 MIME 类型文件
</ifmodule>
注:
1、如果是虚拟主机,需要在<VirtualHost*:80></VirtualHost>中添加配置即可实现压缩
2、图片和视频本身就是压缩格式,一般不需要压缩的。有些小图片和视频压缩后还会变大。 - 创建测试文件:
- cp /etc/passwd /usr/local/apache2.4.46/htdocs/passwd.html
- 下面访问网站,然后用火狐、google 或 360 游览器的 YSLOW 插件,查看压缩效果。
这里以 360 浏览器为例,进行安装 YSLOW 插件
- passwd.html 文件大小为 2.8 k
- 这里可以看到已经压缩到了 0.4 k
- 总结:我们在企业生产环境中时,在启用 mod_deflate 时,一定要注意,对于太小的文件和某些格式的图片不要对它们进行压缩,有可能越压越大。
- 扩展:AddOutputFilterByTypeDEFLATE 后跟的所有的压缩文件类型,后期可以参照选择。
text/plain text/html text/php text/xml text/css text/javascript
application/xhtml+xml application/xml application/rss+xml application/atom_xml
application/x-javascript application/x-httpd-php image/svg+xml image/gif image/png image/jpe image/swf image/jpeg image/bmp
- mod_expires: 设置网页缓存时间 expire [ɪkˈspaɪə(r)] 到期
- 虽然我们上面通过 mod_deflate 模块启用了压缩,从很大程度上节约了企业带宽,降低了企业成本。可是由于现在越来越多的图片、脚本、css 和 flash 被嵌入到页面中,当客户访问站点势必会做很多次的 http 请求,因此我们还可以通过 mod_expires 缓存模块来设置 xpiresHeader 来缓存这些文件。
- Expires 是通过 header 报文来指定特定类型的文件在游览器中的缓存时间的。平时,我们大多数的图片,flash 在发布之后都是不需要经常修改的,因此做了缓存之后,游览器第一次从服务器下载之后,就不需要再从服务器下载这些文件而是直接从游览器缓存中读取了。这样客户访问页面的速度就会大大加快,企业的带宽压力也得到了缓解。
- 检查 mod_expires 模块是否安装的方法如下:
/usr/local/apache2.4-xuegod/bin/apachectl -M | grep expires - 如果没有安装,参照上面 dso 的方式编译安装
-
配置缓存参数
- 对全局的配置就是在 apache 主配置文件 httpd.conf 的中加入如下参数即可
- <IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 12 month"
ExpiresByType text/html "access plus 12 months"
ExpiresByType text/css "access plus 12 months"
ExpiresByType image/gif "access plus 12 months"
ExpiresByType image/jpeg "access plus 12 months"
ExpiresByType image/jpg "access plus 12 months"
ExpiresByType image/png "access plus 12 months"
EXpiresByType application/x-shockwave-flash "access plus 12 months"
EXpiresByType application/x-javascript "access plus 12 months"
ExpiresByType video/x-flv "access plus 12 months"
</IfModule>
- 对目录的配置就是在 apache 主配置文件中<Directory></Directory>标签内,最后加入如下参数即可
-
<Directory "/usr/local/apache2.4.46/htdocs">
ErrorDocument 404 /index.html<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 12 month"
ExpiresByType text/html "access plus 12 months"
ExpiresByType text/css "access plus 12 months"
ExpiresByType image/gif "access plus 12 months"
ExpiresByType image/jpeg "access plus 12 months"
ExpiresByType image/jpg "access plus 12 months"
ExpiresByType image/png "access plus 12 months"
EXpiresByType application/x-shockwave-flash "access plus 12 months"
EXpiresByType application/x-javascript "access plus 12 months"
ExpiresByType video/x-flv "access plus 12 months"
</IfModule> -
</Directory>
-
对虚拟主机的配置就是在 Apache 的虚拟主机配置文件 httpd-vhosts.conf 中添加如下参数即可
- vim /usr/local/apache2.4.46/conf/extra/httpd-vhosts.conf
-
<VirtualHost *:88>
ServerName fdipzone.demo.com
DocumentRoot "/www/html"
DirectoryIndex index.html index.php<Directory "/www/html">
Options -Indexes +FollowSymlinks
AllowOverride All
Require all granted
</Directory>CustomLog "|/usr/sbin/cronolog /www/logs/www_access_%Y%m%d.log" combined
ErrorLog "|/usr/sbin/cronolog /www/logs/www_error_%Y%m%d.log"<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 12 month"
ExpiresByType text/html "access plus 12 months"
ExpiresByType text/css "access plus 12 months"
ExpiresByType image/gif "access plus 12 months"
ExpiresByType image/jpeg "access plus 12 months"
ExpiresByType image/jpg "access plus 12 months"
ExpiresByType image/png "access plus 12 months"
EXpiresByType application/x-shockwave-flash "access plus 12 months"
EXpiresByType application/x-javascript "access plus 12 months"
ExpiresByType video/x-flv "access plus 12 months"
</IfModule></VirtualHost>
- 测试:
cd /usr/local/apache2.4-xuegod/htdocs
rz -E #上传一张图片 beyond.jpg 到 Apache 的网站目录下
- http://192.168.2.40/beyond.jpg
- 通过时间对比,发现缓存 1 年左右。
- 扩展:expires 模块的语法
expires 模块用到了 ExpiresDefault 和 EXpiresByType 两个指令,下面是这两个指令的语法。
ExpiresDefault “<base> [plus] {<num><type>}*”
EXpiresByType type/encoding "<base> [plus] {<num><type>}"
其中<base>的参数有 3 个:access,now(等价于‘access’),modification
modification [ˌmɒdɪfɪˈkeɪʃn] 改性,修正
plus 关键字是可选的。
plus [plʌs] 加上
<num>必须是整数,确保可以 atoi()所接收。(atoi 可以把字符串转换成长整型数)
<type>参数类型:years,months,weeks,days,hours,minutes,seconds - 例如:下面 3 个指令都表示文档默认的有效期是一个月
ExpiresDefault "access plus 1 month"
ExpiresDefault "access plus 4 weeks"
ExpiresDefault "access plus 30 days"
有效期可以通过增加“<num><type>”子句进一步调整
ExpiresByType text/html "access plus 1 month 15 days 2 hours"
ExpiresByType image/gif "modification plus 5 hours 3 minutes" - 注意:如果你使用基于最后修改日期的设置,“Expires”头将不会被添加到那些并非来自于硬盘文件的内容,这是因为这些内容并不存在“最后修改时间”的属性。
基准时刻可以是源文件的最后修改时刻或者客户端对源文件的访问时刻,至于使用那一个则由<code>指定。“M”表示源文件的最后修改时刻,“A”表示客户端对源文件的访问时刻,需要注意的是<code>和 seconds 之间没有空格。 - 这两个基准的差别是很微妙的。如果使用“M”,所有当前缓存中的文档副本都将在同一时刻过期,这个可能对定期更新的 URL(比如位于同一位置的每周通告)很有好处。如果使用“A”,则每个客户端所得到的有效期是不一样的,这个可能对那些几乎不更新的图片很有好处,特别是对于一组都引用相同图片的相关文档。
- 缓存优化对企业来说是至关重要了的,不同的业务类型,对于缓存的类型和时间又各不相同,大家可以用 YSlow 对淘宝,京东,新浪,谷歌等站点进行测试,看看他们的缓存时间是多少,并思考下为什么那样设置。
- 注:天猫解决被缓存文件及时更新的方法:对缓存的对象改名
虽然缓存的设置有如下优点
1.缩短服务的响应时间
2.减轻服务器负担
3.减少网络带宽使用量,降低企业成本
但是他的缺点也是显而易见的,由于使用了缓存设置,导致被缓存的内容更新了,但是客户看到的却还是旧的。
如何解决被缓存文件及时更新这个问题呢?
第一种:缩短缓存时间例如:1 天,不彻底牺牲性能
第二种:对缓存的对象改名。
- 开启长连接功能
Apache 的 keepalive 和 keepalivetimeout
打开长链接:
KeepAlive Off/On 保持连接,会减少三次握手,但是会消耗内存,是否打开,取决于单位时间内是否进行多次连接(三次握手),一个连接有多次请求的,建议打开,并适当调整 KeepAliveTimeout 时间在 APACHE 的 httpd.conf 中,KeepAlive 指的是保持连接活跃,如果将 KeepAlive 设置为 On,那么来自同一客户端的请求就不需要再一次连接,避免每次请求都要新建一个连接而加重服务器的负担。 - KeepAlive 的连接活跃时间当然是受 KeepAliveTimeOut 限制的。如果第二次请求和第一次请求之间超过 KeepAliveTimeOut 的时间的话,第一次连接就会中断,再新建第二个连接。
- 所以,一般情况下,图片较多的网站应该把 KeepAlive 设为 On。但是 KeepAliveTimeOut 应该设置为多少秒就是一个值得讨论的问题了。
- 如果 KeepAliveTimeOut 设置的时间过短,例如设置为 1 秒,那么 APACHE 就会频繁的建立新连接,当然会耗费不少的资源;反过来,如果 KeepAliveTimeOut 设置的时间过长,例如设置为 300秒,那么 APACHE 中肯定有很多无用的连接会占用服务器的资源,也不是一件好事。
- 所以,到底要把 KeepAliveTimeOut 设置为多少,要看网站的流量、服务器的配置而定。
- vim /usr/local/apache2.4.46/conf/extra/httpd-default.conf
修改:
改: KeepAlive Off
为: KeepAlive On #如果已经为 On,开启长链接功能。那么就不需要再开启了
改: KeepAliveTimeout 5
为: KeepAliveTimeout 30
注:考虑到我的网站上有不少的图片,所以将 KeepAlive 设为 On,一般的页面两次请求间隔不会超过 30 秒,所以这样设置,至尽运行状况良好。如果是艺术品网站, 需要看的时间长,那么就设置长一些。 - MaxKeepAliveRequests 100 默认:100
一个建立好的 Keep-Alive 连接,允许发送的请求的个数。一旦建立连接,要么就是个数达到了断开,要么就是等 KeepAliveTimeout 时间到了断开连接。
MaxKeepAliveRequests 指令限制了当启用 KeepAlive 时,每个连接允许的请求数量。如果将此值设为"0",将不限制请求的数目。我们建议最好将此值设为一个比较大的值,以确保最优的服务器性能。"
这个数字的设置,必须考虑在一个时间段内,同一个用户访问你的服务会发多少请求。要结合KeepAliveTimeout 参数来考虑。 - 举个例子,用户需要间隔时间不大于 KeepAliveTimeout 的时间内,连续请求 10 个文件,那么这个参数就应该设置成 10,如果用户在连续时间里不断请求访问,则这个数值得设置得更多。否则就重新建立连接下载。一旦用户连续进行了 10 个请求后,并且这个用户肯定在完成这些请求后的 5 秒内不会再请求,甚至要在之后的很长时间后请求,那么这个 KeepAliveTimeout 时间就可以设置得很短,以便尽
早断开这种用户,把资源让个其他用户。 - 10 Timeout 60
"TimeOut 指令用于设置 Apache 等待以下三种事件的时间长度:
1. 接受一个 GET 请求耗费的总时间。
2. POST 或 PUT 请求时,接受两个 TCP 包之间的时间。3. 应答时 TCP 包传输中两个 ACK 包之间的时间。
比如:apache 需要把 jsp 文件传给后端 tomcat 服务器,而 tomcat 服务器关了,这时这个链接需要等待的超时时间,由 TimeOut 控制。但对于绝大多数情况来说仍是足够的。
- 案例分析
假设 KeepAlive 的超时时间为 10 秒钟,服务器每秒处理 50 个独立用户访问,那么系统中Apache 的总进程数就是 10 * 50 = 500 个,如果一个进程占用 4M 内存,那么总共会消耗 2G 内存,所以可以看出,在这种配置中,相当消耗内存,但好处是系统只处理了 50 次 TCP 的握手和关闭操作。 - 如果关闭 KeepAlive,如果还是每秒 50 个用户访问,如果用户每秒的并发请求数为 3 个,那么Apache 的总进程数就是 50 * 3 = 150 个,如果还是每个进程占用 4M 内存,那么总的内存消耗为600M,这种配置能节省大量内存,但是,系统处理了 150 次 TCP 的握手和关闭的操作,因此又会多消耗一些 CPU 资源。
- 注:
- 1、如果内存和 CPU 都足够,开启和关闭 KeepAlive 对性能影响不大。
- 2、如果考虑服务器压力,如果同一个客户端对服务器会经常访问,建议开启 KeepAlive。
- /usr/local/apache2.4.46/conf/extra/httpd-default.conf
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 30
UseCanonicalName Off
AccessFileName .htaccess
ServerTokens Prod
ServerSignature Off
HostnameLookups Off
<IfModule reqtimeout_module>
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>
- Apache 工作模式介绍
Web 服务器 Apache 目前一共有三种稳定的 MPM(Multi-Processing Module,多进程处理模块)模式。如:Prefork(进程模式)、worker(线程模式)、Event (事件模式,2.4 版本后开始稳定)。
- Apache 工作模式详解
Prefork MPM : Prefork MPM 实现了一个非线程的、预派生的 web 服务器。它在 Apache 启动之初,就先预派生一些子进程,然后等待连接;可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,只能处理一个请求。这是一个成熟稳定,可以兼容新老模块,也不需要担心线程安全问题,但是一个进程相对占用资源,消耗大量内存,不擅长处理高并发的场景。
最重要的是将 MaxClients 设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。所以现在已经不常用这个模式了。
- Apache2.4 版本以后,默认使用的是 worker 模式。
注: Prefork 是基于多进程的模式。
优点:因为每个进程使用独立的内存空间,所以比较安全。一个进程坏了,不会影响其他进程。
缺点:占用的内存比较大。
运行原理图如下:
- Worker MPM : 和 prefork 模式相比,worker 使用了多进程和多线程的混合模式,worker 模式也同样会先预派生一些子进程,然后每个子进程创建一些线程,同时包括一个监听线程,每个请求过来会被分配到一个线程来服务。
- 线程比起进程会更轻量,因为线程是通过共享父进程的内存空间,因此,内存的占用会减少一些,在高并发的场景下会比 prefork 有更多可用的线程,表现会更优秀一些;另外,如果一个线程出现了问题也会导致同一进程下的线程出现问题,如果是多个线程出现问题,也只是影响 Apache 的一部分,而不是全部。由于用到多进程多线程,需要考虑到线程的安全了,在使用 keepalive 长连接的时候,某个线程会一直被占用,即使中间没有请求,需要等待到超时才会被释放(该问题在 prefork 模式下也存在)。
运行原理图如下:
- 注: Worker MPM 优点:可以处理海量请求,而系统资源的开销小。原因:一个进程中包括多个线程。多个线程之间可以共享内存,所以占用的内存资源比较少。
- 缺点:不太安全。如果一个线程坏了。 整个进程都要坏了。另外存在 keep-alive 长连接占用资源时间过长。
如何避免进程中某个线程坏了? 一个进程中所有线程完成一定数量的请求后,自动关闭,再重打开。就可以避免内存溢出等问题。 就像一个电脑开机时间长了,会卡,需要重启一下。
总结: 不管是 Worker 模式或是 Prefork 模式,Apache 总是试图保持一些备用的(spare)或者是空闲的子进程(空闲的服务线程池)用于迎接即将到来的请求。这样客户端就不需要在得到服务前等候子进程的产生。这就是预先派生进程或线程。
- Event MPM:event 模式是在 2.4 版本中才可以稳定运行。
- 这是 Apache 最新的工作模式,它和 worker 模式很像,不同的是在于它解决了 keep-alive 长连接的时候占用线程资源被浪费的问题,在event 工作模式中,会有一些专门的线程用来管理这些 keep-alive 类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放。这增强了在高并发场景下的请求处理。当某个连接没有请求时,会主动关闭连接,在 work 模式下,必须等 keep-alive 超时,才可以释放
总结:在 configure 配置编译参数的时候,可以使用 --with-mpm=prefork|worker|event 来指定编译为那一种 MPM。也可以编译为三种都支持:--enable-mpms-shared=all,这样在编译的时候会在 modules 目录下自动编译出三个 MPM 文件的 so,然后通过修改 httpd.conf 配置文件更改MPM
- 查看 Apache 运行模式两种方法。
- #/usr/local/apache2.4.46/bin/apachectl -l 或者 /usr/local/apache2.4.46/bin/httpd -l
Compiled in modules:
core.c
mod_so.c
http_core.c
worker.c - 使用 apachectl -l 来确定当前使用的 MPM,看到 worker.c 说明使用的是 worker MPM。咱们这里默认使用的是 worker 模式。
- prefork 模式已经被淘汰了,所以主要讲一下 worker 和 event 两个模式。
- 或者使用
- /usr/local/apache2.4.46/bin/httpd -V
Server version: GF/8.8.8-dev (Unix)
Server built: Jul 25 2021 09:27:14
Server's Module Magic Number: 20120211:105
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
- 扩展:查看使用 yum 安装的 httpd 默认使用的运行模式 prefork
-
对 worker、event 模式性能优化
Apache2.0 以后的版本在性能方面改进最明显的变化就在于使用 worker 模式。
优点:内存占用比 prefork 模式低,适合高并发高流量 HTTP 服务。
缺点:假如一个线程崩溃,整个进程就会连同其他任何线程一起“死掉”。由于线程共享内存空间,所以一个程序在运行时必须被系统识别为“每个线程都是安全的”。服务稳定性不如prefork 模式。后期根据每个进程处理的请求数,重启 worker 进程 - 主配置文件必须开启引用 httpd-mpm.conf
- grep -Ev "^$|^#" /usr/local/apache2.4.46/conf/extra/httpd-mpm.conf
<IfModule !mpm_netware_module>
PidFile "logs/httpd.pid"
</IfModule>
<IfModule mpm_prefork_module> #这是 prefork 模式的配置参数,虽然配置文件中有参数,但是不启作用,因为我们是以 worker 模式在运行 Apache
StartServers 5 #启动时进程数
MinSpareServers 5 #最小空闲线程数。
MaxSpareServers 10 #最大空闲线程数
MaxRequestWorkers 250 # 最大并发进程数。
MaxConnectionsPerChild 0 #最大连接数限制。
</IfModule>
<IfModule mpm_worker_module>
StartServers 3 #启动时进程数
MinSpareThreads 75 #最小空闲线程数。
MaxSpareThreads 250 #最大空闲线程数。
ThreadsPerChild 25 #每个进程可以启动的线程数量。
MaxRequestWorkers 400 #所有线程数量的最大值,通常表示了一个 web 服务可以同时处理的请求数。
MaxConnectionsPerChild 0 #最大连接数限制。
- 配置参数详细说明:
- <IFModule mpm_worker_module>
StartServers 3 #最初建立的子进程
MinSpareThreads 75 #基于整个服务器监视的最小空闲线程数,如果空闲的线程小于设定值,Apache 会自动建立线程,如果服务器负载大的话,可以考虑加大此参考值。
MaxSpareThreads 250 #基于整个服务器监视的最大空闲线程数,如果空闲的线程大于设定值,Apache 会自动 kill 掉多余的线程,如果服务器负载大的话,可以考虑加大此参考值。
ThreadsPerChild 25 #表示每个进程包含的线程数,如果是并发量比较大,可以考虑加大这个值。此参数在 worker 模式中,是影响最大的参数。
MaxRequestWorkers 400 #所有线程数量的最大值,通常表示了一个 web 服务的最大并发值。MaxRequestWorkers 必须是 ThreadsPerChild 的整数倍,否则 Apache 会提示调整到一个相近的值。MaxRequestWorkers=StartServers* ThreadsPerChild
MaxConnectionsPerChild 0 #每个子进程可以处理的最大请求数。达到该数目后,进程将死掉。如果设置为 0,表示没有限制。
如:MaxConnectionsPerChild 25000。当进程处理了 25000 个请求后,Apache 管理进程会去终止此进程继续处理新的请求,当此进程处理完所有的已建立的请求后,管理进程会杀掉此进程,重新生成一个新的进程。
- <IFModule mpm_worker_module>
</IfModule>
<IfModule mpm_event_module>
StartServers 3 #启动时进程数
MinSpareThreads 75 #最小空闲线程数。
MaxSpareThreads 250 #最大空闲线程数。
ThreadsPerChild 25 #每个进程可以启动的线程数量。
MaxRequestWorkers 400 #所有线程数量的最大值,通常表示了一个 web 服务可以同时处理的请求数。
MaxConnectionsPerChild 0 #最大连接数限制。
</IfModule>
- MinSpareServers 指令设置空闲子进程的最小数量。所谓空闲子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于 MinSpareServers ,那么 Apache 将以第一秒一个,第二秒两个,第三秒四个,按指数递增个数的速度产生新的子进程。如此按指数级增加创建的进程数,最多达到每秒 32个,直到满足 MinSpareServers 设置的值为止;这就是预派生(prefork)的由来;这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能
- MaxSpareServers 指令设置空闲子进程的最大数量。所谓空闲子进程是指没有正在处理请求的子进程。如果当前有超过 MaxSpareServers 数量的空闲子进程,那么父进程将杀死多余的子进程。
- 可以调整 MinSpareServers 和 MaxSpareServers 这两个参数,但是这两个参数的值不能设得太大,否则 Apache 进程太多,会导致内存占用太多。
注:在一台压力大(并发访问 2000)的服务器上,MaxSpareServers 这个值设置的是 200。保留最大并发数的 11 分之一。设置了这个值的好处是不会有太多的空闲的进程在消耗资源,关闭空闲 Apache进程的同时,会释放内存,进而减少系统资源消耗。 - MaxRequestWorkers : 最大同时处理请求的进程数量,也是最大的同时连接数,表示了 Apache的最大请求并发能力,超过该数目后的请求,将排队。
- MaxConnectionsPerChild : 进程生命周期内,处理的最大请求数目。达到该数目后,进程将死掉。如果设置为 0,表示没有限制。该参数的意义在于,避免了可能存在的内存泄露带来的系统问题。
将 MaxRequestsPerChild 设置成非零值有两个好处:
* 可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。
* 给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
如:MaxConnectionsPerChild 25000。当进程处理了 25000 个请求后,Apache 管理进程会去终止此进程继续处理新的请求,当此进程处理完所有的已建立的请求后,管理进程会杀掉此进程,重新生成一个新的进程
注:当 KeepAlive 为 On, 开启长链接时,发送的请求,在 MaxRequestsPerChild 里面只算一个,不管这个连接发送了多少个请求。
- <IfModule mpm_worker_module>
StartServers 8
ServerLimit 20000
ThreadLimit 128
MinSpareThreads 256
MaxSpareThreads 512
ThreadsPerChild 128
MaxRequestWorkers 4096
MaxConnectionsPerChild 25000
</IfModule>
-
Apache 基于 worker 模式的生产环境配置实例
- 查看每个进程使用的内存大小
连接数理论上是越大越好,但是得根据硬件,服务器的 CPU,内存,带宽等因素,来配置当前的Apache 连接数。
- 查看 httpd 占用内存的平均数: 使用 ps 查看 RSS 列,每个进程占用的内存容量。
- ps -aux|grep -E "^apache"|awk '{print $6}'
6724
6720
6784
6724
6724
6784
6728
6720 - 注:默认单位是 K,可以看到进程大概使用的是 6800K 内存,一共使用了 6800*8=54.40MB内存,这是初始的内存大小。
后期随着 Apache 进程处理的 web 请的增加,每个进程使用的内存数量还会增加的。 因为每个网站和业务不一样。所以每个 Apache 进程使用的内存大小也不一样。但是大家可以在自己的服务器上线 1 天后,使用此命令查看一下,每个进程使用的内存大小,这样可以准确算出每个进程使用的内存数量。
查看进程使用的内存的总大小: - ps -axu | grep -E "apache" | awk '{sum += $6;n++};END{print sum}'
- 大约 148 MB 内存
- 查看每个进程使用内存的平均:
- ps -axu | grep -E "apache" | awk '{sum += $6;n++};END{print sum/n}'
12402.7 - 注:这样就可以根据每个进程使用内存的大小,来算一下我们最多可以给多少内存。
- 扩展:在选择服务器时,如何确认 cpu 和内存搭配?
通用型服务器选择标准:cpu 核心和内存大小,一般比例为 1:4 ,如 8 核 cpu,32G 内存;16 核心 CPU,64G内存。
计算型服务器选择标准:cpu 核心和内存大小,一般比例为 1:2 ,如 8 核 cpu,16G 内存;16 核心 CPU,32G内存。
内存型服务器选择标准:cpu 核心和内存大小,一般比例为 1:8 ,如 8 核 cpu,64G 内存;16 核心 CPU,128G内存。 - 实战场景:一台服务器,16 核心 CPU,64G内存。 Apache 最大可以设置多少个 work 进程。
- 思路:先减去服务器系统本身所需要的资源,剩下的才能给 Apache 使用。具体分配内存场景,可以参考以下案例。
例 1:当一台服务器是 8G 内存时, 2G留给系统使用, 6G留给 Apache 使用。
例 2:当一台服务器是 16G 内存时,4G留给系统使用,12G留给 Apache 使用。
例 3:当一台服务器是 32G 内存时,8G留给系统使用,24G留给 Apache 使用。
例 4:当一台服务器是 64G 内存时,8G留给系统使用,56G留给 Apache 使用。
总结:系统最多使用 8G 内存,就足够了稳定运行了。 - 那么对于 64G 内存的服务器,Apache 可以使用 56G 内存,假如每个 work 进程稳定运行时,平均使用 56M 内存。最大 work 进程数为:56*1124/56=1124 个。
根据上述情况,修改后的 http-mpm.conf 的 worker 的配置后为: - conf/extra/httpd-mpm.conf
<IfModule mpm_worker_module>
StartServers 1124
MinSpareThreads 750
MaxSpareThreads 2500
ThreadsPerChild 250
MaxRequestWorkers 25000
MaxConnectionsPerChild 25000
</IfModule> - 动态观察 Apache 的最大连接数:
- watch -n 1 "pgrep httpd|wc -l"
-
生产环境配置实例
- 实战环境:一台服务器 cpu 是 8 核心,物理是内存 32G ,想达到 2000 并发的 apache,worker模式的配置参数如下:
<IfModule mpm_worker_module>
StartServers 16
MinSpareThreads 75
MaxSpareThreads 1250
ThreadsPerChild 125
MaxRequestWorkers 2000
MaxConnectionsPerChild 12500
</IfModule>
详解每个参数的配置合理性如下:
<IfModule mpm_worker_module>
StartServers 16 #启动时进程数。一般设同 cpu 核心数一样或是 cpu核心数的 2 倍。这里调成 16 和 cpu 核心一样。
MinSpareThreads 75 #最小空闲线程数。假设一个网站每天正常被用户使用的时间为早上 7:00 到晚上 2:00。那么 MinSpareThreads 应该配置为,这一时间段,最小并发访问量的 3 倍。比如 7:00 最少并发为 25,那就配置成 75。
MaxSpareThreads 1250 #最大空闲线程数。一般配置为 1 天中最大并发量的 1半。如这台服务器能处理的最大并量为 2500。那么此值应该为 1250。因为内存闲着也是闲着,可以按linux 下尽可能使用内存的原则,配置成 1250.这样在突然到来更多访问量时,响应会更及时。
ThreadsPerChild 125 #每个进程可以启动的线程数量。生成环境中,在带宽和硬盘性能充足的情况下,希望这个这台可以完成 2000 左右的并发。那么此值应该为:2000/StartServers 的值(这里是 16)=125 。但是一个进程不可能包括无数的线程,包括太多,会导致进程不稳定,容易崩溃。所以我们认为一个进程最多包括 125 线程,就很好了。所以如果还想处理更多的请求,可以把 StartServers 的值增加,而不是增大 ThreadsPerChild 的值。 因为 ThreadsPerChild值过大,会导致 Apache 运行不稳定。
系统调优,稳定是一切的前提。
MaxRequestWorkers 2000 #所有线程数量的最大值,通常表示了一个 web 服务的最大并发值。MaxRequestWorkers 必须是 ThreadsPerChild 的整数倍,否则 Apache 会提示调整到一个相近的值。MaxRequestWorkers=StartServers* ThreadsPerChild。 这里是:16*125=2000
MaxConnectionsPerChild 12500 # 最大连接数限制。每个子进程可以处理的最大请求数。如果设置为 0,表示没有限制。 我们设置为 MaxConnectionsPerChild 12500。当进程处理了 12500 个请求后,Apache 管理进程会去终止此进程继续处理新的请求,当此进程处理完所有的已建立的请求后,管理进程会杀掉此进程,重新生成一个新的进程。结合当前的配置,得出结论:
Apache 一个进程中有 125 个线程。 Apache 一个进程处理 12500 个请求。 平均一个线程处理12500/125=110 个请求。这样配置还是合理的。一个线程处理太多的请求,也会出现内存溢出,导致进程崩溃。
- event 模式调优
- event 模式调优和 worker 模式一样的,不同的是在于它解决了 keep-alive 长连接的时候占用线程资源被浪费的问题。所以理伦上 event 模式比 worker 模式好。
总结:生产环境下对于要求更高伸缩性的站点可以选择使用 worker 或 event 模式; 需要可靠性或者与旧软件兼容的站点可以使用 prefork 模式。现在网站使用 worker 模式比较多。worker 也比较成熟。event 模式从 Apache2.4 版本才开始有。
-
Apache 的 Rewrite 规则使用技巧
- Rewrite 规则简介
Rewirte 主要的功能就是实现 URL 的跳转,它的正则表达式是基于 Perl 语言。可基于服务器级的(httpd.conf)和目录级的 (.htaccess)两种方式。如果要想用到 rewrite 模块,必须先安装或加载rewrite 模块。 - 安装 Rewirte 模块两种方式:
方法一:是编译 Apache 的时候就直接 安装 rewrite 模块。
方法二:编译 Apache 时以 DSO 模式安装 Apache,然后再利用源码和 apxs 来安装 rewrite 模块。 - 基于服务器级的(httpd.conf)有两种方法:
方法 1:在 httpd.conf 的全局下 直接利用 RewriteEngine on 来打开 rewrite 功能;
方法 2:在局部里利用 RewriteEngine on 来打开 rewrite 功能,下面将会举例说明,需要注意的是,
必须在每个 virtualhost 里用 RewriteEngine on 来打开 rewrite 功能。否则 virtualhost 里没有RewriteEngine on 它里面的规则也不会生效。 - Apache mod_rewrite 规则重写的标志参数说明
1) R[=code](force redirect) 强制外部重定向。
强制在替代字符串加上 http://thishost[:thisport]/前缀重定向到外部的 URL.如果 code 不指定,将用缺省的 302 HTTP 状态码。
2) F(force URL to be forbidden)禁用 URL,返回 403HTTP 状态码。
3) G(force URL to be gone) 强制 URL 为 GONE,返回 411HTTP 状态码。
4) P(force proxy) 强制使用代理转发。
5) L(last rule) 表明当前规则是最后一条规则,停止分析以后规则的重写。
6) N(next round) 重新从第一条规则开始运行重写过程。
7) C(chained with next rule) 与下一条规则关联。如果规则匹配则正常处理,该标志无效,如果不匹配,那么下面所有关联的规则都跳过。
8) T=MIME-type(force MIME type) 强制 MIME 类型。
9) NS (used only if no internal sub-request) 只用于不是内部子请求。
11) NC(no case) 不区分大小写
11) QSA(query string append) 追加请求字符串。
12) NE(no URI escaping of output) 不在输出转义特殊字符。
例如:RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE] 将能正确的将/foo/zoo 转换成/bar?arg=P1=zed - 13) PT(pass through to next handler) 传递给下一个处理。
14) S=num(skip next rule(s)) 跳过 num 条规则。
11) E=VAR:VAL(set environment variable) 设置环境变量。 - mod_rewrite 模块检查及安装
- /usr/local/apache2.4.48/bin/apachectl -M|grep rewrite
rewrite_module (shared) - grep -E "mod_rewrite.so" /usr/local/apache2.4.48/conf/httpd.conf
LoadModule rewrite_module modules/mod_rewrite.so
- 扩展:如果之前安装 Apache 时,没有添加--enable-rewrite 选项,那需要使用下面的方法手动编译出来这个模块。 具体如下:
a)编译方式安装
编译的时候跟上--enable-rewrite 即可实现安装。
b)DSO 方式安装
以 dso 的方式编译安装到 Apache 中
/usr/local/apache2.4.48/bin/apxs -c -i -a /opt/httpd-2.4.48/modules/mappers/mod_rewrite.c
-
实现请求的主机前缀不是 www.gf-beyond.com 和 192.168.2.40 都跳转到主机前缀为
http://www.gf-beyond.com 。例如当用户在地址栏写入 http://gf-beyond.com 和 bbs.gf-beyond.com 直接跳转到 http://www.gf-beyond.com - vim /usr/local/apache2.4.48/conf/httpd.conf
- 在: LoadModule rewrite_module modules/mod_rewrite.so 之后插入以下内容。
- RewriteEngine on
RewriteCond %{HTTP_HOST} !^www.gf-beyond.com [NC]
RewriteCond %{HTTP_HOST} !^192.168.2.40 [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) http://www.gf-beyond.com/ [L] - 注释:
RewriteEngine on #打开 rewirte 功能。
RewriteCond %{HTTP_HOST} !^www.gf-beyond.com [NC] #声明 Client 请求的主机中前缀不是。www.gf-beyond.com ,[NC]的意思是忽略大小写。
RewriteCond %{HTTP_HOST} !^192.168.1.63 [NC] #声明 Client 请求的主机中前缀不是。192.168.2.40 ,[NC]的意思是忽略大小写。
RewriteCond %{HTTP_HOST} !^$ #声明 Client 请求的主机中前缀不为空,[NC]的意思是忽略大小写。
RewriteRule ^/(.*) http://www.gf-beyond.com/ [L]
#含义是如果 Client 请求的主机中的前缀符合上述条件,则直接进行跳转到 http://www.gf-beyond.com/,[L]意味着立即停 止重写操作,并不再应用其他重写规则。这里的.*是指匹配所有 URL 中不包含换行字符,()括号的功能是把所有的字符做一个标记,以便于后面的应用. 就是引用前面里的(.*)字符。 - 不重启服务加载配置
- /etc/init.d/apache graceful
- 创建一个测试 index.html 页
echo "www.gf-beyond.com" > /usr/local/apache2.4.48/htdocs/index.html - 编辑 windows hosts 文件
- 打开浏览器访问 http://www.gf-beyond.com 和 http://192.168.2.40 观察
- 访问正常没有跳转,测试 http://gf-beyond.com http://bbs.gf-beyond.com
- The document has moved <a href="http://www.gf-beyond.com/
- 将 www.360buy.com 域名时跳转到 www.jd.com
- vim /usr/local/apache2.4.48/conf/httpd.conf
- 在原来位置插入以下内容:
RewriteCond %{HTTP_HOST} ^www.360buy.com [NC]
RewriteRule ^/(.*) http://www.jd.com/ [L]
- /etc/init.d/apache graceful
- Apache 进行防盗链的配置
实战场景:一些小网站为了盈利,通过盗链来实现对自己网站内容的丰富,这无疑加大了企业的空间和流量的成本,因此我们需要对 Apache 进行防盗链的配置。
防盗链配置如下: - vim /usr/local/apache2.4.48/conf/httpd.conf
删除:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.360buy.com [NC]
RewriteRule ^/(.*) http://www.jd.com/ [L]
在原位置插入以下内容:
<IfModule rewrite_module>
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://gf-beyond.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://gf-beyond.com$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.gf-beyond.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.gf-beyond.com [NC]
RewriteRule .*\.(gif|jpg|swf)$ http://www.gf-beyond.com/1.jpg [R,NC]
</IfModule>
-
禁止浏览目录和 php 文件被解析
- 由于开启目录浏览会让整个目录下的内容全部都暴露到外面,因此必须要禁止目录浏览功能。当然一些目录开放给客户做下载的,可以忽略此项优化。
我们通过修改 Apache 主配置文件 httpd.conf 中的<Directory></Directory>标签内的Options 选项参数来实现禁用目录浏览 - cp -r /boot/grub2/ /usr/local/apache2.4.48/htdocs/
- chmod 755 /usr/local/apache2.4.48/htdocs/grub2/
chown -R apache. /usr/local/apache2.4.48/htdocs/
ll /usr/local/apache2.4.48/htdocs/
total 156
-rw-r--r-- 1 apache apache 154629 Jul 27 10:42 1.jpg
drwxr-xr-x 5 apache apache 132 Jul 27 10:56 grub2
-rw-r--r-- 1 apache apache 18 Jul 27 10:13 index.html - 测试:打开 链接 http://192.168.2.40/grub2/ ,发现当 grub2 目录下没有 index.html 文件时,会直接把目录中的文件表出来,这不是我们想要的。
- vim /usr/local/apache2.4.48/conf/httpd.conf
- #Options Indexes FollowSymLinks 删除 Indexes
Options FollowSymLinks
- 注:你只需要将上面代码中的 Indexes 去掉,就可以禁止 Apache 显示该目录结构。用户就不会看到该目录下的文件和子目录列表了。Indexes 的作用就是当该目录下没有 index.html 文件时,就显示目录结构,去掉 Indexes,Apache 就不会显示该目录的列表了。另外在 Options Indexes FollowSymLinks 的 Indexes 前面加上-减号符号。 即: Options -Indexes FollowSymLinks 也可以实现。
- 在 Indexes 前,加 + 代表允许目录浏览;加 – 代表禁止目录浏览。
-
禁止网站中某个目录中的 php 文件被解析
- 实战场景:企业的站点有时会提供用户进行上传操作,比如让用户上传一个文件或头像图片,而用户上传文件的存放目录,不能给 php 的解析权限,否则会对 Apache 服务和系统造成危害。
设置不允运行/usr/local/apache2.4.48/htdocs/upload 目录下的 php 结尾的文件 - vim /usr/local/apache2.4.48/conf/httpd.conf
- 在:
<Directory "/usr/local/apache2.4.48/htdocs">
。。。
</Directory>
之后,添加以下内容: - <Directory "/usr/local/apache2.4.48/htdocs/upload" >
<Files ~ ".php">
Order allow,deny
Deny from all
</Files>
</Directory> - mkdir /usr/local/apache2.4.48/htdocs/upload
chown -R apache. /usr/local/apache2.4.48/htdocs/upload
ll -d /usr/local/apache2.4.48/htdocs/upload
drwxr-xr-x 2 apache apache 6 Jul 27 11:02 /usr/local/apache2.4.48/htdocs/upload - 写入 php 测试页面:
vim /usr/local/apache2.4.48/htdocs/upload/index.php
<?php
phpinfo();
?> - 访问 测试 http://www.gf-beyond.com/upload/index.php
- Apache 网站架构优化
好的网站架构是网站性能强大关键,更是网站安全的关键。
在生产环境中建议将程序页面服务器、图片附件服务器和上传服务器三者的功能尽量分离。
分离方法:
1、分离最佳方式是分别使用独立的服务器(需要程序支持)
2、次选方案在前端负载均衡器通过 haproxy/nginx 来根据用户请求的目录或扩展名来对后端的服务器发出请求。
例如:请求 http://www.xuegod.cn/a/b.jpg 就抛给图片服务器(CDN 最好),这里是根据扩展名.jpg 分发
请求 http:// /www.xuegod.cn /upload/login.php 就抛给 Apache 服务器,这里是根据 URL 路径分发。
均不符合上面两个要求的,默认就都是抛给主 web 服务器。
目录 返回
首页