php 模式是使用的 php-fpm 模式
比如用户正在请求响应,这时候我更新了代码。会不会对正在请求响应产生影响
问了我老大,他说不会。 让我了解 web 的工作原理
这里我就想问下,大家 这个没想明白
1
imdong 2019-09-19 18:05:18 +08:00
答:不会。
如果对工作原理懂了,都不会这么问了。 简单的说,用户 -> Nginx -> php-fpm ( read php file -> run code ) -> Nginx -> 用户 你更改 php 文件的时候,只要 fpm 执行中,就不会出现问题。 因为不是边执行边读取,而是读取以后再执行,读取文件是瞬时完成的,修改和读取不会同时(系统保证) |
2
toyuanx 2019-09-19 18:13:21 +08:00
可以看下这篇文章: https://blog.csdn.net/IT_10/article/details/95387481
"可以看到一旦 kill 掉 worker 进程后,会重启一个新的 worker 进程。因此客户端请求肯定会得到响应处理。这进一步验证了的上面的结论,master 进程负责监听子进程的状态,子进程挂掉之后,会发信号给 master 进程,然后 master 进程重新启一个新的 worker 进程。" 正常来说上线的时候对用户是有有影响的,但是如果上线的时间够快,可能影响就比较少 |
3
lincanbin 2019-09-19 18:15:03 +08:00 via Android
你去 Google 搜一下,关键字:php-fpm 平滑重启
|
4
lp7631010 2019-09-19 18:17:40 +08:00 via iPhone
人家问的是更改 php 文件吧 跟 fpm 重启啥的有什么关系呢
|
5
awanganddong OP |
6
awanganddong OP |
7
ben1024 2019-09-19 18:30:23 +08:00
每个进程在运行时已经把代码加载到对应的内存中,每个进程使用的内存是独立的,不会相互干扰
|
8
mcfog 2019-09-19 18:35:23 +08:00
是否有影响影响多少用户多少时间取决于你们的部署流程是否正确
能否观测、监控到这种影响取决于你们的基础设施是否完善 一个很基本简单的方法论:如果你要修复或者改进一个问题,就必须先确保你能够观测、重现或测量它,否则你做的一切改进都是没有意义的。在建立了观测手段以后,减少更新代码对用户的影响这种属于常规基础的问题,找一些实践跟着做就行,很容易降到 0 或者可以忽略的程度的。 基于你其实并没有说你们的情况,所以这里即使说了一些实践做法的人也都只是随意说一些常见的可以做的事情而已 |
9
CODEWEA 2019-09-19 19:13:00 +08:00 7
答案:会 和 不会取决你如何更新代码。
你如果是用 svn git 那种覆盖式的更新,大概率是会因为文件依赖而遇到问题。 为什么会出现问题? 首先,你的 PHP 项目不可能就一个文件吧,比如你上一个版本 UserService 引入了 MailClass,但是你下一个版本中在 UserService 把 MailClass 删除了,如果你使用覆盖式更新时,如果 MailClass 完成更新删除了,但是 UserService 还没有更新,此时一个请求来了,并不会一次性把你 PHP 项目所有文件载入进去,当文件依赖出问题,你网站直接就 5XX 了 如何不出问题呢? 问题的关键就在于你改动 php 项目时,文件的依赖会发生变化,如果项目文件正处于变化时,文件依赖是处于混乱状况的,此时如果一个请求过来,你项目就 5XX 了。 解决办法: 1.更新代码时,阻断外部请求,将所有请求重定向到与这个项目无关的维护页面。 2.nginx 配置 2 个项目,一个为新,一个为旧的,当你新的更新完毕同时内部测试无误后,切换 nginx 的配置文件,切换到新的。 解决的的核心逻辑是不要在你 php 项目中文件发生变化时运行外部程序请求访问。 |
10
zhangtao 2019-09-19 19:20:24 +08:00
太多人喜欢不懂装懂了
|
11
CODEWEA 2019-09-19 19:32:25 +08:00
你老大说的:不会,应该是理想状态,或者说 php 项目中就一个 php 文件
|
12
jsjscool 2019-09-19 19:52:53 +08:00 4
先说答案,会有影响,但是发生的概率极低。
简单理解 PHP 的执行流程是这样的: 1. 扫描所有 PHP 文件,并转换成 Token (语言片段) 2. 解析编译 Token 得到 Opocdes 3. 执行 Opocdes 第一步扫描所有 PHP 文件时会将 include,require 等的代码一起加到内存,速度非常快,如果此时更新代码是有可能影响当前请求的。 如果请求进入到 1 之后的阶段,更新代码是不会对正在进行的请求有影响,因为用户的请求是独立的进程,独立的内存空间,内存里面的代码是请求到达 php-fpm 进程时那一刻的快照。 如何避免: 现在发布 PHP 代码都用 CI,CI 的实现方式不是 update 代码,而是每次创建一个新文件夹,全量拷贝代码,再修改软链接。如果使用类似方式发布代码的话就如你老大所说,不会影响用户请求。 |
13
kx5d62Jn1J9MjoXP 2019-09-19 20:03:51 +08:00 via Android
不管会不会,和 web 都一毛钱关系没有啊,应该和多个文件的写 /读有关。如果你们是像我待的那种公司一样用 ftp 传 PHP 文件的,ftp 和操作系统又不像数据库那样保证多个文件的上传为事务操作啊?
|
14
wshcdr 2019-09-19 20:05:05 +08:00
会的啊
|
16
zsen 2019-09-19 20:16:13 +08:00 via iPhone
同时考虑一下 php.ini 中的 opcache ?
|
19
akira 2019-09-19 23:54:12 +08:00
从原理上讲,单一文件肯定是不会。
但是 不管会不会 , 更新发版的时候 截断请求是个好习惯. |
20
x86 2019-09-20 00:51:34 +08:00
细说的话看你动什么文件了
|
21
lihongming 2019-09-20 01:03:32 +08:00 via iPhone
你要是一个文件一个文件的更新,难免会出现用户访问的文件一部分新一部分旧的问题。要是还改了数据库,那就不可避免会出错。
所以我们都是把 PHP 等后端系统放在容器或虚拟机里,一更新就是整个系统,然后在前端 nginx 切换一下就行了。 |
22
ladypxy 2019-09-20 06:30:02 +08:00 via iPhone
这么久了居然都没人提到 opcache.revalidate_freq。这就专门针对更新的设置
|
23
awanganddong OP 现在已经知道对于我提到的问题的解决方案有两种,
一种是 nginx 进行切换 一种是 ci 的自动发布 |
24
lihongjie0209 2019-09-20 10:28:39 +08:00
情况有很多, 简单来讲: 不会
用户正在进行的请求就意味着 php 代码已经被加载的内存中执行了(进程), 这个时候你更新程序, 是不会影响到进程的。 复杂点讲, 可能会: 用户正在进行的请求就意味着 php 代码已经被加载的内存中执行了(进程),这个进程然后去加载其他的代码, 而你在更新其他代码, 那么就会可能导致一些问题, 如: 1. 代码不兼容, 原来是方法 A, 现在改为方法 B, 当然会报错 2. 代码不完整, 取决于你的更新方式, 当前你的文件数据可能是不完整的, 比如说 1K 的文件当前只传输了 0.5K , 这时候你去读取文件, 就会直接报错。 这个问题其实和 PHP 没什么关系, 更多是操作系统中进程和文件系统的一些相关知识。 |
26
laminux29 2019-09-20 11:44:22 +08:00
不管会不会,你这种做法就是不对的。正确的操作应该像 9 楼 [CODEWEA] 说的那样。
这种事情的本质是事务问题,你想了解详情的话,可以翻翻数据库、分布式系统的书籍,里面会有关于这个问题的阐述。 |
27
awanganddong OP @lihongjie0209 对的,实际上公司代码是通过 jenkins 全量覆盖。然后更新过程中,出现不正常,继而引发对这个问题的探讨。
这个问题,也确实不单单 php 会遇到,包括其他中语言也是一样,可能方式不一样。 |
28
lihongjie0209 2019-09-20 14:40:55 +08:00
@awanganddong #27 如果做不到多节点负载, 一个节点一个节点的更新, 那最好就是先把 Nginx 关闭再更新
|