MySQL主从复制

MySQL 分库分表 + 主从复制 一、主从复制 1. 环境说明 1个master节点,2个slave节点 mysql-master mysql-slave1 mysql-slave2 此处使用docker启动多个 MySQL 容器,为每个容器挂载配置文件 docker run -d --name mysql-master -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 mysql:8.0 docker run -d --name mysql-slave1 -e MYSQL_ROOT_PASSWORD=root -p 3307:3306 mysql:8.0 docker run -d --name mysql-slave2 -e MYSQL_ROOT_PASSWORD=root -p 3308:3306 mysql:8.0 创建配置文件目录 mkdir -p ~/mysql/master ~/mysql/slave1 ~/mysql/slave2 2. 修改配置 master的 my.cnf (~/mysql/master/my.cnf) [mysqld] server-id=1 log_bin=mysql-bin binlog_format=ROW gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON slave1 的 my.cnf(~/mysql/slave1/my.cnf) [mysqld] server-id=2 relay_log_recovery=ON read_only=ON super_read_only=ON gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON slave2 的 my....

February 20, 2024 · 2 min · Leanku

Mysql的一些常见题

Mysql的一些常见题 请写出数据类型(int char varchar datetime text)的意思;请问 varchar 和 char有什么区别? Int 整数char 定长字符 Varchar 变长字符 Datetime 日期时间型Text 文本型 Varchar与char的区别 char是固定长度的字符类型,分配多少空间,就占用多长空间。Varchar是可变长度的字符类型,内容有多大就占用多大的空间,能有效节省空间。由于varchar类型是可变的,所以在数据长度改变的时,服务器要进行额外的操作,所以效率比char类型低。 MyISAM和 InnoDB 的基本区别?索引结构如何实现? A、MyISAM类型不支持事务,表锁,易产生碎片,要经常优化,读写速度较快,适合用于频繁查询的应用; B、InnoDB类型支持事务,行锁,有崩溃恢复能力,读写速度比MyISAM慢,适合于插入和更新操作比较多的应用,空间占用大,不支持全文索引等。创建索引:alert table tablename add index 索引名 (字段名) 什么是事务?及其特性? 答:事务:是一系列的数据库操作,是数据库应用的基本逻辑单位。 事务特性:A、原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。B、一致性或可串性。事务的执行使得数据库从一种正确状态转换成另一种正确状态C、隔离性。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务,D、持久性。事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。 或者这样理解:事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。 什么是锁? 答:数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。 加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。 基本锁类型:锁包括行级锁和表级锁 索引的作用?和它的优点缺点是什么? 索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。 怎么防止sql注入? 1)过滤掉一些常见的数据库操作关键字:select,insert,update,delete,and,*等,或者通过系统函数:addslashes(需要被过滤的内容)来进行过滤。 2)在PHP配置文件中 Register_globals=off;设置为关闭状态 //作用将注册全局变量关闭。 比如:接收POST表单的值使用$_POST[‘user’],如果将register_globals=on;直接使用$user可以接收表单的值。 3)SQL语句书写的时候尽量不要省略小引号(tab键上面那个)和单引号 4)提高数据库命名技巧,对于一些重要的字段根据程序的特点命名,取不易被猜到的 5)对于常用的方法加以封装,避免直接暴漏SQL语句 6)开启PHP安全模式 Safe_mode=on; 7)打开magic_quotes_gpc来防止SQL注入 Magic_quotes_gpc=off;默认是关闭的,它打开后将自动把用户提交的sql语句的查询进行转换,把’转为',这对防止sql注入有重大作用。 因此开启:magic_quotes_gpc=on; 8)控制错误信息 关闭错误提示信息,将错误信息写到系统日志。 9)使用mysqli或pdo预处理。 数据库优化策略? 合理的表设计。 依据三范式,设计表. ​ 三范式:1.原子性,每个字段都是不可在分的。 在1方式的基础上,表中每一列必须有唯一性,其他字段依赖主键。 在2方式的基础上,表中的每一列只与主键直接相关,而不是间接相关。 选择合适的字段。 I.尽量使用TYPEINT、SMALLINT、MEDIUM_INT代替INT的使用,一般索引,并且是字段递增,可以考虑设置为UNSIGNED. ​ II.使用枚举代替字符串类型。 ​ III.将少null的使用,null很难优化,并且还占用额外的空间。...

February 20, 2024 · 2 min · Leanku

PHP常见题

PHP常见题 什么事面向对象?主要特征是什么? 面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰。主要特征:封装、继承、多态。 SESSION 与 COOKIE的区别是什么,请从协议,产生的原因与作用说明? A、http无状态协议,不能区分用户是否是从同一个网站上来的,同一个用户请求不同的页面不能看做是同一个用户。B、SESSION存储在服务器端,COOKIE保存在客户端。Session比较安全,cookie用某些手段可以修改,不安全。Session依赖于cookie进行传递。禁用cookie后,session不能正常使用。Session的缺点:保存在服务器端,每次读取都从服务器进行读取,对服务器有资源消耗。Session保存在服务器端的文件或数据库中,默认保存在文件中,文件路径由php配置文件的session.save_path指定。Session文件是公有的。 HTTP 状态中302、403、 500代码含义? 一二三四五原则:(即一:消息系列;二:成功系列;三:重定向系列;四:请求错误系列;五:服务器端错误系列。) 302:临时转移成功,请求的内容已转移到新位置 403:禁止访问 500:服务器内部错误 401:代表未授权。 请写出数据类型(int char varchar datetime text)的意思;请问 varchar 和 char有什么区别? Int 整数char 定长字符 Varchar 变长字符 Datetime 日期时间型Text 文本型 Varchar与char的区别 char是固定长度的字符类型,分配多少空间,就占用多长空间。Varchar是可变长度的字符类型,内容有多大就占用多大的空间,能有效节省空间。由于varchar类型是可变的,所以在数据长度改变的时,服务器要进行额外的操作,所以效率比char类型低。 MyISAM和 InnoDB 的基本区别?索引结构如何实现? A、MyISAM类型不支持事务,表锁,易产生碎片,要经常优化,读写速度较快,适合用于频繁查询的应用; B、InnoDB类型支持事务,行锁,有崩溃恢复能力,读写速度比MyISAM慢,适合于插入和更新操作比较多的应用,空间占用大,不支持全文索引等。创建索引:alert table tablename add index 索引名 (字段名) isset() 和 empty() 区别 isset判断变量是否存在,可以传入多个变量,若其中一个变量不存在则返回假;empty判断变量是否为空为假,只可传一个变量,如果为空为假则返回真。 请说明 PHP 中传值与传引用的区别。什么时候传值什么时候传引用? 按值传递:函数范围内对值的任何改变在函数外部都会被忽略按引用传递:函数范围内对值的任何改变在函数外部也能反映出这些修改优缺点:按值传递时,php必须复制值。特别是对于大型的字符串和对象来说,这将会是一个代价很大的操作。按引用传递则不需要复制值,对于性能提高很有好处。 在PHP中error_reporting这个函数有什么作用? 设置PHP的报错级别并返回当前级别。 现在编程中经常采取MVC三层结构,请问MVC分别指哪三层,有什么优点? MVC三层分别指:业务模型、视图、控制器,由控制器层调用模型处理数据,然后将数据映射到视图层进行显示,优点是:①可以实现代码的重用性,避免产生代码冗余;②M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式 在程序的开发中,如何提高程序的运行效率? A、优化SQL语句,查询语句中尽量不使用select *,用哪个字段查哪个字段;少用子查询可用表连接代替;少用模糊查询; B、数据表中创建索引; C、对程序中经常用到的数据生成缓存。 语句include和require的区别是什么?为避免多次包含同一文件,可用什么语句代替它们? 区别:在失败的时候:include产生一个warning,而require产生直接产生错误中断require在运行前载入include在运行时载入代替:require_once,include_once 简述php的垃圾收集机制。 php中的变量存储在变量容器zval中,zval中除了存储变量类型和值外,还有is_ref和refcount字段。refcount表示指向变量的元素个数,is_ref表示变量是否有别名。如果refcount为0时,就回收该变量容器。如果一个zval的refcount减1之后大于0,它就会进入垃圾缓冲区。当缓冲区达到最大值后,回收算法会循环遍历zval,判断其是否为垃圾,并进行释放处理。 什么是 CSRF 攻击 ?XSS 攻击?如何防范?...

February 20, 2024 · 1 min · Leanku

Redis的一些常见题

Redis的一些常见题 redis数据类型及应用场景 见 Redis的五种数据类型及使用场景 redis持久化及过期策略 见 Redis持久化及过期删除策略 redis 常见问题及解决方案 缓存雪崩:同一时间大量缓存失效,导致请求直接查询数据库,数据库内存和CPU压力增加甚至宕机 解决: 热点数据永不过期或者分布到不同实例,降低单机故障问题 缓存时间添加随机数,防止大量缓存同时失效 做二级缓存或者双缓存,A为原始缓存 短时效,B为备份缓存 ,长期有效。更新时候双写缓存 缓存穿透:缓存和数据库都没有数据,大量请求下,所有请求直接击穿到数据库,导致宕机。 解决: 布隆过滤器:长度为m的位向量或者位列表组成(仅包含0或1位值的列表) 使用多个不用的hash函数,产生多个索引值,填充对应多个位置的值为1 布隆过滤器可以检查值是 “可能在集合中” 还是 “绝对不在集合中” 可能误判但是基础过滤效率高 极端情况,当布隆过滤器没有空闲位置的时候每次查询返回true 空缓存(短时效) 业务层参数过滤 缓存击穿:数据库中有数据,但是缓存突然失效之后发生大量请求导致数据库压力增加甚至打垮宕机 解决: 热点数据永不过期 互斥锁:获取锁之后不管成功还是失败都要释放锁 Redis主从复制原理 Redis 在复制时底层采用的是 psync 命令完成的数据主从同步,同步主要分为:全量复制和增量复制两种 全量复制:顾名思义也就是一次性把主节点数据全部发送给从节点,所以这种情况下,当数据量比较大时,会对主节点和网络造成很大的开销。 部分复制:用于处理主从复制时因网络中断等原因造成数据丢失的场景。当从节点再次和主节点连接时,主节点会补发丢失的数据。因为是补发,所以在发送的数据量一定是小于全量的数据。 详细见 Redis的一些常见题 Redis缓存和数据库数据一致性问题: 读数据 尝试查询缓存,存在缓存则直接返回数据 缓存不存在时则查询数据库,并保存到缓存(合适设置过期时间),返回数据 写数据 先更新缓存再更新数据库 或者 先删除缓存再更新数据库 先更新数据库再更新缓存 或者 先更新数据库再删除缓存 使用删除还是更新? 这里无非是删除还是更新Redis,直接删除的方式比较简单,在下一次查询时会生成缓存(更推荐);更新缓存则相较复杂 先操作Redis还是先操作数据库? 先操作数据库 (推荐) 流程:先更新数据库,再删除缓存 问题:比如线程1执行写操作(修改数据库->删除缓存),线程2执行读操作(查询缓存->旧数据),就会出现旧数据返回,或者删除缓存失败也会返回旧数据 先操作缓存 流程:修改操作先删除缓存再修改数据库 问题: 比如线程1去执行写操作: (删除缓存->更新数据库)同时有线程2执行读操作(查询缓存(未查到缓存)->查数据库->保存到缓存)因为数据库更新有可能网络延迟等问题,这里保存到缓存的数据就是旧的数据,只有再过期之后才会读到新数据 解决方案: (延迟双删)在数据库更新之后再进行一次缓存删除(加适当延迟,比如延迟500ms),这时再有查询过来也会查询到数据库并保存到缓存。但是线程2在这个删除缓存500ms内请求仍然可能会出现一次获取到旧数据 (推荐方式)

February 20, 2024 · 1 min · Leanku

ShardingSphere 使用指南

ShardingSphere 使用指南 一、介绍 Apache ShardingSphere 是一个开源的 分布式数据库中间件生态,支持 分库分表、读写分离、数据加密、影子库 等功能。它的定位是 数据库增强计算层,让你在不修改(或少量修改)应用代码的情况下,实现复杂的数据分片与治理。 核心组件: ShardingSphere-JDBC:客户端 SDK,直接在应用中引入。 ShardingSphere-Proxy:中间件代理层,应用通过 MySQL 协议访问,无需修改业务代码。 ShardingSphere-Sidecar:面向 K8s 的云原生数据库 Mesh。 二、适用场景 分库分表:数据量过大,单表行数超过 1千万~1亿,单库容量超限时。 读写分离:主库写、从库读,提升查询性能。 柔性事务:分布式场景下保证一致性(支持 Seata、XA)。 数据加密:对敏感字段(手机号、身份证号)自动加密存储,解密查询。 影子库:A/B 测试或灰度发布。 三、 配置方式 以 ShardingSphere-Proxy 为例(最常用于 PHP 项目)。 3.1 部署 Proxy wget https://downloads.apache.org/shardingsphere/5.4.2/apache-shardingsphere-5.4.2-shardingsphere-proxy-bin.tar.gz tar -zxvf apache-shardingsphere-5.4.2-shardingsphere-proxy-bin.tar.gz cd apache-shardingsphere-5.4.2-shardingsphere-proxy-bin 配置文件路径: conf/server.yaml # 全局配置(身份认证、元数据) conf/config-sharding.yaml # 分库分表配置 3.2 示例配置(分库分表 + 读写分离) server.yaml (全局配置) authentication: users: root: password: root123 # 设置登录 ShardingSphere-Proxy 的账号和密码 authorizedSchemas: ds_sharding # 指定该用户可访问的逻辑库(schema) props: sql-show: true # 开启 SQL 打印,方便调试时查看 Proxy 最终路由后的真实 SQL config-sharding....

February 20, 2024 · 2 min · Leanku

Logstash

Logstash ALogstash 介绍 Logstash 是一个开源的日志收集、处理和转发工具,通常与 Elasticsearch 和 Kibana 一起组成 Elastic Stack,用于集中式日志管理和数据分析。它支持多种数据源、数据处理及输出目标,常用于日志的收集和处理。 1. 安装 Logstash Logstash 支持多种操作系统,安装方式可以使用包管理工具、压缩包或 Docker。 a. 通过 apt 安装(以 Ubuntu 为例) 首先,添加 Elastic 的 APT 仓库: wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - sudo sh -c 'echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elastic-7.x.list' 然后,更新 APT 仓库并安装 Logstash: udo apt-get update sudo apt-get install logstash b. 使用 .tar.gz 包安装 可以从官网(https://www.elastic.co/downloads/logstash)下载压缩包,解压并安装。 tar -xvzf logstash-7.x.x.tar.gz cd logstash-7.x.x 2. 配置 Logstash Logstash 的配置文件通常由 3 个部分组成:输入(input)、过滤器(filter) 和 输出(output)。...

February 20, 2024 · 2 min · Leanku

PHP常用函数整理

PHP常用函数整理 字符串 strlen() 获取字符串长度。(一个汉字长度为3个字符,一个英文字母长度为1个字符) strpos() 在字符串内查找一个字符或一段指定的文本,返回第一次出现的位置或者false stripos() 同上,但不区分大小写 strrpos() 同上上,返回最后一次出现的位置或false strripos() 同上,但不区分大小写 explode() 字符串打散为数组 implode() 数组拼接成字符串 strtoupper() 把字符串转换为大写 strtolower() 把字符串转换为大写 ucfirst() 把单词的首字母转换成大写 lcfirst() 把单词的首字母转换为小写 ucwords() 把字符串中每个单词的首字母转换为大写 str_replace 子字符串替换 str_ireplace str_replace 的忽略大小写版本 strrev 反转字符串 trim 去除字符串首尾处的空白字符(或者其他字符) rtrim 删除字符串末端的空白字符(或者其他字符) substr 截取字符串的一部分,返回字符串的子串 substr 截取字符串的一部分(中文,需要安装扩展mbstring),返回字符串的子串 更多请参考官方文档 数组 array() 创建数组 count() 返回数组中元素的数量 sizeof() 同样效果 array_push() 将一个或多个单元压入数组的末尾(入栈) array_pop() 弹出数组最后一个单元(出栈) array_unshift() 在数组开头插入一个或多个单元 array_shift() 将数组开头的单元移出数组 shuffle() 打乱数组 reset — 将数组的内部指针指向第一个单元 end — 将数组的内部指针指向最后一个单元 current — 返回数组中的当前值 list — 把数组中的值赋给一组变量...

February 18, 2024 · 1 min · Leanku

一些PHP基础的简单整理

一些PHP基础的简单整理 常量 关于常量定义 <?php $a = 1; define("AAA".$a,"AAA"); echo constant("AAA".$a); define() 在运行时定义一个常量。 constant() 返回一个常量的值。当你不知道常量名,却需要获取常量的值时,constant() 就很有用了。也就是说,常量名储存在一个变量里,或者由函数返回时。 const不能在条件语句中定义常量。 const用于类成员变量的定义,define()不可用于类成员变量的定义,可用于全局变量。 const可在类中使用,define不能。 常量和变量的区别 常量前面没有且不能有$符号 常量可以不用理会变量的作用域,在任何地方定义和使用 常量一旦定义就不能重新定义或取消定义 常量的值只能是标量(字符串、整数、浮点数、布尔值),支持数组 获取所有常量 get_defined_constants() get_defined_constants(true) get_defined_constants(true)[‘user’] 魔术常量:它的值随着它在代码中的位置改变而变化 LINE 文件中的当前行号 FILE 文件的完整路径和文件名,包含根目录 DIR 文件所在目录 FUNCTION 该函数被定义时的名字,区分大小写 CLASS 该类被定义时的名字,区分大小写 NAMESPANCE 命名空间 METHOD 命名空间类名方法名 TRAIT 当前使用的trait的名字 包含文件 include和require的区别 include和require除了错误处理的方式不同,其他方面都是相同的。 require生成一个致命错误(E_COMPILE_ERROR),在错误发生后脚本停止运行 include生成一个警告(E_WARNING),在错误发生后脚本继续运行 面向对象(OO) 概念 面向对象是一种编程思想和方法,它将程序中的数据和操作数据的方法封装在一起,形成“对象”,并通过对象之间的交互和消息传递来完成程序的功能。 面向对象编程(OOP)强调数据的封装、继承、多态和动态绑定等特性,使得程序具有更好的可扩展性、可维护性和可重用性。 OOP特性 封装:指将对象的属性和方法封装在一起,使得外部无法直接访问和修改对象的内部状态。通过使用访问控制修饰符(public、private、protected)来限制属性和方法的访问权限,从而实现封装 继承:指可以创建一个新的类该类继承(extends)了父类的属性和方法,并且可以添加自己的属性和方法。通过继承,可以避免重复编写相似的代码,并且可以实现代码的复用。 多态:指可以使用一个父类类型的变量来引用不同子类类型的对象,从而实现对不同对象统一操作。多态可以使得代码更加灵活,具有更好的可扩展性和可维护性。在PHP中多态可通过实现接口(interface)和使用抽象类(abstract class)来实现。 类的访问控制 public(公有):公有的类成员可以在任何地方被调用。 protected(受保护):受保护的类成员可以被其自身以及其子类和父类访问。 private(私有):私有的类成员只能被其定义所在的类访问 构造方法 __construct 构造方法是一种特殊的方法,在创建一个新对象时,它会被自动调用 他可以用来 初始化 对象的属性或执行其他必要的操作 没有返回值 析构函数 __destruct...

February 18, 2024 · 2 min · Leanku

对进程、线程和协程的理解

对进程、线程和协程的理解 一、 进程 先来了解一下操作系统的进程: 操作系统对正在运行程序的抽象,这个就是进程(process)。 比如运行一个 web 浏览器,一个 text 文本,都是运行的一个一个进程。 有的人说:进程是程序运行资源的集合。进程是系统资源分配的最小单位等等。 从静态的角度来说,进程确实是运行程序的各种资源集合。 如果你进一步思考,进程里的各种资源都有哪些呢? 内存管理相关 文件系统 调度相关 信号处理 内核栈 进程各种状态 进程运行时统计信息 进程标识 等等。 可以看出,进程中的资源是相当多的。 从 Linux 操作系统对进程的定义也可以看出。 多进程:操作系统有多个程序运行,那么就有多个进程 二、 线程 《操作系统设计与实现》里说: 在传统操作系统中,每个进程中只存在一个地址空间和一个控制流(thread)。 然后,有些情况下,需要在相同地址空间中有多个控制流并行的运行,就像他们是单独的进程一样(只是他们共享相同的地址空间)。 这些控制流通常被称为线程(thread),有时也称为轻量级进程(lightweight process)。 尽管线程必须在进程中执行,但是线程和进程是可以分别对待处理的两个概念。进程用来集合资源,而线程是 CPU 调度的实体。 线程给进程模型增加的是,允许在同一个进程环境中有多个执行流,这些执行流在很大程度上相对独立。 也即是说,在进程中,程序执行的最小单位(执行流)是线程,可以把线程看作是进程里的一条执行流。 一个进程里可以有一条或多条线程。 为什么会有多线程 在一个应用程序执行过程中,应用程序里可能会有多种事件执行。 而有些事件执行一段时间后可能会被阻塞。如果把应用程序执行事件分解成多个并行运行的线程,即可以让程序设计变得简单,如果有阻塞的, 可以把这部分让出行换其他线程执行。 还有一个原因是: 线程比进程更轻量级。所以线程比进程更加容易创建,销毁。 第三个跟第一个有点关系,是关于性能的,若多线程都是 CPU 密集型的,那么不能获取性能上增强。如果有大量计算和大量 I/O 处理,那么 多线程就可以获取性能上的优势,因为允许多线程重叠执行。 多线程的缺点: 对于多线程来说,进程中的资源是共享的,所以会产生资源竞争。 当进程中的一个线程崩溃了,会导致这个进程里的其他线程也崩溃。所以有时多进程程序更好,一个进程崩溃不会导致其他进程也崩溃。 三、 进程和线程的区别 从上面进程和线程介绍知道,线程是程序执行流的最小单位,进程是操作系统分配资源的单位。 进程与进程之间关系: 进程与进程之间是相互独立的。 线程与进程关系: 线程是进程里的执行流,进程里的线程可以是一个,也可以是多个。 所有线程共享进程里一些资源,比如代码,数据,地址空间,信号处理,打开文件,全局变量等。 同时,线程也有自己的寄存器,程序计数器,堆栈,线程状态等 四、协程 协程是建立在线程之上,一般是语言级别的 ”多线程“ 模型,比线程更加的轻量级。有的叫它微线程。它是完全运行在用户态里。 协程是在线程之上在进行抽象,它需要线程来承载运行。一个线程可以有多个协程。 协程的优点:...

February 18, 2024 · 1 min · Leanku

PHP的 FPM 和 CLI

PHP的 FPM 和 CLI PHP-FPM PHP-FPM 即 PHP FastCGI 进程管理器。 要了解 PHP-FPM ,首先要看看 CGI 与 FastCGI 的关系。 CGI 的英文全名是 Common Gateway Interface,即通用网关接口,是 Web 服务器调用外部程序时所使用的一种服务端应用的规范。 早期的 Web 通信只是按照客户端请求将保存在 Web 服务器硬盘中的数据转发过去而已,这种情况下客户端每次获取的信息也是同样的内容(即静态请求,比如图片、样式文件、HTML文档),而随着 Web 的发展,Web 所能呈现的内容更加丰富,与用户的交互日益频繁,比如博客、论坛、电商网站、社交网络等。 这个时候仅仅通过静态资源已经无法满足 Web 通信的需求,所以引入 CGI 以便客户端请求能够触发 Web 服务器运行另一个外部程序,客户端所输入的数据也会传给这个外部程序,该程序运行结束后会将生成的 HTML 和其他数据通过 Web 服务器再返回给客户端(即动态请求,比如基于 PHP、Python、Java 实现的应用)。利用 CGI 可以针对用户请求动态返回给客户端各种各样动态变化的信息。 FastCGI 顾名思义,是 CGI 的升级版本,为了提升 CGI 的性能而生,CGI 针对每个 HTTP 请求都会 fork 一个新进程来进行处理(解析配置文件、初始化执行环境、处理请求),然后把这个进程处理完的结果通过 Web 服务器转发给用户,刚刚 fork 的新进程也随之退出,如果下次用户再请求动态资源,那么 Web 服务器又再次 fork 一个新进程,如此周而复始循环往复。 而 FastCGI 则会先 fork 一个 master 进程,解析配置文件,初始化执行环境,然后再 fork 多个 worker 进程(与 Nginx 有点像),当 HTTP 请求过来时,master 进程将其会传递给一个 worker 进程,然后立即可以接受下一个请求,这样就避免了重复的初始化操作,效率自然也就提高了。而且当 worker 进程不够用时,master 进程还可以根据配置预先启动几个 worker 进程等着;当空闲 worker 进程太多时,也会关掉一些,这样不仅提高了性能,还节约了系统资源。 这样一来,PHP-FPM 就好理解了,FastCGI 只是一个协议规范,需要每个语言具体去实现,PHP-FPM 就是 PHP 版本的 FastCGI 协议实现,有了它,就是实现 PHP 脚本与 Web 服务器(通常是 Nginx)之间的通信,同时它也是一个 PHP SAPI,从而构建起 PHP 解释器与 Web 服务器之间的桥梁。 PHP-FPM 负责管理一个进程池来处理来自 Web 服务器的 HTTP 动态请求,在 PHP-FPM 中,master 进程负责与 Web 服务器进行通信,接收 HTTP 请求,再将请求转发给 worker 进程进行处理,worker 进程主要负责动态执行 PHP 代码,处理完成后,将处理结果返回给 Web 服务器,再由 Web 服务器将结果发送给客户端。这就是 PHP-FPM 的基本工作原理。...

February 17, 2024 · 1 min · Leanku