
企业级web架构LAMP详解
一、WEB服务器
WEB服务器也称为WWW服务器、HTTP服务器,其主要功能是提供网上信息浏览服务。Unix和Linux平台下常用的服务器有Apache、Nginx、Lighttpd、Tomcat、IBM WebSphere等,其中应用最广泛的是Apache。而Windows平台下最常用的服务器是微软公司的IIS。
1.1 常见的WEB应用服务器
IIS
IIS是Internet Information Server(信息服务)的缩写,也是微软主推的web服务器产品,适用于windows系统,很多著名网站都采用IIS搭建,ASP、.net开发的程序一般也只能在IIS上运行。
IIS提供了一个图形界面的管理工具,称为 Internet服务管理器,可用于监视配置和控制Internet服务,其中包括Web服务器、FTP服务器、NNTP服务器和SMTP服务器,分别用于网页浏览、文件传输、新闻服务和邮件发送等方面,IIS的使用让网络(包括互联网和局域网)上的信息发布变得非常简单。同时,IIS还提供ISAPI(Intranet Server API)作为扩展Web服务器功能的编程接口,并提供一个Internet数据库连接器,可以实现对数据库的查询和更新。
Apache
Apache是目前世界上最流行的Web服务器之一,支持跨平台应用,可以运行在几乎所有的Unix、windows、linux系统平台上,尤其对linux的支持相当完美。
Apache是开源免费的,有很多开发者都参与了设计和改进,推动了产品的持续完善。Apache的特点是简单、高速、性能稳定,可作代理服务器使用。到目前为止,Apache仍然是世界上用的最多的Web服务器,其成功之处主要在于源码开放、强大的社区支持、跨平台应用以及可移植性等方面。不过,Apache是以进程为基础的结构,要比线程消耗更多的系统开支,不太适合于多处理器环境,还有就是并发不强,流量大了就容易出现500错误。
Nginx
Nginx是一种高性能的HTTP和反向代理web服务器,支持高并发和负载均衡,以稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。
Nginx可以在大多数Unix/Linux上编译运行,并有Windows移植版。Nginx的安装简单、配置文件简洁(支持perl语法),同时Bug非常少,几乎可以做到7*24不间断运行,支持在不间断服务的情况下进行软件版本升级。在连接高并发的情况下,Nginx是Apache服务不错的替代品。同时Nginx的模块也非常丰富,能够满足不同的需求,适合做静态使用。另外Nginx还提供了IMAP/POP3/SMTP服务,是一个非常优秀的邮件代理服务器。
Tomcat
Tomcat是一个开放源代码、运行servlet和JSP Web应用软件、并基于Java的Web应用软件容器。由于技术先进、性能稳定,而且免费,深受Java 爱好者欢迎,同时,也得到了部分软件开发商认可,成为目前比较流行的Web应用服务器。
Tomcat 属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。和IIS等Web服务器一样,tomcat也有处理HTML页面的功能,另外它还是一个Servlet和JSP容器(默认模式下为独立的Servlet容器)。不过,Tomcat处理静态HTML的能力不如Apache服务器,目前Tomcat最新版本为9.0。
其他
Kangle是一款跨平台、功能强大、易操作的高性能web服务器和反向代理服务器,也是一款专为做虚拟主机研发的web服务器,实现虚拟主机独立进程、独立身份运行与用户安全隔离,支持php、asp、java、ruby等多种动态开发语言。
WebSphere是IBM 的软件平台,包含了编写、运行和监视全天候的工业强度的随需应变Web应用程序和跨平台、跨产品解决方案所需要的整个中间件基础设施,如服务器、服务和工具。WebSphere 是一个模块化的平台,基于业界支持的开放标准,并可在 Intel、Linux 等多平台运行。
WebLogic是Oracle出品的一款多功能、基于标准的web应用服务器,是一款基于JAVAEE架构的中间件,用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用,将Java的动态功能和安全标准引入大型网络应用的开发、集成、部署和管理之中,为企业构建自己的应用提供了坚实的基础。
1.2 WEB服务器的工作原理
这张图,将一次Web服务的工作流程过一遍,我们假设以浏览器作为客户端
(1) 用户做出了一个操作,可以是填写网址敲回车,可以是点击链接,可以是点击按键等,接着浏览器获取了该事件。
(2) 浏览器与对端服务程序建立TCP连接。
(3) 浏览器将用户的事件按照HTTP协议格式打包成一个数据包,其实质就是在待发送缓冲区中的一段有着HTTP协议格式的字节流。
(4) 浏览器确认对端可写,并将该数据包推入Internet,该包经过网络最终递交到对端服务程序。
(5) 服务端程序拿到该数据包后,同样以HTTP协议格式解包,然后解析客户端的意图。
(6) 得知客户端意图后,进行分类处理,或是提供某种文件、或是处理数据。
(7) 将结果装入缓冲区,或是HTML文件、或是一张图片等。
(8) 按照HTTP协议格式将(7)中的数据打包
(9) 服务器确认对端可写,并将该数据包推入Internet,该包经过网络最终递交到客户端。
(10) 浏览器拿到包后,以HTTP协议格式解包,然后解析数据,假设是HTML文件。
(11) 浏览器将HTML文件展示在页面
以上为Web服务器工作基本原理。其实不难发现,这仅仅只是一个简单的网络通信。我们应该深信,作为一个服务器,其根本的工作无非有三个:接收数据,处理数据,发送数据。
二、LAMP架构
2.1 LAMP架构简述
如今,我们每次谈及web网站的架构,都会离不开一个话题就是LAMP架构和LNMP的架构,它使我们搭建网站的基础,我们可以通过各种途径和方式轻松的获取它的各类的资料和文档,使因为他们现在目前正在被广泛的应用,对于它的安装和使用,优化等也非常多的心得和体验,那LAMP架构到底使什么呢?接下来我们就一起来了解一下。
首先解释一下LAMP架构的组成部分是什么?LNMP架构我们后面再继续聊。
LAMP架构是4个基础组件的首字母组合而成的,其中:
L: Linux
A:APACHE
M: Mysql
P: PHP
2.2 各组件作用
平台:Linux
作为LAMP架构的基础,提供用于支撑Web站点的操作系统,能够与其他三个组件提供更好的稳定性,兼容性(AMP组件也支持Windows,UNIX等平台)
前台:Apache(静态页面)
作为LAMP架构的前端,是一款功能强大哦,稳定性好的Web服务器程序,该服务器直接面向用户提供网站访问,发送网页,图片等文件内容。
后台:MySQL(数据库--数据存储/读取)
作为LAMP架构的后端,是一款流行的开源关系数据库系统。在企业网站,业务系统等应用中,各种账户信息,产品信息,客户资料,业务数据库等都可以存储到MySQL数据库,其他程序可以通过SQL语句来查询,更改这些信息。
中间连接:PHP/Perl/Python(动态页面)
作为三种开发动态网页的编程语言,负责解释动态网页文件,负责沟通Web服务器和数据库系统以协同工作,并提供Web应用程序的开发和运行环境。其中PHP是一种被广泛应用的开放源代码的多用途脚本语言,它可以嵌入到HTML中,尤其适合于Web应用开发。
三、LAMP架构部署
3.1 安装APACHE
3.1.1 安装准备的软件包
httpd-2.4.28.tar.gz #Apache主程序包
apr-1.5.2.tar.gz #Apache依赖包
apr-util-1.5.4.tar.gz #Apache依赖包
pcre-8.41.tar.gz #Apache依赖包
下载地址:
https://dlcdn.apache.org//httpd/httpd-2.4.51.tar.gz
http://archive.apache.org/dist/apr/apr-1.6.2.tar.gz
http://archive.apache.org/dist/apr/apr-util-1.6.0.tar.gz
https://sourceforge.net/projects/pcre/files/pcre/8.41/pcre-8.41.tar.gz
3.1.2 安装依赖
[root@lamp ~]# yum -y install make gcc gcc-c++ openssl openssl-devel expat-devel
3.1.3 编译安装依赖包apr
[root@lamp ~]# tar zxvf apr-1.6.2.tar.gz
[root@lamp ~]# cd apr-1.6.2
[root@lamp apr-1.6.2]# ./configure --prefix=/usr/local/apr
[root@lamp apr-1.6.2]# make && make install
教你一招:如果想加快编译安装的速度,可以在编译的时候加一个-j选项,如果是4个核心就是-j 4,其他类比即可
3.1.4 编译安装依赖包apr-util
[root@lamp ~]# tar zxvf apr-util-1.6.0.tar.gz
[root@lamp ~]# cd apr-util-1.6.0
[root@lamp apr-util-1.6.0]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr/bin/apr-1-config
[root@lamp apr-util-1.6.0]# make -j 8 && make -j 8 install
3.1.5 编译安装依赖包pcre
[root@lamp ~]# tar zxvf pcre-8.41.tar.gz
[root@lamp ~]# cd pcre-8.41/
[root@lamp pcre-8.41]# ./configure --prefix=/usr/local/pcre
[root@lamp pcre-8.41]# make -j 8 && make -j 8 install
提问:怎么确保编译安装的结果是正确的呢?
3.1.6 编译安装Apache
[root@lamp ~]# tar zxvf httpd-2.4.51.tar.gz -C /usr/local/src/
[root@lamp ~]# cd /usr/local/src/httpd-2.4.51
[root@lamp httpd-2.4.51]# ./configure --prefix=/usr/local/apache --enable-so --enable-rewrite --enable-ssl --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util/ --with-pcre=/usr/local/pcre/
[root@lamp httpd-2.4.51]# make -j 8 && make -j 8 install
注:
--enable-so #支持动态加载模块
--enable-rewrite #支持网站地址重写
--enable-ssl #支持ssl加密
--with-apr=/usr/local/apr #关联apr
--with-apr-util=/usr/local/apr-util #关联apr-util
--with-pcre=/usr/local/pcre #关联pcre
--libdir=/usr/lib64 #关联库文件
3.1.7 查看配置文件
[root@lamp ~]# ls /usr/local/apache/conf/httpd.conf #网站的配置文件
/usr/local/apache/conf/httpd.conf
[root@lamp ~]# ls /usr/local/apache/htdocs/ #网站的根目录文件
index.html
3.1.8 生成启动脚本
[root@lamp ~]# cp /usr/local/apache/bin/apachectl /etc/init.d/
[root@lamp ~]# chmod +x /etc/init.d/apachectl
写个apache系统服务脚本, 以754的权限保存此文件
vim /usr/lib/systemd/system/apache.service
[Unit]
Description=apache
After=network.target
[Service]
Type=forking
ExecStart=/etc/init.d/apachectl start
ExecReload=/etc/init.d/apachectl restart
ExecStop=/etc/init.d/apachectl stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target
3.1.9 启动服务
[root@lamp ~]# systemctl start apache
[root@lamp ~]# systemctl enable apache
或者
[root@lamp ~]# /etc/init.d/apachectl start
3.1.10 测试访问
http://<IP>
3.2 mysql安装
3.2.1下载Mysql源码包
下载地址:
http://cdn.mysql.com/Downloads/MySQL-5.7/mysql-5.7.19.tar.gz
http://liquidtelecom.dl.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz
MySQL从5.7版本之后,boost是必须的,建议把系统自带的boost库卸载,源码编译安装高版本
[root@lamp ~]# yum -y remove boost-*
卸载系统自带的mysql
[root@lamp ~]# yum -y remove mysql
3.2.2 安装依赖
[root@lamp ~]# yum install -y cmake make gcc gcc-c++ bison ncurses ncurses-devel
3.2.3 添加mysql用户和组
[root@lamp ~]# groupadd mysql
[root@lamp ~]# useradd -M -s /sbin/nologin -r -g mysql mysql
3.2.4 创建安装目录和数据存放目录
添加一块新的硬盘,创建分区sdb1并分配所有的空间
[root@lamp ~]# mkdir -p /var/lib/mysql/
[root@lamp ~]# mkdir -p /var/lib/mysql/data
[root@lamp ~]# mount /dev/sdb1 /var/lib/mysql
[root@lamp ~]# echo "/dev/sdb1 /var/lib/mysql ext4 defaults 0 0" >> /etc/fstab
注:mysql-5.7.11.tar.gz安装时占用空间比较大,虚拟机环境下建议新添加一块硬盘进行安装,真实服务器中可不需要
3.2.5 解压mysql包
[root@lamp ~]# tar zxvf mysql-5.7.19.tar.gz -C /usr/local/src/
[root@lamp ~]# cd /usr/local/src/mysql-5.7.19
[root@lamp ~]# mkdir -p /usr/local/src/mysql-5.7.19/boost
[root@lamp ~]# tar zxvf boost_1_59_0.tar.gz -C /usr/local/src/mysql-5.7.19/boost
[root@lamp mysql-5.7.19]# cmake -DCMAKE_INSTALL_PREFIX=/var/lib/mysql \
-DMYSQL_DATADIR=/var/lib/mysql/data \
-DSYSCONFDIR=/etc \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DMYSQL_UNIX_ADDR=/var/lib/mysql/mysql.sock \
-DMYSQL_TCP_PORT=3306 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DDOWNLOAD_BOOST=1 \
-DWITH_BOOST=/usr/local/src/mysql-5.7.19/boost/boost_1_59_0
编译参数详解:
DCMAKE_INSTALL_PREFIX:指定MySQL程序的安装目录,默认/usr/local/mysql
DEFAULT_CHARSET:指定服务器默认字符集,默认latin1
DEFAULT_COLLATION:指定服务器默认的校对规则,默认latin1_general_ci
ENABLED_LOCAL_INFILE:指定是否允许本地执行LOAD DATA INFILE,默认OFF
WITH_COMMENT:指定编译备注信息
WITH_xxx_STORAGE_ENGINE:指定静态编译到mysql的存储引擎,MyISAM,MERGE,MEMBER以及CSV四种引擎默认即被编译至服务器,不需要特别指定。
WITHOUT_xxx_STORAGE_ENGINE:指定不编译的存储引擎
SYSCONFDIR:初始化参数文件目录
MYSQL_DATADIR:数据文件目录
MYSQL_TCP_PORT:服务端口号,默认3306
MYSQL_UNIX_ADDR:socket文件路径,默认/tmp/mysql.sock
3.2.6 编译
[root@lamp mysql-boost-5.7.19]# make -j 8
注意:编译过程中可能存在的问题,报错如下,提示内存不足,建议至少给3-4GB
c++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
make[2]: [libmysqld/CMakeFiles/sql_embedded.dir/__/sql/item_geofunc.cc.o] Error 4
make[2]: Waiting for unfinished jobs....
[ 71%] Building CXX object sql/CMakeFiles/sql.dir/item_geofunc_internal.cc.o
[ 71%] Building CXX object sql/CMakeFiles/sql.dir/item_geofunc_relchecks.cc.o
[ 71%] Building CXX object sql/CMakeFiles/sql.dir/item_geofunc_relchecks_bgwrap.cc.o
[ 71%] Building CXX object sql/CMakeFiles/sql.dir/item_geofunc_setops.cc.o
c++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
make[2]: [sql/CMakeFiles/sql.dir/item_geofunc.cc.o] Error 4
make[2]: Waiting for unfinished jobs....
make[1]: [libmysqld/CMakeFiles/sql_embedded.dir/all] Error 2
make[1]: Waiting for unfinished jobs....
make[1]: [sql/CMakeFiles/sql.dir/all] Error 2
make: [all] Error 2
3.2.7 编译安装
[root@lamp mysql-5.7.19]# make -j 8 install
3.2.8 修改目录的权限
[root@lamp ~]# chown -R mysql:mysql /var/lib/mysql
# 存放PID
[root@lamp ~]# mkdir /var/run/mysqld
[root@lamp ~]# chown mysql:mysql /var/run/mysqld -R
3.2.9 生成配置文件
[root@lamp ~]# mv /etc/my.cnf /etc/my.cnf.bak
自行创建my.cnf配置文件
[root@lamp ~]# vim /etc/my.cnf
[mysqld]
basedir=/var/lib/mysql
datadir=/var/lib/mysql/data
port=3306
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
character-set-server=utf8
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[mysql]
socket=/var/lib/mysql/mysql.sock
[client]
socket=/var/lib/mysql/mysql.sock
#sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
3.2.10 添加path路径环境变量
#添加下面2行 在文件的结尾
vim /etc/profile
export MYSQL_HOME=/var/lib/mysql
export PATH=$PATH:$MYSQL_HOME/bin
#使修改生效
source /etc/profile
3.2.11 生成服务启动脚本
[root@lamp ~]# cp /var/lib/mysql/support-files/mysql.server /etc/init.d/mysqld
[root@lamp ~]# chmod +x /etc/init.d/mysqld
3.2.12 初始化数据库
1)然后先删除数据目录下的文件,并创建日志文件
[root@lamp ~]# rm -rf /var/lib/mysql/data/*
[root@lamp ~]# touch /var/log/mysqld.log
2)开始初始化数据库
[root@lamp ~]#/var/lib/mysql/bin/mysqld --initialize-insecure --user=mysql --basedir=/var/lib/mysql --datadir=/var/lib/mysql/data --port=3306
3.2.13 启动服务
[root@lamp ~]# /etc/init.d/mysqld start
注意:启动可能存在报错
[root@lamp ~]# /etc/init.d/mysqld start
Starting MySQL.. ERROR! The server quit without updating PID file (/var/run/mysqld/mysqld.pid).
这种情况请检查/var/run/mysqld是否存在,如果没有的话请创建
完成后,如还是无法启动,则将/var/lib/mysql/data的数据全部删除,再次初始化!!!
3.2.14 修改mysql密码
[root@lamp ~]# mysqladmin -u root password "123456"
或者
[root@lamp ~]# mysql
mysql> set password for 'root'@'hopu01'=password('123456');
3.2.14 修改mysql密码
[root@lamp ~]# mysqladmin -u root password "123456"
或者
[root@lamp ~]# mysql
mysql> set password for 'root'@'hopu01'=password('123456');
3.3.7 添加测试页
[root@lamp php-7.1.10]# cd /usr/local/apache/htdocs/
[root@lamp htdocs]# vim index.php
<?php
phpinfo();
?>
至此,LAMP架构就完全搭建好了。
3.4 扩展:yum方式安装LAMP架构
#安装
[root@client html]# yum -y install httpd mysql mysql-server php php-mysql #centos6
[root@client html]# yum –y install httpd mariadb mariadb-server php php-mysql #centos7
#测试apache是否支持php,创建一个文件
[root@client html]## vim index.php
<?php
phpinfo();
?>
#启动服务
[root@client html]# systemctl start httpd
[root@client html]# systemctl start mariadb
四、APACHE的优化
4.1 隐藏版本
隐藏版本的重要性在于黑客可以扫描出 Apache 版本信息,可以查看对应的版本信息的漏洞,然后攻击。
4.1.1 查看版本
[root@client ~]# curl -I 192.168.1.100
HTTP/1.1 200 OK
Date: Wed, 10 May 2023 07:27:23 GMT
Server: Apache/2.4.51 (Unix) PHP/7.1.10 #可以看到具体的版本
Last-Modified: Wed, 10 May 2023 06:24:44 GMT
ETag: "10-5fb50ed86435c"
Accept-Ranges: bytes
Content-Length: 16
Content-Type: text/html
4.1.2 优化方法
打开http的配置文件,在文件的结尾加入
ServerTokens Prod
ServerSignature off
4.1.3 重启APACHE
[root@lamp conf]# systemctl restart apache
4.1.4 查看
[root@client ~]# curl -I http://192.168.1.100
HTTP/1.1 200 OK
Date: Wed, 10 May 2023 07:56:00 GMT
Server: Apache #没有具体的版本信息。
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes
Content-Length: 45
Content-Type: text/html
4.2 启用压缩模块
网站随着用户访问量的增加和内容量的增加,网站的带宽会不断的增加,随之就是网站成本的增加。 并且当内容量增大的时候,客户端如果带宽小,就会影响用户的体验。因此从这两方面考虑,网站的某些内容必须经过压缩之后再传给用户,然后在用户客户端进行解压,来实现双方共赢的效果。
Apache 的压缩要用到 mod_deflate 模块,该模块提供了 DEFLATE 输出过滤器,允许服务器在将输出内容发送到客户端以前进行压缩,以节约带宽。它的核心思想就是把文件先在服务器进行压缩,然后再进行传输,这样可以显著减少文件传输的大小。当传输完毕后,客户端游览器会重新对压缩过的内容进行解压缩。如果没特殊情况的话,所有的文本内容都应该能被 gzip 压缩,例如:html(php),js,css,xml,txt 等
4.2.1 mod_deflate 模块检查及安装
[root@lamp ~]# /usr/local/apache/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 文件中,以激活此模块,或者,如果此行 已经存在,则启用之。
[root@lamp filters]# /usr/local/src/httpd-2.4.51/modules/filters #apache源码包 mod_deflate 所在的目录
[root@lamp filters]# /usr/local/apache/bin/apxs -c -i -a /usr/local/src/httpd-2.4.51/modules/filters/mod_deflate.c #以 dso 的方式编译安装到apache 中
[root@lamp filters]# ll /usr/local/apache/modules/mod_deflate.so #成功安装这里会显示出该文件 mod_deflate.so
-rwxr-xr-x 1 root root 98632 5月 11 09:03 /usr/local/apache/modules/mod_deflate.so
4.2.2 查看是否安装了模块
[root@lamp filters]# /usr/local/apache/bin/apachectl -M |grep deflate
httpd: Syntax error on line 105 of /usr/local/apache/conf/httpd.conf: Cannot load modules/mod_deflate.so into server: /usr/local/apache/modules/mod_deflate.so: undefined symbol: inflate
解决方法:
[root@lamp filters]# vim /usr/local/apache/conf/httpd.conf
LoadModule deflate_module modules/mod_deflate.so #上面一行,插入以下内容:
LoadFile /usr/lib64/libz.so
[root@lamp filters]# /usr/local/apache/bin/apachectl -M |grep deflate
deflate_module (shared)
4.2.3 压缩模块配置
[root@lamp ~]# vim /usr/local/apache/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、图片和视频本身就是压缩格式,一般不需要压缩的。有些小图片和视频压缩后还会变大。
4.2.4 创建测试文件
[root@lamp htdocs]# cp /etc/passwd /usr/local/apache/htdocs/passwd.html
[root@lamp htdocs]# ll -h
总用量 8.0K
-rw-r--r-- 1 root root 45 6月 12 2007 index.html
-rw-r--r-- 1 root root 2.8K 5月 11 09:22 passwd.html
4.2.5 测试
总结:我们在企业生产环境中时,在启用 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
4.3 Apache 缓存
所说的静态文件指的是图片、js、css等文件,用户访问一个站点,其实大多数元素都是图片、js、css等,这些静态文件其实是会被客户端的浏览器缓存到本地电脑上的,目的就是为了下次再请求时不再去服务器上下载,这样就加快了速度,提高了用户体验。但这些静态文件总不能一直缓存,它总有一些时效性,那么就得设置这个过期时间。
4.3.1 配置静态缓存
vim /usr/local/apache/conf/httpd.conf
<IfModule mod_expires.c> #此模块默认未启用,请手动启用
ExpiresActive on
ExpiresByType image/gif "access plus 1 days"
ExpiresByType image/jpeg "access plus 24 hours"
ExpiresByType image/png "access plus 24 hours"
ExpiresByType text/css "now plus 2 hours"
ExpiresByType application/x-javascript "now plus 2 hours"
ExpiresByType application/javascript "now plus 2 hours"
ExpiresByType application/x-shockwave-flash "now plus 2 hours"
ExpiresDefault "now plus 0 min"
</IfModule>
4.3.2 开启模块
或者使用 mod_headers模块实现:该模块默认启用
<IfModule mod_headers.c>
案例1:htm,html,txt类的文件缓存一个小时
<filesmatch "\.(html|htm|txt)$">
header set cache-control "max-age=3600"
</filesmatch>
案例2: css, js, swf类的文件缓存一个星期
<filesmatch "\.(css|js|swf)$">
header set cache-control "max-age=604800"
</filesmatch>
案例3:jpg,gif,jpeg,png,ico,flv,pdf等文件缓存一年
<filesmatch "\.(ico|gif|jpg|jpeg|png|flv|pdf)$">
header set cache-control "max-age=29030400"
</filesmatch>
</IfModule>
说明:这里的时间单位可以days、hours甚至是min,两种不同的方法,上面使用的是mod_expires,而下面用的是mod_headers,要想使用这些模块,必须要事先已经支持。如何查看是否支持,使用命令:
# /usr/local/apache/bin/apachectl -M
4.3.3 重启服务器并验证
/usr/local/apache/bin/apachectl -t
/usr/local/apache/bin/apachectl stop
/usr/local/apache/bin/apachectl start
[root@localhost htdocs]# curl -x192.168.1.101:80 '192.168.1.101/b.png' -I
HTTP/1.1 200 OK
Date: Sat, 30 Oct 2021 13:41:33 GMT
Server: Apache/2.4.51 (Unix) PHP/7.1.10
Last-Modified: Wed, 07 Jul 2021 02:32:26 GMT
ETag: "53954-5c67f595d8280"
Accept-Ranges: bytes
Content-Length: 342356
Cache-Control: max-age=86400 #这里显示了缓存时间
Expires: Sun, 31 Oct 2021 13:41:33 GMT
Content-Type: image/png
4.4 开启长连接功能
KeepAlive Off/On 保持连接,会减少三次握手,但是会消耗内存,是否打开,取决于单位时间内是否进行多次连接(三次握手),一个连接有多次请求的,建议打开,并适当调整 KeepAliveTimeout 时间在 APACHE 的 httpd.conf 中,KeepAlive 指的是保持连接活跃,如果将 KeepAlive 设置为 On,那么来自同一客户端的请求就不需要再一次连接,避免每次请求都要新建一个连接而加重服务器的负担。
KeepAlive 的连接活跃时间当然是受 KeepAliveTimeOut 限制的。如果第二次请求和第一次请求之间超过 KeepAliveTimeOut 的时间的话,第一次连接就会中断,再新建第二个连接。
所以,一般情况下,图片较多的网站应该把 KeepAlive 设为 On。但是 KeepAliveTimeOut 应该设置为多少秒就是一个值得讨论的问题了。
如果 KeepAliveTimeOut 设置的时间过短,例如设置为 1 秒,那么 APACHE 就会频繁的建立新连接,当然会耗费不少的资源;反过来,如果 KeepAliveTimeOut 设置的时间过长,例如设置为 300秒,那么 APACHE 中肯定有很多无用的连接会占用服务器的资源,也不是一件好事。
所以,到底要把 KeepAliveTimeOut 设置为多少,要看网站的流量、服务器的配置而定。
4.4.1 开启长连接
打开/usr/local/apache/conf/httpd.conf
添加如下内容:
KeepAlive On #如果已经为 On,开启长链接功能。那么就不需要再开启了
KeepAliveTimeout 30 #时间到了断开连接。
注:考虑到如果网站上有不少的图片,所以将 KeepAlive 设为 On,一般的页面两次请求间隔不会超过 30 秒,所以这样设置,至尽运行状况良好。如果是艺术品网站, 需要看的时间长,那么就设置长一些。
MaxKeepAliveRequests 100 默认:100
注:一个建立好的 Keep-Alive 连接,允许发送的请求的个数。一旦建立连接,要么就是个数达到了断开,要么就是等 ,MaxKeepAliveRequests 指令限制了当启用 KeepAlive 时,每个连接允许的请求数量。如果将此值设为"0",将不限制请求的数目。我们建议最好将此值设为一个比较大的值,以确保最优的服务器性能。",这个数字的设置,必须考虑在一个时间段内,同一个用户访问你的服务会发多少请求。要结合KeepAliveTimeout 参数来考虑
4.4.2 案例分析
假设 KeepAlive 的超时时间为 10 秒钟,服务器每秒处理 50 个独立用户访问,那么系统中Apache 的总进程数就是 10 * 50 = 500 个,如果一个进程占用 4M 内存,那么总共会消耗 2G 内存,所以可以看出,在这种配置中,相当消耗内存,但好处是系统只处理了 50 次 TCP 的握手和关闭操作。
如果关闭 KeepAlive,如果还是每秒 50 个用户访问,如果用户每秒的并发请求数为 3 个,那么Apache 的总进程数就是 50 * 3 = 150 个,如果还是每个进程占用 4M 内存,那么总的内存消耗为600M,这种配置能节省大量内存,但是,系统处理了 150 次 TCP 的握手和关闭的操作,因此又会多消耗一些 CPU 资源。
4.5 对 worker、event 模式性能优化
Apache2.0 以后的版本在性能方面改进最明显的变化就在于使用 worker 模式。
优点:内存占用比 prefork 模式低,适合高并发高流量 HTTP 服务。
缺点:假如一个线程崩溃,整个进程就会连同其他任何线程一起“死掉”。由于线程共享内存空间,所以一个程序在运行时必须被系统识别为“每个线程都是安全的”。服务稳定性不如prefork 模式。后期根据每个进程处理的请求数,重启 worker 进程
4.5.1 主配置文件必须开启引用 httpd-mpm.conf
[root@lamp conf]# vim /usr/local/apache/conf/httpd.conf
#开启httpd-mpm.conf配置
Include conf/extra/httpd-mpm.conf
4.5.2 各种模式详解
1)prefork模式
<IfModule mpm_prefork_module>
StartServers 5 #启动时进程数
MinSpareServers 5 #最小空闲线程数。
MaxSpareServers 10 #最大空闲线程数
MaxRequestWorkers 250 # 最大并发进程数。
MaxConnectionsPerChild 0 #最大连接数限制。
</IfModule>
worker模式
</IfModule>
<IfModule mpm_worker_module>
StartServers 3 #启动时进程数
MinSpareThreads 75 #最小空闲线程数。
MaxSpareThreads 250 #最大空闲线程数。
ThreadsPerChild 25 #每个进程可以启动的线程数量。
MaxRequestWorkers 400 #所有线程数量的最大值,通常表示了一个 web 服务可以同时处理的请求数。
MaxConnectionsPerChild 0 #最大连接数限制。
</IfModule>
配置参数详细说明:
<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 管理进程会去终止此进程继续处理新的请求,当此进程处理完所有的已建立的请求后,管理进程会杀掉此进程,重新生成一个新的进程。
event模式
</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 里面只算一个,不管这个连接发送了多少个请求。
示例1:
[root@lamp bin]# ./httpd -V | grep -i "server mpm"
Server MPM: worker
<IfModule mpm_worker_module>
StartServers 8
MinSpareThreads 128
MaxSpareThreads 256
ThreadsPerChild 64
MaxRequestWorkers 4000
MaxConnectionsPerChild 10000
</IfModule>
#重启apache后查看新的配置
[root@lamp extra]# ps -aux |grep -E "^apache" |wc -l
8
[root@lamp extra]# ps -aux|grep -E "^apache"|awk '{print $6}'
5764
5780
5776
5780
5776
5772
5768
5760
注:默认单位是 K,可以看到进程大概使用的是 5764K 内存,一共使用了 5764K*8=46.1MB内存,这是初始的内存大小。 后期随着 Apache 进程处理的 web 请的增加,每个进程使用的内存数量还会增加的。 因为每个网站和业务不一样。所以每个 Apache 进程使用的内存大小也不一样
查看进程使用的内存的总大小
[root@lamp extra]# ps -axu | grep -E "apache" | awk '{sum += $6;n++};END{print sum}'
884336
4.5.3 实战场景
假设:一台服务器,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 进程稳定运行时,平均使用 46M 内存。最大 work 进程数为:56*1024/46=1246 个。
根据上述情况,修改后的 http-mpm.conf
的 worker 的配置后为:
<IfModule mpm_worker_module>
ServerLimit 2000
StartServers 1246 <!--apache启动时默认开始的子进程数-->
MinSpareThreads 1000 <!--最小空闲数量的工作线程-->
MaxSpareThreads 2500 <!--最大空闲数量的工作线程-->
ThreadsPerChild 250 <!--每个子进程产生的线程数量-->
MaxRequestWorkers 25000
MaxConnectionsPerChild 25000
</IfModule>
注意:
在上面的配置项中,各个配置项的值都是有默认的限制的,若想改变其限制,则需要在配置项的上一行增加ServerLimit配置项,而ServerLimit配置项也是有最大限制的,若要修改各种值,建议仔细阅读下面的内容,再进行更改。
worker 由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild 线程数,各个线程独立地处理请求。同样, 为了不在请求到来时再生成线程,MinSpareThreads 和 MaxSpareThreads 设置了最少和最多的空闲线程数。而 MaxRequestWorkers 设置了同时连入的 clients 最大总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程MinSpareThreads 和 MaxSpareThreads 的最大缺省值分别是 75 和 250。这两个参数对 Apache的性能影响并不大,可以按照实际情况相应调节 。
ThreadsPerChild 是 worker MPM 中与性能相关最密切的指令。ThreadsPerChild 的最大缺省值是 64,如果负载较大,64 也是不够的。这时要显式使用 ThreadLimit 指令,它的最大缺省值是 20000。
Worker 模式下所能同时处理的请求总数是由子进程总数乘以 ThreadsPerChild 值决定的,应该大于等MaxRequestWorkers。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是 16,加大时 也需要显式声明 ServerLimit(系统配置的最大进程数量,最大值是20000)。需要注意的是,如果显式声明了 ServerLimit,那么它乘以 ThreadsPerChild的值必须大于等于MaxRequestWorkers,而且MaxRequestWorkers必须是 ThreadsPerChild 的整数倍,否则 Apache 将会自动调节到一个相应值。
4.5.4 生产环境配置实例
一台服务器 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 运行不稳定。
<p>MaxRequestWorkers 2000 #所有线程数量的最大值,通常表示了一个 web 服务的最大并发值。MaxRequestWorkers 必须是 ThreadsPerChild 的整数倍,否则 Apache 会提示调整到一个相近的值。MaxRequestWorkers=StartServers* ThreadsPerChild。 这里是:16<em>125=2000
MaxConnectionsPerChild 12500 # 最大连接数限制。每个子进程可以处理的最大请求数。如果设置为 0,表示没有限制。 我们设置为 MaxConnectionsPerChild 12500。当进程处理了 12500 个请求后,Apache 管理进程会去终止此进程继续处理新的请求,当此进程处理完所有的已建立的请求后,管理进程会杀掉此进程,重新生成一个新的进程。结合当前的配置,得出结论:
Apache 一个进程中有 125 个线程。 Apache 一个进程处理 12500 个请求。 平均一个线程处理12500/125=110 个请求。这样配置还是合理的。一个线程处理太多的请求,也会出现内存溢出,导致进程崩溃
[root@lamp extra]# ps -aux |grep -E "^apache" |wc -l
16
4.6 Apache 的 Rewrite
4.6.1 Rewrite 规则简介
Rewirte 主要的功能就是实现 URL 的跳转,它的正则表达式是基于 Perl 语言。可基于服务器级的(httpd.conf)和目录级的 (.htaccess)两种方式。如果要想用到 rewrite 模块,必须先安装或加载rewrite 模块。
RewriteEngine on #开启引擎
RewriteCond 字符串1 正则条件1 [标识符1] #重写条件
RewriteRule 正则条件2 字符串2 [标识符2] #重写规则
mod_rewrite是按照从上到下的顺序执行重写的规则,如果URL匹配了第一条规则,则按照第一条规则进行重写,如果不匹配,就执行第二条规则,直到最后。通过流程控制,可以定义在不同情况下采用不同的重写规则
4.6.2 安装 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 它里面的规则也不会生效。
4.6.3 重写标志说明
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/(.</em>) /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 条规则。
15) E=VAR:VAL(set environment variable) 设置环境变量。
4.6.4 mod_rewrite 模块检查及安装
[root@lamp extra]# /usr/local/apache/bin/apachectl -M |grep rewrite #没有任何输出说明没有安装这个模块
如果之前安装 Apache 时,没有添加--enable-rewrite 选项,那需要使用下面的方法手动编译出来这个模块。 具体如下:
a)编译方式安装
编译的时候跟上--enable-rewrite 即可实现安装。
b)DSO 方式安装
以 dso 的方式编译安装到 Apache 中
[root@lamp extra]# /usr/local/apache/bin/apxs -c -i -a /usr/local/src/httpd-2.4.51/modules/mappers/mod_rewrite.c
[root@lamp extra]# /usr/local/apache/bin/apachectl -M |grep rewrite #再次查看模块加载情况
rewrite_module (shared)
4.6.5 实战案例
1、访问特定url,跳转到www.baidu.com
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.bestit.com$ [NC]
RewriteRule ^(.<em>)$ http://www.baidu.com [R=301,L]
解释一下上述代码:
RewriteEngine On
:开启重定向模式。RewriteCond %{HTTP_HOST} ^www.bestit.com$ [NC]
:判断请求的主机名是否等于 [www.bestit.com],如果是则拒绝重定向,否则继续执行下面的内容。NC
表示不分大小写。RewriteRule ^(.</em>)$ http://www.baidu.com [R=301,L]
:将请求重定向到 [www.baidu.com],R=301
表示永久重定向,L
表示立即重定向。
2、仅允许特定IP地址访问特定页面,不匹配跳转到指定页面
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^192.168.1.1$ [NC]
RewriteCond %{REQUEST_URI} ^/myhome/ [NC]
RewriteRule ^(.<em>)$ /404/index.html [L,QSA]
解释一下上述代码:
RewriteEngine On
:开启重定向模式。RewriteCond %{REMOTE_ADDR} !^192.168.1.1$ [NC]
:判断请求的 IP 地址是否等于 192.168.1.1,如果是则拒绝重定向,否则继续执行下面的内容。NC
表示不分大小写。RewriteCond %{REQUEST_URI} ^/myhome/ [NC]
:判断请求的 URI 是否等于 /myhome/,如果是则执行重定向,否则继续执行下面的内容。RewriteRule ^(.</em>)$ /404/index.html [L,QSA]
:将请求重定向到/404/index.html 页面,其中$1
表示重定向的 URI,L
表示立即重定向,QSA
表示保留请求参数和标头。
3、实现请求的主机前缀不是 www.bestit.com和 192.168.1.1 都跳转到主机前缀为http://www.bestit.com。例如当用户在地址栏写入 http://wuhan.bestit.com 和 shanghai.bestit.com 直接跳转到 http://www.bestit.com
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.bestit.com$ [NC]
RewriteCond %{HTTP_HOST} !^192.168.1.1$ [NC]
RewriteRule ^(.<em>)$ http://www.bestit.com [R=301,L]
解释一下上述代码:
RewriteEngine On
:开启重定向模式。RewriteCond %{HTTP_HOST} !^www.bestit.com$ [NC]
:判断请求的主机名是否不等于 [www.bestit.com],如果是则拒绝重定向,否则继续执行下面的内容。NC
表示不分大小写RewriteCond %{HTTP_HOST} !^192.168.1.1$ [NC]
:判断请求的主机名是否不等于 192.168.1.1,如果是则拒绝重定向,否则继续执行下面的内容。NC
表示不分大小写。RewriteRule ^(.</em>)$ http://www.bestit.com/$1 [R=301,L]
:将请求重定向到 [www.bestit.com],其中$1
表示重定向的URI,R=301
表示永久重定向,L
表示立即重定向。
4、当访问wuhan.bestit.com子域名时,在前面加上www标记
RewriteEngine On
RewriteCond %{HTTP_HOST} ^wuhan.bestit.com$ [NC]
RewriteRule ^(.<em>)$ http://www.wuhan.bestit.com [R=301,L]
解释一下上述代码:
RewriteEngine On
:开启重定向模式。RewriteCond %{HTTP_HOST} ^wuhan.bestit.com$ [NC]
:判断请求的主机名是否等于 Wuhan.bestit.com,如果是则拒绝重定向,否则继续执行下面的内容。NC
表示不分大小写。RewriteRule ^(.</em>)$ http://www.wuhan.bestit.com/$1 [R=301,L]
:将请求重定向到 [www.wuhan.bestit.com],其中$1
表示重定向的 URI,R=301
表示永久重定向,L
表示立即重定向。
5、当访问www.wuhan.bestit.com子域名时,去掉www标记,但是保存子域名
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.wuhan.bestit.com$ [NC]
RewriteRule ^(.<em>)$ http://wuhan.bestit.com [R=301,L]
解释一下上述代码:
RewriteEngine On
:开启重定向模式。RewriteCond %{HTTP_HOST} ^www.wuhan.bestit.com$ [NC]
:判断请求的主机名是否等于 [www.wuhan.bestit.com],如果是则拒绝重定向,否则继续执行下面的内容。NC
表示不分大小写。RewriteRule ^(.</em>)$ http://wuhan.bestit.com/$1 [R=301,L]
:将请求重定向到 wuhan.bestit.com,同时将原始域名保留在请求中,其中$1
表示重定向的 URI,R=301
表示永久重定向,L
表示立即重定向。
6、当访问www.bestit.com/index.html的时候,将.html后缀名转换成.php
RewriteEngine On
RedirectMatch ^/index.html$ /index.php
RedirectMatch ^/(.<em>).html$ /(.</em>).php
解释一下上述代码:
这些规则将在 Apache 服务器响应请求时执行。首先,
RewriteEngine On
指令将开启重定向功能。
接下来,第一个 RedirectMatch
规则将匹配 /index.html
请求,并将其重定向到 /index.php
。^/index.html$
表示匹配 /index.html
开头的 URL,/index.php
表示重定向到的 URL。
第二个
RedirectMatch
规则将匹配/(.<em>).html$
开头的 URL,并将其重定向到/(.</em>).php
。这里,^/(.<em>).html$
表示匹配/(.</em>).html
开头的 URL,/(.<em>).php
表示重定向到的 URL。
7、判断是否是443端口,如果不是则重定向到www.bestit.com/index.php的443端口
RewriteEngine On
RewriteCond %{HTTP_PORT} !^443$
RewriteRule ^/index.html$ https://www.bestit.com/index.php [R=301,L]
解释一下上述代码:
这个规则使用
RewriteEngine On
指令来启用重定向功能接下来,
RewriteCond %{HTTP_PORT} !^443$
指令将判断请求的端口是否为 443。如果不是,则使用RewriteRule
指令将 URL 重定向到https://www.bestit.com/index.php
。R=301
参数表示将请求重定向到新 URL,L
参数表示强制立即执行重定向操作。
8、防止图片盗链
防止别人直接从你网站引用图片等链接,消耗了你的资源和网络流量
注意:需要2台服务器测试
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://www.bestit.com/ [NC] # 防止盗链
RewriteCond %{HTTP_REFERER} !^http://www.bestit.com/index.html [NC] # 防止盗链
RewriteCond %{HTTP_REFERER} !^http://www.bestit.com/index.php [NC] # 防止盗链
RewriteRule ^/?(.</em>).png$ http://www.bestit.com/index.php [R=301,L] # 重定向到 PHP 处理
解释一下上述代码:
这个规则使用
RewriteEngine On
指令来启用重定向功能。接下来,
RewriteCond %{HTTP_REFERER} !^http://www.bestit.com/
指令将判断请求的 referrer 是否为www.bestit.com/
。如果不是,则使用RewriteRule
指令将 URL 重定向到http://www.bestit.com/(.*).php
。R=301
参数表示将请求重定向到新 URL,L
参数表示强制立即执行重定向操作。
新开一个服务器,安装http服务,添加如下内容
[root@client htdocs]# cat index.html
< html>
<h1>TEST Apache PNG </h1>
<img src="http://www.bestit.com/a.png">
</html>
[root@client htdocs]#
解释一下上述代码:
这个静态文件中主要作用是当用户访问当前这台服务器的时候,会引用/www.bestit.com/a.png这个图片,在服务端已经做了防盗链的设置,最后的效果如下:
4.7 常见的Apache的环境变量
Apache中有很多环境变量,以下是一些常见的变量
变量名称 | 变量类型 | 描述 |
---|---|---|
HTTP_USER_AGENT | String | 发送请求的用户代理字符串 |
HTTP_REFERER | String | 发送请求的页面的 referer |
HTTP_COOKIE | String | 包含在请求中的目标 Cookie |
HTTP_FORWARDED | Bool | 指示请求是否通过代理服务器发送 |
HTTP_HOST | String | 发送请求的服务器主机名 |
HTTP_PROXY_CONNECTION | Bool | 指示请求是否通过代理服务器发送 |
HTTP_ACCEPT | String | 发送请求的可接受的内容类型列表 |
REMOTE_ADDR | IP 地址 | 发送请求的客户端 IP 地址 |
REMOTE_HOST | 主机名 | 发送请求的客户端主机名 |
REMOTE_USER | 用户名 | 发送请求的客户端用户名 |
REMOTE_IDENT | String | 发送请求的客户端 IP 地址和客户端机器名的字符串表示 |
REQUEST_METHOD | String | 发送请求的方法,例如 GET 或 POST |
SCRIPT_FILENAME | String | 当前脚本的文件名 |
PATH_INFO | String | 当前请求的路径信息 |
QUERY_STRING | String | 当前请求的查询字符串 |
AUTH_TYPE | String | 发送请求的认证类型 |
DOCUMENT_ROOT | String | 当前文档根目录 |
SERVER_ADMIN | String | 服务器管理员的电子邮件地址 |
SERVER_NAME | 主机名 | 服务器主机名 |
SERVER_ADDR | IP 地址 | 服务器 IP 地址 |
SERVER_PORT | 端口号 | 服务器端口号 |
SERVER_PROTOCOL | String | 服务器使用的 HTTP 协议版本 |
SERVER_SOFTWARE | String | 服务器使用的软件版本 |
TIME_YEAR | Integer | 当前年份 |
TIME_MON | Integer | 当前月份 |
TIME_DAY | Integer | 当前日期的当天日期 |
TIME_HOUR | Integer | 当前小时数 |
TIME_MIN | Integer | 当前分钟数 |
TIME_SEC | Integer | 当前秒数 |
TIME_WDAY | Integer | 当前日期的当天星期几 (0 表示星期日,1 表示星期一,以此类推) |
TIME | Integer | 当前时间戳 |
API_VERSION | String | 当前 API 版本号 |
THE_REQUEST | String | 当前请求的详细信息 |
REQUEST_URI | String | 当前请求的 URI |
五、实战:部署Discuz论坛
官方网站:https://www.discuz.vip
5.1 下载Discuz论坛
下载地址:https://www.discuz.vip/download.html
请根据要求完成如下架构内容:
1.1 部署一套LAMP网站架构
1.2 前端的网页数据存放在NFS服务器中,为了避免NFS的单点故障导致数据异常,因此需要部署一个备份服务器时刻同步NFS主服务器的数据
1.3 动态数据需要存在Mysql数据中
1.4 为了确保网站的数据的安全性,因此需要部署SSL证书
1.5 域名解析使用DNS自动完成,并使用DNS来实现访问负载均衡
IP | 用途 |
---|---|
10.0.0.8 | Client |
10.0.0.9 | DNS |
10.0.0.10 | Web1 |
10.0.0.11 | Web2 |
10.0.0.12 | NFS-Server |
10.0.0.13 | NFS-Backup-server |
10.0.0.14 | MySQL |
=========================================NFS-Rsync=========================================</p>
<h1 id="NFS">NFS</h1>
<p>[root@nfs-server~]$ yum install nfs-utils -y
[root@nfs-backup~]$ yum install nfs-utils -y
[root@nfs-server~]$ useradd -u 1500 nfs
[root@nfs-backup~]$ useradd -u 1500 nfs
[root@nfs-server~]$ cat /etc/exports
[root@nfs-backup~]$ cat /etc/exports
/var/www/html 10.0.0.0/24(rw,all_squash,anonuid=1500,anongid=1500)
[root@nfs-server~]$ systemctl start nfs.service
[root@nfs-backup~]$ systemctl start nfs.service
[root@nfs-server~]$ cat rsync_inotify.sh
#!/bin/bash
/usr/bin/yum install -y epel-release &&
/usr/bin/yum install inotify* -y</p>
<h1 id="服务端密码">服务端密码</h1>
<p>PASS=123456
rpm -q sshpass &> /dev/null || yum -y install sshpass &> /dev/null
rm -rf .ssh/id_rsa .ssh/id_rsa.pub
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa &> /dev/null && echo "ssh key is created"
</p>
<h1 id="定义目标主机">定义目标主机</h1>
<p>host="10.0.0.13"
for IP in $host ;do
{
sshpass -p$PASS ssh-copy-id -i /root/.ssh/id_rsa.pub root@$IP -o StrictHostKeyChecking=no &>/dev/null
echo $IP is ready
}&
done
wait
</p>
<h1 id="Client 本地同步目录">Client 本地同步目录</h1>
<p>SRC=/var/www/html/
</p>
<h1 id="Server 远程目录">Server 远程目录</h1>
<p>DST1=root@10.0.0.13:/var/www/html
</p>
<h1 id="D C E 接收三个输出的变量">D C E 接收三个输出的变量</h1>
<p>inotifywait -mrq -e modify,delete,create,attrib ${SRC}|while read D E F
do
/usr/bin/rsync -avz --delete $SRC $DST1
done
[root@nfs-server~]$ chmod a+x rsync_inotify.sh
[root@nfs-server~]$ nohup ./rsync_inotify.sh &
=========================================Web=========================================
</p>
<h1 id="Web">Web</h1>
<p>[root@web1~]$ vim /etc/fstab && mount -a
10.0.0.12:/var/www/html /var/www/html nfs _netdev 0 0
[root@web2~]$ vim /etc/fstab && mount -a
10.0.0.13:/var/www/html /var/www/html nfs _netdev 0 0
[root@web1~]$ yum -y install httpd php php-mysql mod_ssl openssl
[root@web2~]$ yum -y install httpd php php-mysql mod_ssl openssl</p>
<p>[root@web1/etc/ssl/certs]$ ls
ca-bundle.crt ca.key make-dummy-cert renew-dummy-cert
ca-bundle.trust.crt localhost.crt Makefile</p>
<h2 id="[root@web1/etc/ssl/certs]$ openssl req -new -key ca.key -out https.csr
...">[root@web1/etc/ssl/certs]$ openssl req -new -key ca.key -out https.csr
...</h2>
<p>Country Name (2 letter code) [XX]:CN #国家
State or Province Name (full name) []:HB #省份
Locality Name (eg, city) [Default City]:wh #城市
Organization Name (eg, company) [Default Company Ltd]:wuhan #组织单位名称
Organizational Unit Name (eg, section) []:wuhan<br />
Common Name (eg, your name or your servers hostname) []:www.myx.com #域名
Email Address []:myx@qq.com #邮箱地址</p>
<p>Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: #回车
An optional company name []: #回车</p>
<p>[root@web1/etc/ssl/certs]$ openssl x509 -req -days 365 -sha256 -in https.csr -signkey ca.key -out https.crt
Signature ok
subject=/C=CN/ST=WH/L=wh/O=wh/OU=wh/CN=www.myx.com/emailAddress=myx@qq.com
Getting Private key</p>
<p>[root@web1/etc/httpd/conf.d]$ vim ssl.conf
SSLCertificateFile /etc/ssl/certs/https.crt
SSLCertificateKeyFile /etc/ssl/certs/ca.key
=========================================DNS=========================================
</p>
<h1 id="DNS">DNS</h1>
<p>[root@DNS/var/named]$ vim /etc/named.conf
options {
// listen-on port 53 { 127.0.0.1; };
listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
recursing-file "/var/named/data/named.recursing";
secroots-file "/var/named/data/named.secroots";
// allow-query { localhost; };
[root@DNS/var/named]$ vim /etc/named.rfc1912.zones
zone "myx.com" IN {
type master;
file "myx.com.zone";
};
[root@DNS/var/named]$ cat myx.com.zone
$TTL 1D
@ IN SOA master smtp.myx.com. (01 1D 1H 1W 1H )
NS master
master A 10.0.0.9
www CNAME webser
webser A 10.0.0.10
webser A 10.0.0.11
=========================================NFS=========================================
</p>
<h1 id="NFS-Server">NFS-Server</h1>
<p>[root@NFS-Server/var/www/html]$ if [ -f /usr/bin/curl ];then curl -sSLO https://www.discuz.vip/install/X3.4.sh;else wget -O X3.4.sh https://www.discuz.vip/install/X3.4.sh;fi;bash X3.4.sh
=========================================MySQL=========================================
</p>
<h1 id="Mysql">Mysql</h1>
<p>[root@db~]$ yum install mariadb -y
[root@DB~]$ mysql
mysql> grant all privileges on db.* to root@'localhost' identified by '123456' with grant option;
mysql> GRANT ALL PRIVILEGES ON <em>.</em> TO 'root'@'10.0.0.%' IDENTIFIED BY '123456' WITH GRANT OPTION;
=========================================Client=========================================
</p>
<h1 id="Client">Client</h1>
<p>[root@client~]$ cat /etc/resolv.conf
nameserver 10.0.0.9
</p>
<h1 id="Windows">Windows</h1>
<p>C:\WINDOWS\system32\drivers\etc\hosts
10.0.0.9 www.myx.com # DNS-Server
[root@client~]$ dig www.myx.com
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.13 <<>> www.myx.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37581
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.myx.com. IN A
;; ANSWER SECTION:
www.myx.com. 86400 IN CNAME webser.myx.com.
webser.myx.com. 86400 IN A 10.0.0.10
webser.myx.com. 86400 IN A 10.0.0.11
;; AUTHORITY SECTION:
myx.com. 86400 IN NS master.myx.com.
;; ADDITIONAL SECTION:
master.myx.com. 86400 IN A 10.0.0.9
;; Query time: 1 msec
;; SERVER: 10.0.0.9#53(10.0.0.9)
;; WHEN: 六 11月 11 13:06:15 CST 2023
;; MSG SIZE rcvd: 130
[root@client~]$ ping www.myx.com
PING www.myx.com (10.0.0.11) 56(84) bytes of data.
64 bytes from 10.0.0.11 (10.0.0.11): icmp_seq=1 ttl=64 time=0.553 ms
64 bytes from 10.0.0.11 (10.0.0.11): icmp_seq=2 ttl=64 time=0.691 ms
^C
--- www.myx.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.553/0.622/0.691/0.069 ms
[root@client~]$ ping www.myx.com
PING www.myx.com (10.0.0.10) 56(84) bytes of data.
64 bytes from 10.0.0.10 (10.0.0.10): icmp_seq=1 ttl=64 time=0.542 ms
64 bytes from 10.0.0.10 (10.0.0.10): icmp_seq=2 ttl=64 time=0.727 ms
^C
--- www.myx.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.542/0.634/0.727/0.095 ms
- 感谢你赐予我前进的力量