apache 调优

Posted 笨小孩@GF 知行合一

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 的网站目录下

  •  通过时间对比,发现缓存 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> 
<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 里面只算一个,不管这个连接发送了多少个请求。