imdigital / magento-serverless
使用无服务器函数扩展 Magento 2
Requires
- php: >=8.1
- magento/framework: 103.0.*
This package is auto-updated.
Last update: 2024-09-14 21:01:00 UTC
README
Magento 2 的无服务器框架
使用无服务器函数,在不修改 Magento 代码库的情况下实现自定义功能、数据验证等。
使用此 Magento 模块,开发人员可以使用不属于代码库的无服务器函数来实现数据验证、添加自定义功能等。
什么是无服务器?
无服务器计算是一种按使用量提供后端服务的方法。无服务器提供商允许用户编写和部署代码,而无需担心底层基础设施。从无服务器供应商那里获取后端服务的企业将根据其计算量付费,无需预留和支付固定带宽或服务器数量,因为服务是自动扩展的。请注意,尽管名为无服务器,但仍然使用物理服务器,但开发人员无需了解它们。
在互联网的早期,任何想要构建网络应用程序的人都必须拥有运行服务器所需的物理硬件,这是一项既繁琐又昂贵的任务。
随后出现了云计算,其中可以远程租用固定数量的服务器或服务器空间。租用这些固定服务器空间单位的开发人员和公司通常会超额购买,以确保流量或活动的激增不会超出其月度限制,从而破坏其应用程序。这意味着大部分付费的服务器空间都可能浪费掉。云供应商引入了自动扩展模型来解决这一问题,但即使有自动扩展,不必要的活动激增,如DDoS攻击,也可能非常昂贵。
无服务器计算允许开发人员以灵活的“按使用付费”方式购买后端服务,这意味着开发人员只需为其使用的服务付费。这就像从每月固定限额的移动电话数据计划,切换到只按实际使用的每个字节数据收费的计划。
术语“无服务器”有些误导,因为仍然有服务器提供这些后端服务,但所有服务器空间和基础设施问题都由供应商处理。无服务器意味着开发人员可以完全不必担心服务器。
来源:https://www.cloudflare.com/learning/serverless/what-is-serverless/
为什么在 Magento 中使用无服务器?
当需要定制时,由于它是开源的,因此Magento在电子商务领域非常知名且受欢迎。
使用Magento,我们可以开发并添加新功能,修改现有功能,添加一些业务逻辑、数据验证等。
但这既是它的优点也是缺点,因为Magento经常更新其核心、安全补丁等,通常使用Magento构建的网店将有数十(甚至数百)个模块和定制,这使得这个过程痛苦,并且很多时候难以处理。
使用无服务器函数,我们可以实现几乎相同的事情,无需安装模块或修改Magento代码库。本质上,我们将定制运行在Magento代码库之外,托管在别处,这将便于维护和升级,因为我们将在代码库之外管理这些定制,如果我们想的话,甚至可以使用不同的编程语言来编写这些函数。
标准扩展性与无服务器之间的差异
标准扩展性方法
标准定制将是直接在Magento电子商务平台上开发或安装的模块/插件。这是扩展Magento功能的一种常见和标准方法。
这些插件将通过重写/拦截核心代码来添加新功能,引入新的业务逻辑和数据验证。它们是代码库的一部分,位于接近Magento核心的一层。
无服务器方法
使用无服务器方法,我们可以选择我们偏好的托管提供商,如Google Cloud、AWS或Azure,使用他们支持的任何编程语言(不一定需要PHP,如Magento)开发我们的自定义功能作为无服务器函数,直接在托管提供商上部署和管理此代码,然后就这样了,这些无服务器函数将在事件发生时由Magento触发。例如,假设我们想使用一个不允许客户每周订购超过3个单位单个SKU的购物车验证。我们开发并部署一个在添加到购物车事件上触发的无服务器函数,该无服务器函数将从Magento获取请求数据,进行验证,然后返回是否可以或不行。
这样,我们不仅可以使用任何编程语言编写此代码,而且可以轻松维护和发布新版本,而无需干扰网站。这将使管理未来的Magento升级变得更容易,因为核心几乎不会被触及,因为几乎不再有自定义扩展来重写它。
那么,为什么要使用无服务器呢?
- 使用任何编程语言自定义平台(不一定是Magento开发者)的自由。
- 可维护性。您可以轻松维护、部署和管理定制,而无需部署网站。您可以将功能的部分隔离开来。
- 扩展不是代码库的一部分。让代码库保持核心和店面主题。处理其他部分。
- 更便宜。使用无头架构,您只需为所需使用的内容付费。忘记昂贵的云实例和复制。
- 结束Magento升级噩梦。让代码库保持Magento核心。当处理平台升级时,使您的生活变得更容易。升级更快。
Adobe.io的替代方案
Adobe最近发布了一项类似的服务,但仅限于Adobe Commerce客户通过Adobe.io。但这要求客户使用他们的服务来部署和管理无服务器函数,而且它仅适用于Adobe Commerce客户。此模块不仅为开源客户提供这种类型的实现,而且还提供选择您喜欢的托管提供商来运行无服务器函数的选项。
框架
工作原理
Magento 开发者对 观察者 非常熟悉。当平台发生特定动作时,这些观察者会被触发。例如,一个产品被添加到购物车。一个 checkout_cart_product_add_before 事件被触发,允许模块/插件拦截它,获取其数据,并执行某些操作。这是扩展供应商和开发者常用的做法。我们可以利用这些事件做很多事情。但是,这些事件只能被安装在 Magento 代码库上的模块观察到。不过,现在不再是这样了。
这个 Magento 模块可以使 Magento 不仅能够触发这些事件,还允许安装模块来拦截它们,我们现在还可以注册部署在支持的托管服务提供商中的无服务器函数,并使它们能够接收已分发的数据并执行某些操作。这样,我们可以让代码库之外的代码修改业务逻辑、添加自定义验证等,而无需开发另一个 Magento 扩展来成为其代码库的一部分。
Magento 使用 Magento\Framework\Event\Manager\Proxy 类来分析事件并查看它们是否可以被已安装的 Magento 扩展捕获。因此,我们的框架通过使用我们的 ImDigital\Serverless\Event\Manager\Proxy 来替换这个类,这使得我们不仅可以使用已安装模块的观察者,还可以使用无服务器函数的观察者。因此,如果触发一个事件,Magento 将首先检查已安装的模块,查看是否有要执行观察者,执行它们,然后对已注册的无服务器函数执行同样的操作。因此,它将遍历已注册的无服务器函数以捕获该事件,并将它们逐个运行。
UML 时序图解释框架工作流程
在 Magento 中可用的所有观察者的完整列表可在 https://developer.adobe.com/commerce/php/development/components/events-and-observers/event-list/ 上找到。我们的无服务器框架可以支持这些操作中的任何一个。数据将被转换为 JSON 对象,然后传递给无服务器函数。
此模块将添加一个名为 serverless_functions 的新数据库表。在这张表中,我们将注册即将与 Magento 连接的无服务器函数和监视的事件。在这张表中,我们设置了在托管提供商上函数的名称、解释函数将做什么的简短描述、云提供商、Magento 观察事件、启用/禁用无服务器函数的标志以及云配置。云配置键将具有加密值,使用 Magento 加密密钥加密。
如何调用无服务器函数
每个托管提供商都将有自己的 Magento 无服务器软件包,这意味着它们将扩展这个无服务器模块,添加负责调用托管提供商上的无服务器函数以获取数据的代码。
每个云提供商软件包都必须有一个 Provider.php 类,这是实现这个逻辑的地方。这个调用将实现 ImDigital\Serverless\Api\Data\CloudProviderInterface 接口,该接口具有它们都必须实现的方法以实现这一点。这样,所有云提供商都将遵循相同的标准。
<?php declare(strict_types=1); namespace ImDigital\Serverless\Api\Data; interface CloudProviderInterface { /** * @param ServerlessFunctionInterface $serverlessFunction * @param array $data * @throws \Exception * @return void */ public function execute(ServerlessFunctionInterface $serverlessFunction, array &$data): void; /** * @param ServerlessFunctionInterface $serverlessFunction */ public function getCloudConfig(ServerlessFunctionInterface $serverlessFunction); }
CloudProviderInterface
这些提供者类几乎都必须扩展 ImDigital\Serverless\Model\Cloud\Provider 抽象类。它有两个方法,prepareRequestData 和 prepareResponseData,分别用于准备请求数据和处理响应。该类可在 https://github.com/Imagination-Media/magento-serverless/blob/master/Model/Cloud/Provider.php 上找到。
一个云服务提供商的实现示例可以在https://github.com/Imagination-Media/magento-serverless-gcp/blob/master/Model/Cloud/Provider.php找到。这是谷歌云服务提供商的实现。
云服务提供商通过将它们的云服务提供商类注入到类中来进行配置并添加到受支持的托管服务提供商列表中。我们通过使用etc/di.xml文件来完成此操作。例如,这是谷歌云包的配置。
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <!-- Injecting cloud provider --> <type name="ImDigital\Serverless\Model\ServerlessFunctionConfigRepository"> <arguments> <argument name="cloudProviders" xsi:type="array"> <item name="gcp" xsi:type="object">ImDigital\ServerlessGcp\Model\Cloud\Provider</item> </argument> </arguments> </type> <type name="ImDigital\Serverless\Model\Config\Source\Provider"> <arguments> <argument name="cloudProviders" xsi:type="array"> <item name="gcp" xsi:type="array"> <item name="label" xsi:type="string">Google Cloud</item> <item name="value" xsi:type="string">gcp</item> </item> </argument> </arguments> </type> </config>
JSON配置文件
与Magento相连的无服务器函数通过将所需信息添加到serverless_functions
数据库表中在Magento中设置。但是,当Magento框架运行时,检查观察者比从数据库中读取这些设置函数配置要快得多。因此,在这个框架中有一个CLI命令,它从数据库生成配置到一个JSON文件中,包含框架设置与托管服务提供商连接和执行无服务器函数所需的所有信息。
命令如下:
php bin/magento serverless:deploy:config
管理员管理界面
一旦安装了此扩展,您将在左侧导航菜单中看到一个名为“无服务器”的新项目。此菜单有一个“管理”选项,我们可以看到连接的无服务器函数,管理它们,还可以添加新的。
安装
需求
- Magento >= 2.4.5-p1
- PHP >= 8.1
安装模块并启用它
要安装此模块,我们必须运行composer require命令请求其安装
composer require imdigital/magento-serverless
然后,通过修改app/etc/config.php或运行CLI命令来启用它
php bin/magento module:enable ImDigital_Serverless
最后,我们需要修改app/etc/di.xml文件,将Magento更改为使用ImDigital\Serverless\Event\Manager\Proxy类来管理事件引擎,而不是使用Magento\Framework\Event\Manager\Proxy核心类。
您可以通过创建一个包含以下内容的补丁来完成此操作:
--- app/etc/di.xml 2023-02-28 20:18:29.577784341 +0000 +++ app/etc/di.xml 2023-02-28 20:19:12.078146055 +0000 @@ -67,7 +67,7 @@ <preference for="Magento\Framework\Event\ConfigInterface" type="Magento\Framework\Event\Config" /> <preference for="Magento\Framework\Event\InvokerInterface" type="Magento\Framework\Event\Invoker\InvokerDefault" /> <preference for="Magento\Framework\Interception\PluginListInterface" type="Magento\Framework\Interception\PluginList\PluginList" /> - <preference for="Magento\Framework\Event\ManagerInterface" type="Magento\Framework\Event\Manager\Proxy" /> + <preference for="Magento\Framework\Event\ManagerInterface" type="ImDigital\Serverless\Event\Manager\Proxy" /> <preference for="Magento\Framework\View\LayoutInterface" type="Magento\Framework\View\Layout" /> <preference for="Magento\Framework\View\Layout\ProcessorInterface" type="Magento\Framework\View\Model\Layout\Merge" /> <preference for="Magento\Framework\View\Layout\LayoutCacheKeyInterface" type="Magento\Framework\View\Model\Layout\CacheKey" />
然后,将其应用到您的post-composer安装过程中。您可以通过编辑composer.json文件并添加以下内容来完成此操作:
"scripts": {
"post-install-cmd": [
"git apply m2-hotfixes/di-patch.patch"
]
},
此补丁文件也在此存储库中可用:https://github.com/Imagination-Media/magento-serverless/blob/master/di-patch.patch。
环境变量
有几个环境变量我们可以用来配置此框架中的某些设置
- MAGENTO_SERVERLESS_FILE_PATH - 如描述,此框架生成一个包含无服务器函数配置的JSON文件。此环境变量允许我们定义此文件将被创建的位置。默认情况下(如果没有设置),此值将为var/serverless/functions.json。
- MAGENTO_SERVERLESS_TIMEOUT - 此环境变量用于设置,以毫秒为单位,无服务器函数的超时时间。默认情况下,它使用4000(4秒)。
支持的云服务提供商
这是当前由此框架支持的云服务提供商列表。
添加新的无服务器函数
作为我们的路线图的一部分,我们将添加一个接口到Magento管理员,我们可以管理这些无服务器函数,启用/禁用它们等。目前,我们只能直接将这些函数添加到数据库中。
serverless_functions数据库表有以下字段
- id - 注册的自动生成id。将被自动生成。
- name - 云服务提供商上函数的名称(id)。
- description - 简短描述,说明函数做什么。
- cloud_provider - 云服务提供商代码。例如,gcp代表谷歌云。
- observed_event - 云函数观察到的Magento事件。
- is_enabled - 一个标志,用于启用/禁用无服务器函数。
- cloud_config - 这是一个加密的JSON文件,包含了托管服务商所需的云配置信息。例如,服务账户密钥、区域ID等。此字段的值取决于托管服务商,请查阅托管服务商的套餐文档以获取更多信息。
一旦该函数在数据库中,我们可以运行php bin/magento serverless:deploy:config来为我们生成JSON配置。
JSON生成后,Magento必须能够处理无服务器函数。假设我添加了一个名为validate-add-to-cart的无服务器函数,它将监视checkout_cart_product_add_before事件,该事件在产品即将被添加到购物车时触发。如果有人试图将特定SKU添加到购物车,根据我的业务逻辑,该SKU因为制造商的问题将因某些问题在一周内不可用,这个无服务器函数将会阻止添加。我可以部署一个无服务器函数来完成这个任务。
exports.validate = (req, res) => {
console.log(req.body);
if (req.body.product.sku === "24-MB04") {
return res.status(500).send("Product 24-MB04 is temporarily blocked!");
}
res.status(200).send(JSON.stringify(req.body));
};
如果被添加到购物车的SKU是24-MB04,则不会添加到购物车,因为我们返回了一个错误500和错误信息。
这就是我们需要的一切。如果我们需要修改这个业务逻辑,我们只需要在托管服务商处直接修改它,部署它,然后就可以了。几秒钟后,它就上线了,无需在网站上部署。
路线图
- 添加异步无服务器函数支持。