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

PHP 编译器 BPC 编译实战: workerman/GatewayWorker

  •  2
     
  •   heguangyu5 · 326 天前 · 2116 次点击
    这是一个创建于 326 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不了解 BPC 是什么的可以翻看之前的贴子.

    简言之,BPC 可以将 PHP 代码最终转译成 C 语言,然后编译成动态链接库或者可执行程序,实现 PHP Native AOT.

    how BPC works

    1. 背景

    最近在做一个招聘求职类的项目,B 端 HR 使用的是云招 OurATS 招聘管理系统,C 端求职者使用的是微信小程序.

    HR 在 B 端创建的职位会显示在微信小程序上,求职者在小程序上可以浏览职位信息,就某职位和 HR 在线聊天沟通.

    求职者投递简历后,也可以就此次投递和 HR 在线聊天沟通.

    其中在线聊天功能是基于 workerman/GatewayWorker 实现的.

    整个项目(OurATS+小程序后端+在线聊天)都使用 PHP 开发,交付给客户时,经 BPC 编译成.so 和 elf 可执行文件部署到客户的服务器上.

    虽然之前就尝试着编译过 workerman,但毕竟不是真刀真枪的项目,$eventLoopClass用的还是Select.

    借着这个在线聊天的机会,BPC 实现了event(core)扩展,针对 BPC 调整了部分 workerman/GatewayWorker 的代码,把 BPC 编译版本的 workerman/GatewayWorker 推向生产环境.

    2. PHP 编译器 BPC 用前须知

    1. BPC target 的目标是 php 7.2, 更精确地说是 php 7.2.19
    2. 测试用例参看 bpc-php-7.2.19-tests
    3. BPC 不支持的语法特性可以使用 phptobpc 进行转换,如果 phptobpc 也不支持,那就只能修改你的代码或者等待 BPC 升级了.
    4. BPC 当前不支持的扩展一般不是大问题,因为 BPC 的扩展开发是比较容易的.
    5. 目前 BPC 及其编译产物仅在 ubuntu 18.04 amd64 上完善测试过,在其它 linux 发行版上有可能能运行,大概率会遇到问题.但这并不是说 BPC 无法在其它发行版上运行,我曾在自己的 CubieBoard 7 上的 debian stretch 系统下成功编译并跑通了 phpt 测试.

    3. BPC 支持编译的 workerman/GatewayWorker 版本

    workerman

    workerman 在 5.0 新版本中引入了 Typed Properties 特性. 也就是如下代码:

    class Worker 
    {
        public int $id = 0; // 注意 public 和 $id 中间的 int
    }
    

    BPC 目前不支持这一特性,所以不支持编译 workerman 5.0 版本.

    BPC 当前调整好的,可以编译,基本测试没问题的版本是 workerman 4.1 版本.

    Gatewayworker

    GatewayWorker master 分支引入了 class method 的返回类型.也就是如下代码:

    class BusinessWorker extends Worker
    {
        public function run(): void // 注意 run() 后边的 : void
        {}
    }
    

    BPC 目前不支持这一特性,所以不支持编译 GatewayWorker master 分支.

    BPC 当前调整好的,可以编译,基本测试没问题的版本是 GatewayWorker 3.x 分支.

    4. 为了能够成功编译,需要对 workerman/GatewayWorker 源码做哪些调整?

    workerman

    1. 在编译的场景下, __DIR__ 的语义发生了变化,所以涉及到读写文件的__DIR__都需要调整一下.

    2. BPC 不支持STREAM_CLIENT_ASYNC_CONNECT, 所以不能用 AsyncTcpConnection.php.我写了一个 SyncTcpConnection.php 来替代 AsyncTcpConnection.php,两者的区别在于最开始建立连接是同步还是异步,其它都一样.

    3. BPC 实现的__destruct()不适用于 workerman 这种需要长时间运行的程序,所以有 __destruct() 方法的类都做了调整.

    4. BPC 实现的 event 扩展对于长期运行的程序需要手动 free event,所以对Events/Event.php做了调整.

    大的调整就这 4 点,具体细节可以查看 github commits.

    GatewayWorker

    1. 用到 AsyncTcpConnection 的地方都换成了 SyncTcpConnection

    2. BPC 不支持class_alias, 所以代码中的 class_alias('GatewayWorker\Protocols\GatewayProtocol', 'Protocols\GatewayProtocol'); 都去掉了,需要在自己的项目里加一个如下的 class.

      <?php
      namespace Protocols;
      class GatewayProtocol extends \GatewayWorker\Protocols\GatewayProtocol
      {}
      
    3. BPC 实现的 pdo 扩展对于长期运行的程序需要明确的调用 $pdo->closeConnection()$stmt->destroy(), 所以对 src/Lib/DbConnection.php 做了调整.

    大的调整就这 3 点,具体细节可以查看 github commits.

    5. 怎么编译 workerman 4.1 和 GatewayWorker 3.x ?

    1. 首先需要安装 bpc-compilerphptobpc

    2.  git clone [email protected]:bob-php-compiler/bpc-workerman-4.1-branch.git
       cd bpc-workerman-4.1-branch
       make
       cd Workerman
       sudo bpc -l workerman --install
      
    3.  git clone [email protected]:bob-php-compiler/bpc-GatewayWorker-3.x-branch.git
       cd bpc-GatewayWorker-3.x-branch/src
       make
       cd ../GatewayWorker
       sudo bpc -l gatewayworker --install
      

    现在 workerman 和 gatewaywoker 已经被编译成 .so 和 .a 并安装到 /usr/local/lib 目录下了.

    接下来在编译 workerman 和 GatewayWorker 应用时只需要给 bpc 加上 -u workerman -u gatewayworker 就可以了.

    关于 BPC 的高级用法请看 Wiki: 05_Advanced_usage.

    6. 在 BPC Playground 里立即尝试

    https://bpc.dev Try it online (BPC Playground) 里已经加上了 workerman 和 GatewayWorker 示例.

    不想自己安装编译环境的可以使用这个 online compiler 立即尝试编译 workerman 和 GatewayWorker 应用.

    workerman.png

    GatewayWorker.png

    28 条回复    2023-06-08 21:57:53 +08:00
    veike
        1
    veike  
       326 天前
    PHP8.0 年底停止维护,7.4 已经停止维护。PHP 维护周期太短了,新版本大部人都没开始用呢,就又得升级了。
    IdJoel
        2
    IdJoel  
       326 天前   ❤️ 2
    不开源谁敢用
    zjsxwc
        3
    zjsxwc  
       326 天前
    @veike
    我还在维护的老项目有 7.0 7.1 7.2 , 老项目不会去升级 php 版本,最多升级小数点后第三位小版本。
    alanying
        4
    alanying  
       326 天前
    @veike 有 LTS 组织维护旧版本的。只是不添加新的 feature 了
    heguangyu5
        5
    heguangyu5  
    OP
       326 天前
    @IdJoel 也不知道 zend guard, ioncube, swoole compiler 有没有客户
    IdJoel
        6
    IdJoel  
       326 天前
    @heguangyu5 主要也没有大企业做背书,基本上也算是个人维护的项目,别人用你这个只敢做玩具,万一你哪天失去兴趣不弄了呢? 万一有个 BUG 联系不到你呢
    lifeintools
        7
    lifeintools  
       326 天前
    @heguangyu5 swoole compiler 我有一个项目 付费使用了
    heguangyu5
        8
    heguangyu5  
    OP
       326 天前
    @IdJoel 10 多年前就有人说我们公司是个皮包公司,过不了几天就挂了,现在我们还活的好好的,他们却挂了.

    另外大企业有法务,人家不需要这东西.
    heguangyu5
        9
    heguangyu5  
    OP
       326 天前
    @lifeintools 所以源码保护的需求是有的,BPC 转译的方案可以 100%保护源码,license 机制可以实现强有力的软件授权.

    我们自己也正是有这样的需求,才开发了 BPC.

    当然 BPC 和 PHP 只能做到高度兼容,不能 100%兼容,毕竟 BPC 相当于重新实现了 PHP.
    mengdodo
        10
    mengdodo  
       326 天前
    加油
    IdJoel
        11
    IdJoel  
       326 天前
    Echoldman
        12
    Echoldman  
       326 天前
    为啥是 7.2.19 这个版本呢
    veike
        13
    veike  
       326 天前
    @alanying 哪个 LTS 组织,会推到官方维护的分支吗,还是我得编译安装呢
    heguangyu5
        14
    heguangyu5  
    OP
       326 天前
    @Echoldman 因为当时刚开始开发 BPC 的时候,用的是 ubuntu 18.04,而 ubuntu 18.04 上默认的 php 版本就是 php 7.2.19.
    alanying
        15
    alanying  
       326 天前
    @veike PHP 的母公司 Zend 一直有维护 Zend PHP LTS 。 然后 CloudLinux 也有维护旧版本 PHP ,连 php4 人家都可以支持。
    zengzizhao
        16
    zengzizhao  
       326 天前
    加油
    loudefa
        17
    loudefa  
       326 天前
    @veike 那我说好多系统都是停留在 5.3 时代咋说。。。也不是非得升级,又不是不能用。现在大部分还是 7.x 的版本吧
    veike
        18
    veike  
       326 天前
    @alanying Zend 长期支持的 PHP 版本是免费的还是收费的,会不会更新到各大 linux 分支的仓库里,是不是需要编译安装?我看 PHP 官网的支持周期,7.4 已经结束了,8.0 今年年底结束。
    https://www.php.net/supported-versions.php
    8355
        19
    8355  
       326 天前
    以前没用过,
    最近用了下 webman/workerman/GatewayWorker 性能全都很强.
    老 laravel 项目 tp 项目迁移无敌
    性能完全秒杀 laravel 不过需要开发者有自己造轮子能力, 不然还是有点难受.

    支持下楼主 国内现代 phpWeb 只有 hyperf 和 webman 其他的真的都不值得做了.
    dzdh
        20
    dzdh  
       326 天前
    @veike #18 cloudlinux 的不免费。cloudlinux 算 RPM 系。在 rhel/centos/alma/rocky 等基于 rhel 的发行版,可以用 remi ,在 rhel8.x 及其衍生版 8.x 下,remi 支持 php 最低到 php5.6.

    debian/ubuntu 可以参考 https://packages.sury.org/php 也是最低支持到 5.6
    8355
        21
    8355  
       326 天前
    @veike #1 8.0 本质上就不是一个很值得升级的版本.

    7.*最好的升级版本目前看是 8.1
    基本性能有 10-20%的提升
    又增加新特性.非常好用
    brader
        22
    brader  
       326 天前
    @veike 这点我感觉 PHP 已经是一股清流了,去看看 node 、go 等等,哪家不是版本发布到几十了,哈哈,更新的更快
    dzdh
        23
    dzdh  
       326 天前
    veike
        24
    veike  
       326 天前
    @8355 8.0 还是一个值得升级的版本,里面有很多值得升级的新语法,并且我也不是在讨论性能,10-20%的计算性能提升并没有多少吸引力。主要是随着 PHP7.x 版本停止维护,很多依赖也会停止对 PHP7.x 的支持。其他人说的某些组织在维护低版本的 PHP ,对于大部分使用者没有意义,信息触及不到,而且也不会去折腾。总之是官方已经不支持了,该革新还是要革新。看到评论对于 PHP7.x 停止安全更新没有任何感觉,我真是诧异。
    0o0O0o0O0o
        25
    0o0O0o0O0o  
       326 天前 via iPhone
    印象中 OP 这个坚持开发了两三年了
    veike
        26
    veike  
       326 天前
    我真心希望 op 别搞 PHP 转译 C 语言了,PHP 没啥搞头,日薄西山。不如换个方向研究,研究一下如何把自然语言转为各种各类主流编程语言,这个好玩多了。
    heguangyu5
        27
    heguangyu5  
    OP
       325 天前
    @0o0O0o0O0o

    今年是 BPC 编译器开发的第三年,如果不想着追赶 PHP 版本升级的话,编译器自身已经相当稳健了.
    BPC 的重点在于它改变了 PHP 项目的交付方式,完善解决了源码保护和软件授权的问题.

    @veike

    我个人是非常喜欢 PHP Scheme 这种弱类型语言的,对强类型语言没什么兴趣.
    再说做一个项目只是单纯玩玩很难持续下去.BPC 即使不推广商用,仅在我们公司内部,也有足够的应用场景,这样才能持续搞下去.
    happy321
        28
    happy321  
       316 天前 via iPhone
    @heguangyu5 你们公司内部项目 用的 PHP 什么框架啊?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1169 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 18:16 · PVG 02:16 · LAX 11:16 · JFK 14:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.