4. LAMP架构基础
1 LAMP介绍
1.1 静态资源与动态资源
WEB资源类型:
静态资源:原始代码与响应内容一致,在客户端浏览器执行
动态资源:原始代码通常为程序文件,需要在服务器端执行之后,将执行结果返回给客户端
注意:静态和动态的区别,不在于网页是否能动态变化,而在于服务端的页面文件和客户端得到页面文件是否一致
1.2 LAMP架构

LAMP工作过程:
Apache本身并不支持动态程序的处理, 默认只能处理静态程序, 动态php程序是无法处理的.
- 当客户端请求的是静态资源时, httpd服务器会直接到磁盘把静态资源文件找到, 封装在apache的响应报文, 发给客户端
- 当客户端请求的是动态资源时, 比如php程序, httpd服务器的php模块会进行相应的动态资源运算, 如果此过程还需要数据库的数据作为运算参数时, php会连接mysql取得数据,然后进行运算, 运算的结果转为静态资源由httpd服务器封装在响应报文头部返回到客户端. 客户端看到的是执行结果, 而非php程序本身.
- 动态程序语言, 需要有自己专门的解释器去执行程序, 因此httpd和动态程序语言之间是通过相应的协议去通信的. CGI/FastCGI. httpd一端通过http协议连接http客户端, 另一端通过CGI/FastCGI协议连接到动态程序. httpd起到代理的角色. 因为用户不是直接访问动态程序, 而是通过httpd, 而httpd在收到用户请求后, 再转发用户的请求到后端动态页面程序来进行处理, 因此httpd是代理程序,代理器.
1.3 CGI协议 vs FastCGI协议
CGI: Common Gateway Interface 公共网关接口
CGI在2000年或更早的时候用得比较多, 以前Web服务器一般只处理静态的请求, 如果碰到一个动态请求怎么办呢? Web服务器会根据这次请求的内容, 然后会fork一个新进程(子进程)来运行外部的c程序或者bash,perl脚本等, 这个进程会把处理完的数据返回给Web服务器, 最后Web服务器把内容发送给用户, 刚才fork的进程也随之退出. 如果下次用户还请求该动态脚本, 那么Web服务器又再一次fork一个新进程, 周而复始的进行.
CGI 可以让一个客户端,从网页浏览器通过http服务器向执行在网络服务器上的程序传输数据;CGI描述了客户端和服务器程序之间传输的一种标准
CGI协议: httpd开启一个子进程来运行动态应用程序, 动态程序是httpd开启的一个子进程, 并不是完全独立的程序, 程序运行完会自动关闭, 依附于httpd, httpd和程序通过CGI协议通信. 消耗资源, 慢, 对于相同的访问, 每次都要开启单独的子进程进程处理, 处理完关闭子进程. 子进程频繁的开启和关闭. 使用CGI协议, 需要apache和应用程序在同一个服务器上, 因为是父子进程的关系
请求流程:
Client — (http协议) –> httpd — (cgi协议) –> 本地application server (program file) — (mysql协议) –> mysql
nginx要和php搭配,是不支持CGI的, 只支持FastCGI
FastCGI:
FastCGI的方式是,web服务器收到一个请求时,不会fork一个子进程,而是直接把请求通过FastCGI协议传递给FastCGI服务器,FastCGI服务器上的进程始终是开启的, 接收到用户请求后, 会分配独立的子进程处理请求, 处理完再返回给apache服务器. FastCGI程序与apache之间没有依附关系, 可以在不同的服务器部署, 此时apache和FastCGI服务器要基于tcp/udp协议通讯, 此时apache相当于一个代理服务器, 用于接收用户请求, 并且返回数据给用户

请求流程:
Client — (http协议) –> httpd — (FastCGI协议) –> FastCGI服务器(php,python...) — (mysql协议) –> mysql
两者对比:
名称 | 在web服务器方面 | 在对数据进行处理的进行方面 |
---|---|---|
CGI | fork一个新的进程,进程处理 | 读取参数, 处理数据, 然后关闭, 结束生命周期 |
FastCGI | 用tcp方式与远程FastCGI服务器上的进程或者apache本地的进程建立连接, 进程间是独立的 | 要开启tcp端口, 进入循环, 等待数据的到来, 处理数据 |
1.4 PHP语言
1.4.1 PHP 简介
PHP官网:http://www.php.net/
1.4.2 PHP的Opcode语言
Opcode是一种PHP脚本编译后的中间语言,类似于Java的ByteCode,或者.NET的MSL。
PHP的语言引擎Zend执行PHP脚本代码一般会经过如下4个步骤
1、Scanning 词法分析,将PHP代码转换为语言片段(Tokens)
2、Parsing 语义分析,将Tokens转换成简单而有意义的表达式
3、Compilation 将表达式编译成Opcode
4、Execution 顺次执行Opcode,每次一条,从而实现PHP脚本的功能
即:扫描–>分析–>编译–>执行
1.4.3 PHP配置
PHP主配置文件, 来自php-common包, /etc/php.ini, /etc/php.d/*.ini
配置文件在php解释器启动时被读取
对配置文件的修改生效方法
Modules(以apache的一个模块工作):重启httpd服务
FastCGI:重启php-fpm服务
/etc/php.ini配置文件格式:
[foo]:Section Header
directive = value
注释符:
以#开头,纯粹的注释信息
以 ; 开头,用于注释可启用的directive指令
提示:较新的版本中,已经完全使用 “ ; ” 进行注释
php常见设置:
expose_php = On #在响应报文显示首部字段x-powered-by: PHP/x.y.z,暴露php版本,建议设为off
max_execution_time= 30 最长执行时间30s
memory_limit=128M 生产不够,可调大
display_errors=off 调试使用,不要打开,否则可能暴露重要信息
display_startup_errors=off 建议关闭
post_max_size=8M 最大上传数据大小,生产可能调大,比下面项大
upload_max_filesize =2M 最大上传文件,生产可能要调大
max_file_uploads = 20 同时上传最多文件数
date.timezone =Asia/Shanghai 指定时区
short_open_tag=on 开启短标签,如: <? phpinfo();?>
配置范例:
yum提供的PHP和httpd是依赖关系, 如果服务器没有装httpd, 那么yum安装PHP时会自动安装httpd.

基于CentOS-8
[01:02:36 root@php ~]#yum -y install php
[01:04:03 root@php ~]#rpm -qc php
/etc/httpd/conf.d/php.conf # 安装php后, 默认就会在httpd目录生成对应的php配置文件
/etc/httpd/conf.modules.d/15-php.conf
[01:08:15 root@php ~]#systemctl start httpd
[01:09:55 root@php ~]#vim /var/www/html/test.php
<?php
phpinfo();
?>
[01:10:21 root@php ~]#curl -I 10.0.0.86/test.php
HTTP/1.1 200 OK
Date: Wed, 10 Mar 2021 17:10:36 GMT
Server: Apache/2.4.37 (centos)
X-Powered-By: PHP/7.2.24 # 默认会显示php版本
Content-Type: text/html; charset=UTF-8
php默认使用utc时间, 需要修改配置文件的timezone

[01:13:07 root@php ~]#vim /etc/php.ini
expose_php = Off
date.timezone = Asia/Shanghai
[01:16:22 root@php ~]#systemctl restart php-fpm # CentOS 8安装了PHP后, 默认工作在FastCGI模式下, 通过php-fpm进程来管理php, 是独立服务. 启动httpd服务后, php-fpm进程会自动开启.
php版本被隐藏
[01:17:42 root@php ~]#curl -I 10.0.0.86/test.php
HTTP/1.1 200 OK
Date: Wed, 10 Mar 2021 17:18:01 GMT
Server: Apache/2.4.37 (centos)
Content-Type: text/html; charset=UTF-8
timezone修改成功

PHP运行方式:
CentOS 8安装了PHP后, 默认工作在FastCGI模式下, 通过php-fpm进程来管理php, 是独立服务. 启动httpd服务后, php-fpm进程会自动开启.
CentOS 7安装了PHP后,默认工作以httpd的一个模块进行工作, 依赖于httpd
CentOS 7上将两个服务完全独立开来, 需要各自分别启动
CentOS 8以 FastCGI模式运行php时, 启动httpd会自动启动php-fpm, 两者有依赖关系
PHP安全性不高, 因为是解释型语言, 需要把源代码放在服务器上运行. 适合中小网站.
php生成session信息
php生成的session信息, 除了在内存中保存, 还会在磁盘保存一份
[01:18:01 root@php ~]#vim /var/www/html/session.php
<?php
session_start();
echo session_id();
?>
[01:27:27 root@php ~]#curl 10.0.0.86/session.php
hrm89440obdbejbu4fj1caha14
[01:27:45 root@php ~]#ll /var/lib/php/session/
total 0
-rw------- 1 apache apache 0 Mar 11 01:27 sess_hrm89440obdbejbu4fj1caha14
客户端浏览器访问服务器时, 服务器会产生一个session信息给客户端, 客户端每次访问时, 默认都会携带这个cookie, 因此, 服务器不会重复生成session信息
curl浏览器, 默认访问时是不携带cookie的, 所以每次访问服务器时, 服务器都会产生一个新的session ID, 如果想访问时携带cookie, 可以添加 -b 选项, 指定cookie的名字.
[01:27:49 root@php ~]#curl 10.0.0.86/session.php
2f374o4qpqs0cq12tjf7ai
[01:29:56 root@php ~]#ll /var/lib/php/session/
total 0
-rw------- 1 apache apache 0 Mar 11 01:29 sess_2f374o4qpqs0cq12tjf7aie751
[01:31:08 root@php ~]#curl -b PHPSESSID=2f374o4qpqs0cq12tjf7aie751 10.0.0.86/session.php
2f374o4qpqs0cq12tjf7aie751 # 因为-b会携带cookie信息, 因此不会生成新的session而是返回请求时携带的
1.4.4 PHP语言格式
php语言有两种使用格式:
格式 1
<?php
echo "<h1>Hello world!</h1>"
?>
格式 2
<h1>
<?php echo "Hello world!" ?>
</h1>
1.4.5 LAMP实现方式
httpd 接收用户的web请求;静态资源则直接响应;动态资源为php脚本,对此类资源的请求将交由php来运行
httpd与php结合的方式
modules :apache是没有处理动态页面的功能, 如果想处理php程序, 可以将php编译成为httpd的模块, 类似CGI模式, libphp5.so,只有prefork 模式才支持
FastCGI : 以专门的服务器软件来处理php程序, apache作为反向代理
LAMP架构实现
静态资源:
Client — http –> httpd
动态资源:
Client — http –> httpd –> libphp5.so () — mysql –> MySQL server
Client — http –> httpd –>fastcgi– mysql –> MySQL server
2 实现LAMP
2.1 利用rpm包实现LAMP安装部署
CentOS 8
Module 模块方式
dnf install httpd mariadb-server php php-mysqlnd
FastCGI 方式
dnf install httpd mariadb-server php-fpm php-mysqlnd # CentOS-8上, 启动httpd会自动启动php-fpm
CentOS 7
Module 模块方式
yum install httpd mariadb-server php php-mysql
FastCGI 方式
yum install httpd php-fpm php-mysql mariadb-server # CentOS-7上, 需要分别启动httpd和php-fpm
CentOS 6
Module 模块方式
yum install httpd, php, php-mysql, mysql-server
FastCGI方式:默认不支持
注意:基于module实现,httpd 需要 使用prefork模型
2.2 PHP连接MySQL的方式
- 使用mysql扩展连接数据库
使用mysql扩展模块mysql.so连接数据,此方式已经在php 7 版后淘汰
范例:php使用mysql扩展连接数据库的测试代码
<?php
conn = mysql_connect('mysqlserver','username','password');
if (conn)
echo "OK";
else
echo "Failure";
#echo mysql_error();
mysql_close();
?>
- 使用mysqli扩展连接数据库
使用mysqli扩展模块mysqli.so连接数据,此方式只能连接MySQL数据库,不支持其它数据库
范例:php使用mysqli扩展连接数据库的测试代码
<?php
mysqli=new mysqli("mysqlserver", "username", "password");
if(mysqli_connect_errno()){
echo "Failure";mysqli=null;
exit;
}
echo "OK";
$mysqli->close();
?>
- 使用PDO(PHP Data Object)扩展连接数据库
使用PDO扩展模块pdo_mysql.so连接数据库,此方式可以支持连接MySQL,Oracle等多种数据库
范例:php使用pdo扩展连接数据库的测试代码1
<?php
dsn='mysql:host=mysqlhost;port=3306;dbname=mysql';username='root';
passwd='magedu';dbh=new PDO(dsn,username,passwd);
var_dump(dbh);
?>
范例:php使用pdo扩展连接数据库的测试代码2
<?php
try {
user='root';pass='magedu';
dbh = new PDO('mysql:host=mysqlhost;port=3306;dbname=mysql',user, pass);
foreach(dbh->query('SELECT user,host from user') as row) {
print_r(row);
}
dbh = null;
} catch (PDOExceptione) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
?>
2.3 实现LAMP实战案例
范例:CentOS 8 默认使用FastCGI模式,可以按下面步骤修改为httpd的模块方式
dnf -y install httpd php
#修改为prefork模式支持httpd 模块方式
[01:59:19 root@php ~]#vim /etc/httpd/conf.modules.d/00-mpm.conf
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
#LoadModule mpm_event_module modules/mod_mpm_event.so
#CentOS 8的php 默认是factcgi模式 ,修改为httpd模块方式,此步非必须,是可选做
[02:07:49 root@php ~]#vim /etc/httpd/conf.d/php.conf
<IfModule !mod_php5.c>
<IfModule !mod_php7.c>
# Enable http authorization headers
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
<FilesMatch \.(php|phar)$>
SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost"
</FilesMatch>
</IfModule>
</IfModule>
范例: CentOS 8 部署 phpMyAdmin 5.0.2, 基于模块模式
[02:46:41 root@phpmyadmin ~]#yum -y install httpd mysql-server php php-mysqlnd php-json
[02:48:36 root@phpmyadmin ~]#systemctl enable --now mysqld httpd
[02:50:42 root@phpmyadmin ~]#mysql_secure_installation
[02:51:36 root@phpmyadmin ~]#unzip phpMyAdmin-5.0.2-all-languages.zip
[02:51:50 root@phpmyadmin ~]#mv phpMyAdmin-5.0.2-all-languages /var/www/html/pma
浏览器访问10.0.0.86/pma

3 php的加速器
php的加速器: 基于php的特殊扩展机制, 如opcode缓存扩展, 也可以将opcode缓存于php的共享内存中, 从而可以让同一段代码的后续重复执行时跳过编译阶段以提高性能. 也就是把opcode复用. 这些加速器并没真正提高了opcode的运行速度, 而只是通过分析opcode后将它们重新排列以达到快速执行的目的.
3.1 常见的第三方php加速器
xcache:
快速而且稳定的PHP opcode缓存,经过严格测试且被大量用于生产环境
3.2 opcache加速php 7.X
[root@centos8 ~]#dnf install php-opcache
[root@centos8 ~]#cat /etc/php.ini
[opcache]
zend_extension=opcache.so
opcache.enable=1
查看opcache配置文件, 可以看到opcache加速默认是开启的, 也就是说只要下载了, php-opcache包, 就会启动加速
; Determines if Zend OPCache is enabled
opcache.enable=1
...
范例:CentOS 8 实现opache 加速
基于上面搭建的phpmyadmin
[03:05:48 root@phpmyadmin ~]#yum -y install php-opcache
[03:06:17 root@phpmyadmin ~]#rpm -ql php-opcache
/etc/php.d/10-opcache.ini
/etc/php.d/opcache-default.blacklist
/usr/lib/.build-id
/usr/lib/.build-id/76
/usr/lib/.build-id/76/2fff704ed4e15320636edca34c36f8871c7988
/usr/lib64/php/modules/opcache.so
[03:06:35 root@phpmyadmin ~]#grep opcache /etc/php.d/10-opcache.ini
zend_extension=opcache
opcache.enable=1
#加速前
#禁用加速
[03:06:49 root@phpmyadmin ~]#vim /etc/php.d/10-opcache.ini
opcache.enable=0
[03:07:32 root@phpmyadmin ~]#systemctl restart php-fpm
[03:08:07 root@phpmyadmin ~]#ab -c 10 -n 100 http://10.0.0.86/pma
......
Requests per second: 2437.54 [#/sec] (mean)
......
#启用加速
[03:09:08 root@phpmyadmin ~]#vim /etc/php.d/10-opcache.ini
opcache.enable=1
[03:09:20 root@phpmyadmin ~]#systemctl restart php-fpm
##加速后
[03:10:04 root@phpmyadmin ~]#ab -c 10 -n 100 http://10.0.0.86/pma
......
Requests per second: 2729.48 [#/sec] (mean)
......
注意: 动态页面再怎么加速也不如静态页面块, 尽量让动态页面静态化