Integra Magento en Cloud Spanner

1. Introducción

424db48d9db91638.png

Cómo integrar Magento con un backend de Cloud Spanner

Magento es una plataforma de comercio electrónico de código abierto basada en PHP muy popular que almacena datos en MySQL.

Este codelab es una prueba de concepto para aprovechar Cloud Spanner en lugar de MySQL para el módulo Catálogo. Esto es útil para cualquier persona interesada en integrar, probar e implementar Magento, o bien otras aplicaciones de PHP, con Spanner.

Spanner es la base de datos completamente administrada, de nivel empresarial, distribuida y coherente de Google Cloud que combina los beneficios del modelo de base de datos relacional con escalabilidad horizontal no relacional. Está diseñada para admitir implementaciones globales de procesamiento de transacciones en línea, semántica de SQL, escalamiento horizontal con alta disponibilidad y coherencia transaccional. Spanner puede controlar grandes volúmenes de datos. Su uso no se limita a aplicaciones de gran tamaño, sino que permite la estandarización de un solo motor de base de datos para todas las cargas de trabajo que requieren un sistema de este tipo. Spanner proporciona un tiempo de inactividad cero para el mantenimiento planificado o las fallas de la región, con un ANS de disponibilidad del 99.999%. Admite aplicaciones modernas, ya que proporciona alta disponibilidad y escalabilidad.

Qué aprenderás

  • Cómo instalar Magento en GCE
  • Cómo configurar el emulador de Spanner
  • Cómo migrar un esquema de MySQL existente a Spanner con HarbourBridge
  • Qué debes cambiar para integrar aplicaciones de PHP, como Magento, que usan MySQL para que el backend de la base de datos funcione con Spanner

Qué compilarás

Este codelab se enfoca en integrar Magento a Spanner. Se proporcionan bloques de código y las instrucciones de configuración para que copies y pegues, pero no se analizan en detalle.

En este codelab, comenzarás a integrar Magento en Spanner. Harás lo siguiente:

Requisitos

  • Un proyecto de Google Cloud que está conectado a una cuenta de facturación
  • Además, tienes conocimientos de configuración de PHP, Linux y Apache.
  • La experiencia de Magento será útil, pero no es obligatoria.

2. Prepara la instancia de GCE

Crea la instancia de GCE

Sigue los pasos que se mencionan aquí para crear una instancia de Compute Engine en Google Cloud Platform.

Cuando crees la instancia de GCE, cambia el tipo de instancia a e2-standard-2 y el tamaño del disco de arranque a 20 GB. Puedes dejar todo como predeterminado, pero asegúrate de seleccionar “Permitir tráfico HTTP” y “Permitir tráfico HTTPs”, ya que aprovecharemos la interfaz web de Magento.

Esto da como resultado un tipo de máquina e2-standard-2 que no es una instancia de núcleo compartido y tiene 2 CPU virtuales, 8 GB de RAM y 20 GB de espacio en el disco.

El sistema operativo es Debian 10. La creación de la instancia puede tardar uno o dos minutos.

Una vez que se cree, haz clic en "SSH" en la consola de Cloud para acceder:

4bf915ef8d37c942.png

Se abrirá una nueva ventana del navegador y te dirigirá a una terminal.

Instala el software necesario

Magento necesitará que se instale un software previo para que podamos ejecutarlo. En particular, instalarás PHP, Elastic, MySQL y Apache como se detalla a continuación.

  1. Instala algunos paquetes obligatorios.
sudo apt update

sudo apt -y install lsb-release apt-transport-https ca-certificates wget git screen composer google-cloud-sdk-spanner-emulator gcc
  1. Instala los módulos de PHP necesarios para Magento.
sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg

echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php.list

sudo apt update

sudo apt -y install php7.4-fpm php7.4-common php7.4-mysql php7.4-gmp php7.4-curl php7.4-intl php7.4-mbstring php7.4-xmlrpc php7.4-gd php7.4-xml php7.4-cli php7.4-zip php7.4-bcmath php7.4-soap php7.4-grpc
  1. Instala Elasticsearch y, luego, inicia el servicio
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list

sudo apt update && sudo apt -y install elasticsearch

echo "-Xms1g
-Xmx1g" | sudo tee /etc/elasticsearch/jvm.options.d/jvm.options

sudo systemctl start elasticsearch.service
  1. Instala MySQL

Instalarás MySQL para instalar el esquema predeterminado de Magento. Más adelante, migrarás el esquema a Spanner con HarbourBridge.

wget https://dev.mysql.com/get/mysql-apt-config_0.8.13-1_all.deb

sudo dpkg -i mysql-apt-config*

El comando dpkg anterior mostrará un mensaje interactivo para instalar el servidor MySQL 5.7. Selecciona las siguientes opciones:

  • Servidor y clúster MySQL
  • mysql-5.7
  • Aceptar

a018bfc2ee00bdf5.png 1a126e452ca7312e.png ae39c6f4bbe3be74.png

sudo apt update && sudo apt -y install mysql-server
# You will be prompted to enter a root password
  1. Instala Apache2
sudo apt -y install apache2

sudo a2enmod proxy_fcgi rewrite

Cómo instalar y configurar Magento2

El proyecto de Magento Commerce Cloud incluye un esquema de base de datos y servicios para acceder por completo al sitio y la tienda de Magento.

La forma más fácil de instalarlo y ejecutarlo es seguir las instrucciones de Magento para instalarlo con composer:

  1. Instala la versión 2.4.2 de Magento con el compositor. Magento 2 requiere la versión 1.x de Composer. Es posible que veas algunas advertencias que indican que esta versión es obsoleta.
composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition=2.4.2 magento2
  1. Cómo establecer permisos de carpeta
cd magento2

find var generated vendor pub/static pub/media app/etc -type f -exec chmod g+w {} +

find var generated vendor pub/static pub/media app/etc -type d -exec chmod g+ws {} +
  1. Para configurar el host virtual de Magento, crea /etc/apache2/sites-available/magento.conf con el siguiente contenido.
sudo nano /etc/apache2/sites-available/magento.conf

<VirtualHost *:80>
        ServerAdmin admin@local-magento.com
        DocumentRoot /var/www/html/magento/

        <Directory /var/www/html/magento/>
                Options Indexes FollowSymlinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>

        <FilesMatch \.php$>
               SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost"
        </FilesMatch>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
  1. Crea los symlinks y reinicia apache2.
cd ~/magento2
sudo ln -s $(pwd) /var/www/html/magento 
sudo ln -s /etc/apache2/sites-available/magento.conf  /etc/apache2/sites-enabled/magento.conf
sudo rm /etc/apache2/sites-enabled/000-default.conf

sudo systemctl restart apache2
  1. Crea la base de datos y el usuario para Magento en MySQL
export ROOT_PASSWORD="<root password from installation>"
export GCE_INSTANCE_IP="<GCE instance IP>"
mysql -uroot -p$ROOT_PASSWORD -e "create database magento"

bin/magento sampledata:deploy

bin/magento setup:install --base-url=http://$GCE_INSTANCE_IP/ --db-host=localhost \
--db-name=magento --db-user=root --db-password=$ROOT_PASSWORD --admin-firstname=admin \
--admin-lastname=demo --admin-email=good@example.com --admin-user=admin \
--admin-password=magento123 --language=en_US --currency=USD --timezone=America/Chicago \
--use-rewrites=1

sudo chown -R :www-data ~/magento2/. 
  1. Verifica tu espacio de trabajo local. Para verificar que el entorno local aloje el servidor, accede a la tienda con la URL base que pasaste en el comando de instalación. En este ejemplo, puedes acceder a la tienda local de Magento con los siguientes formatos de URL:
  • http://&lt;GCEexternalIP&gt;/
  • http://<GCEexternalIP>/<adminuri>

Se puede encontrar GCEexternalIP en la consola de Cloud:

3947f1164e1d5409.png

Para cambiar el URI del panel Administrador, usa este comando para encontrarlo:

php bin/magento info:adminuri
  1. Inhabilita la caché de página completa. Para fines de desarrollo, puedes inhabilitar la caché de página completa de Magento2. Esto te permitirá modificar los datos en Spanner y hacer que se reflejen en el sitio web sin que los valores almacenados en caché se vean afectados.
php bin/magento cache:disable full_page

Configura Spanner

Instala el emulador de Spanner

El SDK de Cloud proporciona un emulador local en la memoria, que puedes usar para desarrollar y probar tus aplicaciones de forma gratuita sin crear un proyecto de GCP ni una cuenta de facturación. Como el emulador almacena datos solo en la memoria, todos los estados, incluidos los datos, el esquema y los parámetros de configuración, se pierden durante el reinicio. El emulador ofrece las mismas APIs que el servicio de producción de Spanner y está diseñado para el desarrollo y las pruebas locales, no para las implementaciones de producción.

Usa el siguiente vínculo para obtener más información sobre la instalación, el uso y la implementación del emulador:

Usa el emulador de Spanner

# Set up a new configuration to use the emulator
gcloud config configurations create emulator
gcloud config set auth/disable_credentials true
gcloud config set project magento
gcloud config set api_endpoint_overrides/spanner http://localhost:9020/

# Start emulator in a screen session
screen -S magento
gcloud emulators spanner start &
gcloud spanner instances create magento-instance --config=emulator-config --description='Magento Instance' --nodes=1

# Detach from screen 
ctrl+a+d

export SPANNER_EMULATOR_HOST=localhost:9010

Migra MySQL de Magento a Spanner

Antes de comenzar a integrar Spanner, usaremos una herramienta llamada HarbourBridge para convertir la base de datos de MySQL que se creó como parte de nuestra instalación de Magento anterior a Spanner.

En esencia, HarbourBridge proporciona un flujo de trabajo automatizado para cargar el contenido de una base de datos existente de MySQL o PostgreSQL en Spanner. No requiere configuración, ni manifiestos ni mapas de datos para escribir. En su lugar, importa la base de datos de origen, compila un esquema de Spanner, crea una nueva base de datos de Spanner propagada con datos de la base de datos de origen y genera un informe de evaluación detallado. HarbourBridge está diseñado para cargar bases de datos de hasta unas pocas decenas de GB con fines de evaluación, no para migraciones a gran escala.

HarbourBridge inicia la migración a Spanner en la etapa inicial con una base de datos de origen MySQL o PostgreSQL existente para que puedas comenzar a usar Spanner rápidamente. Genera un informe de evaluación con una puntuación general de aptitud para la migración a Spanner, un análisis tabla por tabla de las asignaciones de tipos y una lista de las funciones que se usan en la base de datos de origen y que Spanner no admite.

HarbourBridge se puede usar con el emulador de Spanner o directamente con una instancia de Spanner.

El archivo README de HarbourBridge contiene una guía de inicio rápido paso a paso para usar la herramienta con una instancia de Spanner.

Instala HarbourBridge

Descarga la herramienta en tu máquina y, luego, instálala. Es necesario instalar golang para que funcione. La instalación de todos los módulos necesarios en una instancia nueva sin Go configurado previamente puede tardar un tiempo.

# Install golang
cd ~
wget https://golang.org/dl/go1.17.2.linux-amd64.tar.gz
sudo tar -zxvf go1.17.2.linux-amd64.tar.gz -C /usr/local
rm go1.17.2.linux-amd64.tar.gz

echo 'export GOROOT=/usr/local/go' | sudo tee -a /etc/profile
echo 'export PATH=/usr/local/go/bin:$HOME/go/bin:$PATH' | sudo tee -a /etc/profile
source /etc/profile

# Install harbourbridge
git clone https://github.com/cloudspannerecosystem/harbourbridge
cd harbourbridge
go run github.com/cloudspannerecosystem/harbourbridge help

Migra los datos

Usa el siguiente comando para migrar la base de datos de Magento a Spanner:

mysqldump --user='root' --password=$ROOT_PASSWORD magento | go run github.com/cloudspannerecosystem/harbourbridge -driver=mysqldump -dbname=magento

Cómo configurar la herramienta Spanner-cli

go install github.com/cloudspannerecosystem/spanner-cli@latest

3. Convierte Magento para que funcione con Spanner

Ahora que tenemos Magento en ejecución y la instancia de Spanner creada con la base de datos de Magento migró, trabajaremos en la modificación de Magento para trabajar con los datos almacenados en Spanner.

Para convertir la instalación de Magento, se realizarán los siguientes pasos:

  • Clona el proyecto magento-spanner-port
  • Cambia la conexión a Spanner
  • Valida que los detalles del catálogo se propaguen desde Spanner

Clona la bifurcación del proyecto de Magento

Clona el código de la aplicación PHP para Magento que contiene las modificaciones de los módulos Catalog, Wishlist y Cart de la URL de Git que se menciona a continuación.

cd ~
git clone https://github.com/searceinc/magento-spanner-port

El directorio principal debería ser similar al siguiente:

$ ls
go  harbourbridge  magento-spanner-port  magento2

Donde magento2 es la base de código que modificaremos, con el código de magento-spanner-port.

Cambia la conexión a Spanner

Para comprobar si las modificaciones del código se reflejan en la IU, podemos seguir los pasos que se indican a continuación:

Consulta el vínculo de GitHub https://github.com/searceinc/magento-spanner-port para ver una implementación de ejemplo.

  • Solicita la biblioteca cliente de PHP google/cloud-spanner
  • Se agregó el adaptador de Spanner para crear una conexión a Spanner.
  • Configura la instancia de Spanner y la información del servidor.
  • Agrega SpannerInterface y Spanner en el adaptador para implementar la conexión a Spanner.

Primero, debes instalar la biblioteca de PHP de Cloud Spanner con el compositor. En el directorio magento2, ejecuta el siguiente comando:

cd ~/magento2
composer require google/cloud-spanner

Luego, agregamos los archivos del adaptador de Spanner de magento-spanner-port a nuestra base de código de magento2:

~/magento2$ cp -r ../magento-spanner-port/lib/internal/Magento/Framework/DB/Adapter/Spanner vendor/magento/framework/DB/Adapter/.
~/magento2$ ls -l vendor/magento/framework/DB/Adapter/Spanner
total 16
-rw-r--r-- 1 derekdowney derekdowney 10378 Nov  9 21:03 Spanner.php
-rw-r--r-- 1 derekdowney derekdowney  2948 Nov  9 21:03 SpannerInterface.php

Ahora, modifica el archivo DB/Adapter/Spanner/Spanner.php para ingresar la información de conectividad de Spanner para $project_id, $instance y $database:

$ nano vendor/magento/framework/DB/Adapter/Spanner/Spanner.php

class Spanner implements SpannerInterface
{
    /**
     * Google cloud project id
     * @var string
     */
    private $project_id = 'magento';

    /**
     * Google cloud instance name
     * @var string
     */
    private $instance  = 'magento-instance';

    /**
     * Cloud Spanner database name
     * @var string
     */
    private $database  = 'magento';

    /**
     * Is Cloud Spanner emulator
     * @var bool
     */
    private $is_emulator = true;
...
   /**
    * Set database connection adapter
    *
    * @param \Magento\Framework\DB\Adapter\AdapterInterface $conn
    * @return $this
    * @throws \Magento\Framework\Exception\LocalizedException
    */
   public function setConnection(\Magento\Framework\DB\Adapter\AdapterInterface $conn)
   {
       $this->_conn = $conn;
       $this->_select = $this->_conn->select();
       $this->_isOrdersRendered = false;
       return $this;
   }


   /**
     * Set Cloud Spanner database connection adapter
     *
     * @return void
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    private function setSpannerConnection()
    {
        $this->_spanner_conn = new Spanner();
    }

Modifica la clase AbstractDB en Magento para conectarte a Spanner mediante la función de conexión recién creada en el adaptador de Spanner. Agrega las líneas verdes después de las líneas blancas en el archivo. Consulta vendor/magento/framework/Data/Collection/AbstractDb.php.

$ nano vendor/magento/framework/Data/Collection/AbstractDb.php
...
use Psr\Log\LoggerInterface as Logger;
use Magento\Framework\DB\Adapter\Spanner\Spanner;
...
    protected $_conn;

    /**
     * Cloud Spanner connection
     *
     * @var \Magento\Framework\DB\Adapter\Spanner\SpannerAdapterInterface
     */
    protected $_spanner_conn;
...
       if ($connection !== null) {
            $this->setConnection($connection);
        }
        $this->setSpannerConnection();
        $this->_logger = $logger;
...
   /**
     * Retrieve connection object
     *
     * @return AdapterInterface
     */
    public function getConnection()
    {
        return $this->_conn;
    }

   /**
     * Retrieve connection object
     *
     * @return SpannerAdapterInterface
     */
    public function getSpannerConnection()
    {
        return $this->_spanner_conn;
    }
...

Una vez que se establece la conexión, debemos modificar el método de recuperación de datos del adaptador de MySQL al adaptador de Spanner . Modifica el método _loadAttributes en AbstractCollection para conectarte a Spanner y recuperar los datos de Spanner. Reemplaza la línea roja por las líneas en verde.

Consulta /app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php.

$ nano ./vendor/magento/module-eav/Model/Entity/Collection/AbstractCollection.php

use Magento\Framework\Exception\LocalizedException;
use Google\Cloud\Spanner\SpannerClient;

...
               try {
                    if (is_array($selects)) {
                        $select = implode(' UNION ALL ', $selects);
                    } else {
                        $select = $selects;
                    }
                   $values = $this->getConnection()->fetchAll($select);
                   $con = $this->getSpannerConnection();

                    /**
                     * Cloud Spanner follows strict type so cast the columns in common type
                     */
                    $select = $con->addCast($select, "`t_d`.`value`", 'string');
                    $select = $con->addCast($select, "`t_s`.`value`", 'string');
                    $select = $con->addCast($select, "IF(t_s.value_id IS NULL, t_d.value, t_s.value)", 'string');
                    
                    $values = $con->fetchAll($select);

...

Valida que los detalles del catálogo se propaguen desde Spanner

Eso es todo. Ahora, puedes ir a tu instalación de Magento en el navegador y verificar que se carguen los datos.

Por ejemplo, estas son las entradas del catálogo para relojes:

13b54ba4482408fc.png

Modificar los datos de Spanner a través de la terminal de uno de los productos y consultar los datos a través de la terminal para confirmar la modificación en Spanner

$ spanner-cli -pmagento -i magento-instance -d magento
spanner> SELECT * FROM catalog_product_entity_varchar WHERE value LIKE "Aim Analog%";
+----------+--------------+----------+-----------+--------------------+
| value_id | attribute_id | store_id | entity_id | value              |
+----------+--------------+----------+-----------+--------------------+
| 390      | 73           | 0        | 36        | Aim Analog Watch |
+----------+--------------+----------+-----------+--------------------+
1 rows in set (80.711542ms)

spanner> UPDATE catalog_product_entity_varchar SET value = "Aim Analog Spanner" WHERE value_id=390;
Query OK, 1 rows affected (0.19 sec)

spanner> SELECT * FROM catalog_product_entity_varchar WHERE value_id=390;
+----------+--------------+----------+-----------+--------------------+
| value_id | attribute_id | store_id | entity_id | value              |
+----------+--------------+----------+-----------+--------------------+
| 390      | 73           | 0        | 36        | Aim Analog Spanner |
+----------+--------------+----------+-----------+--------------------+
1 rows in set (80.711542ms)

Ahora, vuelve a cargar la pantalla para confirmar que el nombre del reloj cambió a “Aim Analog Spanner”, según se actualizó en la terminal de Spanner.

63a9c7b065c7051f.png

4. Felicitaciones

Felicitaciones. Conectaste correctamente el módulo de catálogo de Magento para trabajar con Spanner. No es una integración completa, pero ahora conoces los elementos para conectar una aplicación de PHP como Magento a una instancia de Spanner.

Realice una limpieza

Cuando se complete la configuración y validación de la POC, te recomendamos que borres los recursos de GCP creados durante el proceso. Esto incluiría la máquina virtual de Compute Engine, así como una instancia de Cloud Spanner si decides usar una en lugar del emulador.

Próximos pasos

Este es solo un modelo de prototipo para una prueba de concepto de Spanner.

Si quieres obtener más información para trabajar con Spanner y las tecnologías que aprovechamos en este codelab, estos son algunos recursos adicionales: