From 7cb2aa1c42b0e29087dabbeb34f3b45a05ba906a Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 3 Aug 2016 17:30:11 +0200 Subject: [PATCH 01/11] Added a new article about applications with multiple kernels --- request/multiple_kernels.rst | 140 +++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 request/multiple_kernels.rst diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst new file mode 100644 index 00000000000..48e561613a5 --- /dev/null +++ b/request/multiple_kernels.rst @@ -0,0 +1,140 @@ +.. index:: + single: kernel, performance + +How To Create Symfony Applications with Multiple Kernels +======================================================== + +In most Symfony applications, incoming requests are processed by the +``web/app.php`` front controller, which instantiates the ``app/AppKernel.php`` +class to create the application kernel that loads the bundles and generates the +response. + +This single kernel approach is a convenient default provided by the Symfony +Standard edition, but Symfony applications can define any number of kernels. +This is useful to execute the same application using a different configuration +and a different set of bundles for each kernel: + +* An application that defines an API could create an ``ApiKernel`` to not have + to load all the bundles enabled in the regular web application. This will + improve the API performance; +* A bundle that doesn't allow multiple instances can define multiple + configurations in different files loaded by each kernel. + +Adding a new Kernel to the Application +-------------------------------------- + +Creating a new kernel in a Symfony application is a three-step process: + +1. Create a new front controller to load the new kernel; +2. Create the new kernel class; +3. Define the configuration loaded by the new kernel. + +The following example shows how to create a new kernel for the API of a given +Symfony application. + +Step 1) Create a new Front Controller +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Instead of creating the new front controller from scratch, it's recommended to +duplicate the existing ``web/app_dev.php`` and ``web/app.php`` files. For +example, you can create ``web/api_dev.php`` and ``web/api.php`` (or +``web/api/app_dev.php`` and ``web/api/app.php`` depending on your server +configuration). + +Then, update the code of the new front controllers to instantiate the new kernel +class instead of the usual ``AppKernel`` class: + + // web/api.php + // ... + $kernel = new ApiKernel('prod', true); + // ... + + // web/api_dev.php + // ... + $kernel = new ApiKernel('dev', true); + // ... + +Step 2) Create the new Kernel Class +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now you need to define the ``ApiKernel`` class used by the new front controller. +The recommendation again is to duplicate the existing ``app/AppKernel.php`` file +and make the needed changes. + +In this example, the changes of the new ``ApiKernel`` would be to load less +bundles than ``AppKernel`` and to change the location of the cache, logs and +config files to not mess with the regular application: + + // app/ApiKernel.php + getEnvironment(); + } + + public function getLogDir() + { + return dirname(__DIR__).'/var/logs/api'; + } + + public function registerContainerConfiguration(LoaderInterface $loader) + { + $loader->load($this->getRootDir().'/config/api/config_'.$this->getEnvironment().'.yml'); + } + } + +Step 3) Define the Kernel Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Finally, define the configuration used by the application when it executes the +new API kernel. According to the previous code, this config must be defined in +the ``app/config/api/`` directory. + +The new configuration can be created from scratch when you load just a few +bundles, because it it will be very simple. Otherwise, duplicate the existing +config files or better, import them and override the needed options: + +.. code-block:: yaml + + # app/config/api/config_dev.yml + imports: + - { resource: ../config_dev.yml } + + # override option values ... + +Adding more Kernels to the Application +-------------------------------------- + +If your application is very complex and you create several kernels, it's better +to store them on their own directories instead of messing with lots of files in +the default ``app/`` directory: + +.. code-block:: text + + project/ + ├─ app/ + │ ├─ ... + │ ├─ config/ + │ └─ AppKernel.php + ├─ api/ + │ ├─ ... + │ ├─ config/ + │ └─ ApiKernel.php + ├─ ... + └─ web/ + ├─ ... + ├─ app.php + ├─ app_dev.php + ├─ api.php + └─ api_dev.php From 21329ecbc47e1b4e436ab6936f7566f3dfe12991 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 3 Aug 2016 17:38:06 +0200 Subject: [PATCH 02/11] Fixed some syntax issues --- request/multiple_kernels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index 48e561613a5..21a842654c3 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -63,7 +63,7 @@ and make the needed changes. In this example, the changes of the new ``ApiKernel`` would be to load less bundles than ``AppKernel`` and to change the location of the cache, logs and -config files to not mess with the regular application: +config files to not mess with the regular application:: // app/ApiKernel.php Date: Wed, 3 Aug 2016 17:39:18 +0200 Subject: [PATCH 03/11] Fixed another syntax issue --- request/multiple_kernels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index 21a842654c3..8be4bea3703 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -42,7 +42,7 @@ example, you can create ``web/api_dev.php`` and ``web/api.php`` (or configuration). Then, update the code of the new front controllers to instantiate the new kernel -class instead of the usual ``AppKernel`` class: +class instead of the usual ``AppKernel`` class:: // web/api.php // ... From d45e1f43b5f39944089e3626e9819c6b38deeb1d Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 3 Aug 2016 21:55:17 +0200 Subject: [PATCH 04/11] Fixed an example code --- request/multiple_kernels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index 8be4bea3703..d8ad2c4151c 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -46,7 +46,7 @@ class instead of the usual ``AppKernel`` class:: // web/api.php // ... - $kernel = new ApiKernel('prod', true); + $kernel = new ApiKernel('prod', false); // ... // web/api_dev.php From 5c8ed87f9866a73553365f09ab20d66a688ad90b Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 3 Aug 2016 22:01:03 +0200 Subject: [PATCH 05/11] Fixed typo --- request/multiple_kernels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index d8ad2c4151c..8c018938439 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -102,7 +102,7 @@ new API kernel. According to the previous code, this config must be defined in the ``app/config/api/`` directory. The new configuration can be created from scratch when you load just a few -bundles, because it it will be very simple. Otherwise, duplicate the existing +bundles, because it will be very simple. Otherwise, duplicate the existing config files or better, import them and override the needed options: .. code-block:: yaml From 097a73d79b4dbd4cef32fb0a50f45edb968ced40 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 4 Aug 2016 09:43:48 +0200 Subject: [PATCH 06/11] Reworded the use cases section --- request/multiple_kernels.rst | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index 8c018938439..b77e91d6de6 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -11,14 +11,23 @@ response. This single kernel approach is a convenient default provided by the Symfony Standard edition, but Symfony applications can define any number of kernels. -This is useful to execute the same application using a different configuration -and a different set of bundles for each kernel: - -* An application that defines an API could create an ``ApiKernel`` to not have - to load all the bundles enabled in the regular web application. This will - improve the API performance; -* A bundle that doesn't allow multiple instances can define multiple - configurations in different files loaded by each kernel. +Whereas :doc:`environments ` execute the same +application with different configurations, kernels can execute different parts +of the same application. + +These are some of the common use cases for creating multiple kernels: + +* An application that defines an API could define two kernels for performance + reasons. The first kernel would serve the regular application and the second + one would only respond to the API requests, loading less bundles and enabling + less features; +* A highly sensitive application could define two kernels. The first one would + only load the routes that match the parts of the application exposed to the + public. The second kernel would load the rest of the application and its + access would be protected by the web server; +* An application that uses a bundle which doesn't allow multiple instances could + define two identical kernels to define a different bundle configuration for + each of them. Adding a new Kernel to the Application -------------------------------------- From 2c5aeb1ac76ad64d77962a4c00eb1d2b469a58ff Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 4 Aug 2016 20:19:16 +0200 Subject: [PATCH 07/11] Removed a use case --- request/multiple_kernels.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index b77e91d6de6..11de3cbc815 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -24,10 +24,7 @@ These are some of the common use cases for creating multiple kernels: * A highly sensitive application could define two kernels. The first one would only load the routes that match the parts of the application exposed to the public. The second kernel would load the rest of the application and its - access would be protected by the web server; -* An application that uses a bundle which doesn't allow multiple instances could - define two identical kernels to define a different bundle configuration for - each of them. + access would be protected by the web server. Adding a new Kernel to the Application -------------------------------------- From af4ff183afb3a49c798c23fa1a1c0651a9bf8e8b Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 4 Aug 2016 20:27:28 +0200 Subject: [PATCH 08/11] Added a new use case related to micro-services --- request/multiple_kernels.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index 11de3cbc815..7d84d1f379d 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -22,9 +22,12 @@ These are some of the common use cases for creating multiple kernels: one would only respond to the API requests, loading less bundles and enabling less features; * A highly sensitive application could define two kernels. The first one would - only load the routes that match the parts of the application exposed to the - public. The second kernel would load the rest of the application and its - access would be protected by the web server. + only load the routes that match the parts of the application exposed publicly. + The second kernel would load the rest of the application and its access would + be protected by the web server; +* A micro-services oriented application could define several kernels to + enable/disable services selectively turning a traditional monolith application + into several micro-applications. Adding a new Kernel to the Application -------------------------------------- From e403fd8582167bf3d6b2d7bcff45b5ad777bd959 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 4 Oct 2016 13:02:40 +0200 Subject: [PATCH 09/11] Added a new section about running commands under a different kernel --- request/multiple_kernels.rst | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index 7d84d1f379d..e77de0852cf 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -6,8 +6,8 @@ How To Create Symfony Applications with Multiple Kernels In most Symfony applications, incoming requests are processed by the ``web/app.php`` front controller, which instantiates the ``app/AppKernel.php`` -class to create the application kernel that loads the bundles and generates the -response. +class to create the application kernel that loads the bundles and handles the +request to generate the response. This single kernel approach is a convenient default provided by the Symfony Standard edition, but Symfony applications can define any number of kernels. @@ -45,10 +45,8 @@ Step 1) Create a new Front Controller ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Instead of creating the new front controller from scratch, it's recommended to -duplicate the existing ``web/app_dev.php`` and ``web/app.php`` files. For -example, you can create ``web/api_dev.php`` and ``web/api.php`` (or -``web/api/app_dev.php`` and ``web/api/app.php`` depending on your server -configuration). +duplicate the existing ones. For example, create ``web/api_dev.php`` from +``web/app_dev.php`` and ``web/api.php`` from ``web/app.php``. Then, update the code of the new front controllers to instantiate the new kernel class instead of the usual ``AppKernel`` class:: @@ -122,6 +120,24 @@ config files or better, import them and override the needed options: # override option values ... +Executing Commands with a Different Kernel +------------------------------------------ + +The ``bin/console`` script used to run Symfony commands always uses the default +``AppKernel`` class to build the application and load the commands. If you need +to execute console commands using the new kernel, duplicate the ``bin/console`` +script and rename it (e.g. ``bin/api``). + +Then, replace the ``AppKernel`` instantiation by your own kernel instantiation +(e.g. ``ApiKernel``) and now you can execute commands using the new kernel +(e.g. ``php bin/api cache:clear``) Now you can use execute commands using the new kernel + +.. note:: + + The commands available for each console script (e.g. ``bin/console`` and + ``bin/api``) can differ because they depend on the bundles enabled for each + kernel, which could be different. + Adding more Kernels to the Application -------------------------------------- From 2613810bdc1b74edfe3447d63c5749cdd3e45464 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 12 Oct 2016 17:29:31 +0200 Subject: [PATCH 10/11] Added a note about rendering templates from different kernels --- request/multiple_kernels.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index e77de0852cf..6fa21ea2cc2 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -138,6 +138,24 @@ Then, replace the ``AppKernel`` instantiation by your own kernel instantiation ``bin/api``) can differ because they depend on the bundles enabled for each kernel, which could be different. +Rendering Templates Defined in a Different Kernel +------------------------------------------------- + +If you follow the Symfony Best Practices, the templates of the default kernel +will be stored in ``app/Resources/views/``. Trying to render those templates in +a different kernel will result in a *There are no registered paths for +namespace "__main__"* error. + +In order to solve this issue, add the following configuration to your kernel: + +.. code-block:: yaml + + # api/config/config.yml + twig: + paths: + # allows to use app/Resources/views/ templates in the ApiKernel + "%kernel.root_dir%/../app/Resources/views": ~ + Adding more Kernels to the Application -------------------------------------- From bc3618def2632ce6b613573431809a7de95d11c0 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 25 Oct 2016 19:35:16 +0200 Subject: [PATCH 11/11] Made a bunch of fixes recommended by Ryan --- request/multiple_kernels.rst | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/request/multiple_kernels.rst b/request/multiple_kernels.rst index 6fa21ea2cc2..fbd23a0b0fa 100644 --- a/request/multiple_kernels.rst +++ b/request/multiple_kernels.rst @@ -44,7 +44,7 @@ Symfony application. Step 1) Create a new Front Controller ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Instead of creating the new front controller from scratch, it's recommended to +Instead of creating the new front controller from scratch, it's easier to duplicate the existing ones. For example, create ``web/api_dev.php`` from ``web/app_dev.php`` and ``web/api.php`` from ``web/app.php``. @@ -65,16 +65,14 @@ Step 2) Create the new Kernel Class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Now you need to define the ``ApiKernel`` class used by the new front controller. -The recommendation again is to duplicate the existing ``app/AppKernel.php`` file -and make the needed changes. +The easiest way to do this is by duplicating the existing ``app/AppKernel.php`` +file and make the needed changes. -In this example, the changes of the new ``ApiKernel`` would be to load less -bundles than ``AppKernel`` and to change the location of the cache, logs and -config files to not mess with the regular application:: +In this example, the ``ApiKernel`` will load less bundles than AppKernel. Be +sure to also change the location of the cache, logs and configuration files so +they don't collide with the files from ``AppKernel``:: // app/ApiKernel.php -