【问题标题】:multi-instance symfony application with shared code base具有共享代码库的多实例 symfony 应用程序
【发布时间】:2017-06-20 09:51:09
【问题描述】:

所以,我在 Symfony 3 之上构建了一个大型的 SAAS Web 应用程序。开始时大约有 10 到 20 个应用程序,现在已经发展到超过 500 多个应用程序。每个应用程序仅供应商目录的大小就已超过 150 MB。

所有这些应用程序都有自己的数据库。我想保持这种状态。但是,我相信如果共享一些代码会很好。以 vendor 和 src 目录为例。每个应用程序都是一样的,但是它们都在 OpCache 中单独“加载”。我相信从资源的角度来说,最好是共享这些目录。

Composer 和 Symfony 似乎都不太支持具有共享目录的多实例应用程序。但是我想知道是否有人有任何线索可以实现我的想法,或者我的计划不可行?

每个应用程序的配置不同(parameters.yml),Web 目录包含每个应用程序的不同样式表。所以他们需要与其他人分开。

我一直在考虑为此使用环境设置,但是我们有环境“test”,“dev”,“application1”,“application2”等感觉不对。config_prod.yml 突然也然后就无法使用了。

我的思维方式有问题吗?关于如何实现这一目标的任何建议?还是我应该只使用一个完整的单独实例?

(我们的应用程序正在使用 SemVer,如果我们共享 1.0.0 版、1.1.0 版等的代码,那就更好了。所以这甚至是最上面的下一层。但也许这是下一步。 )

编辑: 再澄清一点; 本质上,您可以说 web 目录和 var 目录都是不可共享的。 web 目录包含自定义样式表并且是主要入口点。 var 目录包含缓存文件,每个应用程序根据其数据库设置而有所不同。 最后,您还拥有自定义参数文件,每个应用程序存储数据库凭据的文件不同。

我尝试了符号链接,但作曲家对此并不满意。此外,在使用符号链接时,工作目录始终是实际使用的目录,而不是您从中进行符号链接的实际目录。 我还尝试在应用程序的 vhost 文件中使用自定义设置。覆盖缓存和内核目录是可能的,但是您再次失去了您正在符号链接的实际目录。

【问题讨论】:

  • 只是一个想法:Opcache 使用真实路径,如果相同,您可以使用指向“父”的符号链接替换文件。在作曲家安装后编写脚本,您可能可以从中解脱...
  • 是的,我试过了。但是,composer 不支持供应商目录由多个应用程序符号链接。它将路径保存在其中一个自动加载器中的某处。
  • 我不是指供应商文件夹,而是包中的代码。而不是包,而是在该级别下所有相同的文件。 Linke 递归比较两个目录树,如果文件相同,则用符号链接替换它。 opcache 然后将使用真实路径。这必须在脚本中完成,以便您可以通过清除供应商文件夹来重置,使用 composer 重新安装,然后重新运行比较和链接脚本。

标签: php symfony


【解决方案1】:

您需要创建自定义配置目录和/或文件,然后根据您使用的任何标准调整您的 AppKernel 以指向正确的配置目录和/或文件。例如,如果您要离开子域: 首先,更新您的前端控制器以拥有一个新的超级全局。可能有更好的方法可以做到这一点,我建议您研究一下..

// web/app.php
use Symfony\Component\HttpFoundation\Request;

/** @var \Composer\Autoload\ClassLoader $loader */
$loader = require __DIR__.'/../app/autoload.php';
include_once __DIR__.'/../var/bootstrap.php.cache';

list($scheme, $host) = explode('.',$_SERVER['SERVER_NAME']);
define(APP_CONFIG_FILENAME, sprintf('%s.yml', $host));

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
//$kernel = new AppCache($kernel);

// When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter
//Request::enableHttpMethodParameterOverride();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

现在在你的AppKernel 中,使用这个新的超全局

// app/AppKernel.php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load($this->getProjectDir().'/app/config/' . APP_CONFIG_FILENAME . '.yml');
    }
}

然后在你的 example1.yml

# app/config/mysubdomain.yml
imports:
    - { resource: 'parameters_example1.yml' }
    - { resource: 'routing_example1.yml' }

【讨论】:

  • 感谢您的回复,但我认为这并不能完全解决问题。如前所述,每个应用程序都有一个单独的数据库。这意味着缓存也不能在应用程序之间共享。我会更新我的主要帖子。
  • 因此,您只需更改 config_{x}.yml 中的缓存配置设置以及 parameters_{x}.yml 中的数据库参数 - 对于缓存,您必须设置非文件系统存储,或用于 redis 之类的自定义缓存处理程序,或者如果您愿意;带有 pdo 的数据库驱动缓存,如下所示:symfony.com/doc/master/components/cache/adapters/… 或单独的 pdo 会话处理程序:symfony.com/doc/current/doctrine/pdo_session_storage.html
  • 除了你是否正确(我相信你让它听起来比实际上更容易,因为由于缓存我不能在 yml 文件中存储任何东西),它仍然没有解决将 vendor 和 src 目录(可能更多)放在共享目录中的问题。
  • 如果我让它听起来太简单了,我深表歉意,但我实际上已经这样做了,所以我知道它有效。共享的供应商和 src 是这样的多站点设置的全部要点。
  • 嗨,杰克。好吧。很高兴听到:) 我也会自己尝试一下。那么你是如何共享 vendor / src 目录的呢?因为当您使用符号链接时,实际工作目录会更改为文件实际所在的目录。
猜你喜欢
  • 1970-01-01
  • 2011-05-30
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多