如何成功地将Zend Framework 1应用程序从CloudControl Luigi迁移到Pinky stack


How to successfully migrate a Zend Framework 1 application from CloudControl Luigi to Pinky stack?

简单的部分…

通常,当将ZF1应用程序从内置自动加载迁移到基于composer的自动加载时(强烈建议部署在CloudControls Pinky stack上),您只需要执行一些简单的步骤:

创建编曲器。并要求Zend Framework(例如1.12版本的最新版本):

{
    "require" : {
        "zendframework/zendframework1" : "1.12.*"
    }
}

通过命令行安装编译器依赖项:

composer install

更新.gitignore文件并添加:

vendor/*

从库路径中递归删除当前ZF文件夹(例如./library):

rm -r library/Zend

在使用Zend_类之前,在index.php 中添加:

$loader = include 'vendor/autoload.php';

从您的index.php中删除所有现在过时的与ZF相关的requirerequire_once语句-例如,这不再需要了:

require_once 'Zend/Application.php';

一旦你完成了上面的更改,你就像往常一样通过git提交和推送,然后你通过CLI在CloudControl上部署新版本(这里的APP_NAMEDEP_NAME指的是你的应用程序和部署名称):

cctrlapp APP_NAME/DEP_NAME deploy

您将注意到cctrlapp打印出一些关于解析编译器依赖的信息,并最终启动新版本的部署。要检查是否完成,可以运行:

cctrlapp APP_NAME/DEP_NAME log deploy

好的,部署日志看起来很好,让我们打开浏览器!

什么鬼!内部服务器错误?为什么? ?在本地的LA(M)P堆栈下一切都很顺利!!

棘手的部分…

幸运的是,CloudControl还允许我们访问错误日志…

cctrlapp APP_NAME/DEP_NAME log error

应该不难发现这里出了什么问题。

但是…呃…

8/1/14 5:23 AM  error [error] [client ] FastCGI: incomplete headers (0 bytes) received from server "/app/php/box/php-fpm"
8/1/14 5:23 AM  error [error] [client ] (104)Connection reset by peer: FastCGI: comm with server "/app/php/box/php-fpm" aborted: read failed

由于上面的错误信息根本没有帮助,我们首先需要追踪这个bug。这确实很棘手!我们可以谷歌一下。我们可以试试别的办法。然后我们可以重新部署。我们可以再谷歌一下。我们可以试试别的办法。然后我们可以重新部署。我们可以另找时间谷歌一下。我们可以尝试其他方法。我们可以……但是我们想要吗?

幸运的是,Pinky堆栈提供了另一种加快速度的方法(Luigi不是全部)。虽然它仍然包含繁琐的手动调试,但至少我们可以节省一些时间-进入CLI并执行:
cctrlapp APP_NAME/DEP_NAME run bash

CloudControl现在为我们实例化了一个新的容器,并让我们基于SSH shell访问它。正如文档所说,所有内容都应该与部署框中的内容一致:

cloudControl平台的分布式特性意味着它不是可以SSH到实际的服务器。相反,我们提供跑步服务命令,它允许您启动一个新容器并连接到它通过SSH .

容器与web或worker容器相同,但会启动SSH守护进程,而不是Procfile命令之一。这是基于相同的堆栈映像和部署映像还提供附加凭证。

让我们看看是否能(从容器内部)找到更多信息:

cd code/public
php index.php

嗯…这里没有报道…和…日志里什么都没有?!搞什么鬼?!

所以,web和run容器之间似乎有区别——确实有!为了找出这个问题,我立即开始编辑index.php:

vi index.php

过了一会儿,我终于重现了至少另一个错误:

8/1/14 8:55 AM  error [error] [client ] FastCGI: server "/app/php/box/php-fpm" stderr: PHP message: PHP Fatal error:  require_once(): Failed opening required '' (include_path='/srv/www/code/vendor/zendframework/zendframework1/library:/srv/www/code/library:.:/usr/share/php') in /srv/www/code/vendor/zendframework/zendframework1/library/Zend/ ...
8/1/14 8:55 AM  error [error] [client ] FastCGI: server "/app/php/box/php-fpm" stderr: PHP message: PHP Warning: require_once(/srv/www/code/vendor/zendframework/zendframework1/library): failed to open stream: No such file or directory in /srv/www/code/vendor/zendframework/zendframework1/library/Zend/ ...

看起来有些文件丢失了-可能与自动加载有关-应该不会太难修复。

等等,那是什么:Failed opening required '' ?当然你不需要任何东西,你这个愚蠢的代码!!

嗯…当查看相应的ZF库文件时,您不会在那里发现任何错误。包含路径似乎也是正确的——是的,文件是存在的——composer正确地管理了这两件事。


这是一个PHP bug!

更准确地说,这是PECL APC的一个bug,影响了Pinky的当前版本的PHP 5.4.30/APC 3.1.13 -参见:

https://bugs.php.net/bug.php?id=62398

这正是运行容器和web容器之间的区别,因为php.ini选项apc.stat被设置为0(关闭)用于web容器,1(打开)用于运行容器。


tl;博士

从GitHub克隆CloudControl Pinky PHP构建包:

git clone https://github.com/cloudControl/buildpack-php.git

从这个存储库复制所有文件,并将它们添加到您的项目根文件夹:

.buildpack/php

编辑.buildpack/php/conf/php.ini并设置:

apc.stat = 1

提交、推送、部署和享受!


指出:

请记住,这只是一个解决方案,因为APC状态不需要在这种环境中被激活(在部署时重新创建堆栈),它会减慢执行速度。参考PHP文档:

在脚本文件很少更改的生产服务器上可以通过禁用状态来实现显著的性能提升。


谢谢:

最后,我要感谢来自CloudControl的Dimitris和Mateusz的一般性建议——尽管我需要自己找出这里发生了什么。此外,我要感谢Stack Overflow的@BullfrogBlues和@Thierry_Marianne,他们试图回答另一个问题,可以追溯到去年11月,这最终让我寻找APC相关问题。