V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
awanganddong
V2EX  ›  PHP

PHP 代码更新的时候会不会中断用户正在进行的请求及响应

  •  3
     
  •   awanganddong · 2019-09-19 17:59:22 +08:00 · 6222 次点击
    这是一个创建于 1652 天前的主题,其中的信息可能已经有所发展或是发生改变。

    php 模式是使用的 php-fpm 模式

    比如用户正在请求响应,这时候我更新了代码。会不会对正在请求响应产生影响

    问了我老大,他说不会。 让我了解 web 的工作原理

    这里我就想问下,大家 这个没想明白

    28 条回复    2019-09-20 14:40:55 +08:00
    imdong
        1
    imdong  
       2019-09-19 18:05:18 +08:00
    答:不会。

    如果对工作原理懂了,都不会这么问了。

    简单的说,用户 -> Nginx -> php-fpm ( read php file -> run code ) -> Nginx -> 用户

    你更改 php 文件的时候,只要 fpm 执行中,就不会出现问题。

    因为不是边执行边读取,而是读取以后再执行,读取文件是瞬时完成的,修改和读取不会同时(系统保证)
    toyuanx
        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 进程。"

    正常来说上线的时候对用户是有有影响的,但是如果上线的时间够快,可能影响就比较少
    lincanbin
        3
    lincanbin  
       2019-09-19 18:15:03 +08:00 via Android
    你去 Google 搜一下,关键字:php-fpm 平滑重启
    lp7631010
        4
    lp7631010  
       2019-09-19 18:17:40 +08:00 via iPhone
    人家问的是更改 php 文件吧 跟 fpm 重启啥的有什么关系呢
    awanganddong
        5
    awanganddong  
    OP
       2019-09-19 18:19:37 +08:00
    @imdong 你说的最后一句,可以稍微解答我的困惑,但是就是太简略了。

    @toyuanx nginx 的热加载和 php-fpm 的热加载 master-worker 这种模式我也知道。包括多进程间内存是隔离的。


    但是隐约感觉没有一语中的。
    awanganddong
        6
    awanganddong  
    OP
       2019-09-19 18:27:21 +08:00
    https://t.ti-node.com/thread/6528965533792993280

    这是一个大佬的笔记


    apue 我需要连接下了
    ben1024
        7
    ben1024  
       2019-09-19 18:30:23 +08:00
    每个进程在运行时已经把代码加载到对应的内存中,每个进程使用的内存是独立的,不会相互干扰
    mcfog
        8
    mcfog  
       2019-09-19 18:35:23 +08:00
    是否有影响影响多少用户多少时间取决于你们的部署流程是否正确
    能否观测、监控到这种影响取决于你们的基础设施是否完善

    一个很基本简单的方法论:如果你要修复或者改进一个问题,就必须先确保你能够观测、重现或测量它,否则你做的一切改进都是没有意义的。在建立了观测手段以后,减少更新代码对用户的影响这种属于常规基础的问题,找一些实践跟着做就行,很容易降到 0 或者可以忽略的程度的。

    基于你其实并没有说你们的情况,所以这里即使说了一些实践做法的人也都只是随意说一些常见的可以做的事情而已
    CODEWEA
        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 项目中文件发生变化时运行外部程序请求访问。
    zhangtao
        10
    zhangtao  
       2019-09-19 19:20:24 +08:00
    太多人喜欢不懂装懂了
    CODEWEA
        11
    CODEWEA  
       2019-09-19 19:32:25 +08:00
    你老大说的:不会,应该是理想状态,或者说 php 项目中就一个 php 文件
    jsjscool
        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 代码,而是每次创建一个新文件夹,全量拷贝代码,再修改软链接。如果使用类似方式发布代码的话就如你老大所说,不会影响用户请求。
    ssynhtn
        13
    ssynhtn  
       2019-09-19 20:03:51 +08:00 via Android
    不管会不会,和 web 都一毛钱关系没有啊,应该和多个文件的写 /读有关。如果你们是像我待的那种公司一样用 ftp 传 PHP 文件的,ftp 和操作系统又不像数据库那样保证多个文件的上传为事务操作啊?
    wshcdr
        14
    wshcdr  
       2019-09-19 20:05:05 +08:00
    会的啊
    CODEWEA
        15
    CODEWEA  
       2019-09-19 20:09:02 +08:00
    @jsjscool 不是吧? include require 是否真的引入文件还是根据你逻辑来的啊
    zsen
        16
    zsen  
       2019-09-19 20:16:13 +08:00 via iPhone
    同时考虑一下 php.ini 中的 opcache ?
    crynocry
        17
    crynocry  
       2019-09-19 20:40:10 +08:00
    @imdong 同一个文件可以保证。 可是替换代码是批量替换,会出现有一部分老代码一部分新代码的情况么
    jsjscool
        18
    jsjscool  
       2019-09-19 23:20:25 +08:00
    @CODEWEA 我这里描述有误 ,从扫描文件到执行在多文件下是串行的不是并行。
    akira
        19
    akira  
       2019-09-19 23:54:12 +08:00
    从原理上讲,单一文件肯定是不会。
    但是
    不管会不会 , 更新发版的时候 截断请求是个好习惯.
    x86
        20
    x86  
       2019-09-20 00:51:34 +08:00
    细说的话看你动什么文件了
    lihongming
        21
    lihongming  
       2019-09-20 01:03:32 +08:00 via iPhone
    你要是一个文件一个文件的更新,难免会出现用户访问的文件一部分新一部分旧的问题。要是还改了数据库,那就不可避免会出错。

    所以我们都是把 PHP 等后端系统放在容器或虚拟机里,一更新就是整个系统,然后在前端 nginx 切换一下就行了。
    ladypxy
        22
    ladypxy  
       2019-09-20 06:30:02 +08:00 via iPhone
    这么久了居然都没人提到 opcache.revalidate_freq。这就专门针对更新的设置
    awanganddong
        23
    awanganddong  
    OP
       2019-09-20 09:26:55 +08:00
    现在已经知道对于我提到的问题的解决方案有两种,
    一种是 nginx 进行切换
    一种是 ci 的自动发布
    lihongjie0209
        24
    lihongjie0209  
       2019-09-20 10:28:39 +08:00
    情况有很多, 简单来讲: 不会

    用户正在进行的请求就意味着 php 代码已经被加载的内存中执行了(进程), 这个时候你更新程序, 是不会影响到进程的。


    复杂点讲, 可能会:
    用户正在进行的请求就意味着 php 代码已经被加载的内存中执行了(进程),这个进程然后去加载其他的代码, 而你在更新其他代码, 那么就会可能导致一些问题, 如:

    1. 代码不兼容, 原来是方法 A, 现在改为方法 B, 当然会报错
    2. 代码不完整, 取决于你的更新方式, 当前你的文件数据可能是不完整的, 比如说 1K 的文件当前只传输了 0.5K , 这时候你去读取文件, 就会直接报错。


    这个问题其实和 PHP 没什么关系, 更多是操作系统中进程和文件系统的一些相关知识。
    ETO
        25
    ETO  
       2019-09-20 11:19:38 +08:00
    @lp7631010 道理一样的。
    laminux29
        26
    laminux29  
       2019-09-20 11:44:22 +08:00
    不管会不会,你这种做法就是不对的。正确的操作应该像 9 楼 [CODEWEA] 说的那样。

    这种事情的本质是事务问题,你想了解详情的话,可以翻翻数据库、分布式系统的书籍,里面会有关于这个问题的阐述。
    awanganddong
        27
    awanganddong  
    OP
       2019-09-20 14:05:10 +08:00
    @lihongjie0209 对的,实际上公司代码是通过 jenkins 全量覆盖。然后更新过程中,出现不正常,继而引发对这个问题的探讨。

    这个问题,也确实不单单 php 会遇到,包括其他中语言也是一样,可能方式不一样。
    lihongjie0209
        28
    lihongjie0209  
       2019-09-20 14:40:55 +08:00
    @awanganddong #27 如果做不到多节点负载, 一个节点一个节点的更新, 那最好就是先把 Nginx 关闭再更新
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3156 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 13:02 · PVG 21:02 · LAX 06:02 · JFK 09:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.