PHP代码的解析过程

2019-11-06 11:47:59 浏览数 (1)

城边编程 phplog

读完需要8分钟

速读仅需4分钟

又有一周没更新了,也没人催更,决定主动更新一篇。

这段时间国家开始推行『区块链』,央行也即将发行数字货币DCEP(Digital Currency Electronic Payment)。这个数字货币对支付宝和微信支付不会有太大的影响,他们两家加起来那点份额对央行来说就是毛毛雨,不过云闪付可能会退位让贤。

这不是重点,重点是国家已经规划在多个领域应用区块链技术。强调要探索“区块链 ”在民生领域的应用,积极推动区块链技术在教育、就业、养老、精准脱贫、医疗健康、商品防伪、食品安全、公益、社会救助、政务等领域的应用。对于程序员来说这又是一个挣零花钱的好机会,这是一个最好的时代。

国家十三五规划(2016-2020)给腾讯和阿里都分了任务,腾讯主管智慧医疗、警务、政务。阿里主管云计算、大数据、工业。2020年马上要交卷了,两家企业做的都不错,特别是阿里。马上要十四五规划,看区块链技术花落谁家,我没猜错的话应该会是阿里牵头。所以小程序也是未来5年的一个爆发点。

正文

问:PHP代码更新的时候会不会中断用户正在进行的请求?

答:会,但有办法防止这种情况出现。

PHP属于热更新语言,在不开Opcache缓存的情况下修改代码能实时生效,因为这个灵活的特性也导致PHP在发布代码时容易遇到问题,这点和前端资源的发布很像。前端需要保证多个js和css文件更新后同时生效,但是文件更新肯定会有先后顺序,存在时间差,如何处理时间差带来的风险也是值得深究的话题。主要有如下问题:文件的更新顺序导致用户请求出错。

a.php -> b.php -> c.php

有如上调用流程,在更新b和c文件时,凑巧用户请求刚加载完更新后的b文件,此时如果c文件还在更新中,就会导致顺序出错,变成如下情况。

a.php -> 新 b.php -> c.php

对用户来说这次请求多半会报错。如果当前请求有I/O操作更会造成灾难性的后果。

这里说了"可能"、"如果"、"凑巧"三个概率性的词,在编程时千万不要相信概率,请迷信墨菲定律。

PHP是如何解析执行的?

1. Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)

2. Parsing, 将Tokens转换成简单而有意义的表达式,再通过Bison转换成ZendAPI

3. Compilation, 将表达式编译成Opocdes

4. Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。

文件加载到内存后,无论怎么修改文件都不会影响当次请求。所以只要知道include的PHP文件是什么时候被加载到内存的,问题也迎刃而解。

假设我们有两个php文件,内容如下:

代码语言:javascript复制
//a.php
<?php
echo 123;
include "b.php";
?>
//b.php
<?php
echo 456;
?>

1. Scanning(Lexing) 词法分析结果

代码语言:javascript复制
Array
(
    [0] => Array
        (
            [0] => 379
            [1] => <?php
            [2] => 1
        )

    [1] => Array
        (
            [0] => 328
            [1] => echo
            [2] => 1
        )

    [2] => Array
        (
            [0] => 382
            [1] =>  
            [2] => 1
        )

    [3] => Array
        (
            [0] => 317
            [1] => 123
            [2] => 1
        )

    [4] => ;
    [5] => Array
        (
            [0] => 258
            [1] => include
            [2] => 1
        )

    [6] => Array
        (
            [0] => 382
            [1] =>  
            [2] => 1
        )

    [7] => Array
        (
            [0] => 323
            [1] => "b.php"
            [2] => 1
        )

    [8] => ;
)

2. Compilation, 将表达式编译成Opocdes

从Opocdes可以看出此时已经将`b.php`文件加载到了内存,也就是说在PHP代码被转换成Opocdes前已经完成了所有代码的加载。

最后得出结论,如果用户发送的请求在Compilation之前,我们更新代码是会导致服务中断的。

如何解决更新过程中请求中断的问题?

通常会给PHP项目文件夹设置一个软链接。每次更新项目时创建一个新文件夹,然后将PHP项目的全量代码拷贝过去,最后修改软链接指向新文件夹。这样就能保证用户请求不受文件更新的影响。gitlab的CD流程中已经集成该方法。

0 人点赞