Como integrar o Magento ao Cloud Spanner

1. Introdução

424db48d9db91638.png

Integrar o Magento a um back-end do Cloud Spanner

O Magento é uma plataforma de e-commerce de código aberto baseada em PHP muito popular que armazena dados no MySQL.

Este codelab é uma prova de conceito para aproveitar o Cloud Spanner em vez do MySQL no módulo de catálogo. Isso é útil para quem tem interesse em integrar, testar e implantar o Magento ou outros aplicativos PHP com o Spanner.

O Spanner é o banco de dados totalmente gerenciado, distribuído, de nível empresarial e consistente do Google Cloud que combina os benefícios do modelo de banco de dados relacional com a escalonabilidade horizontal não relacional. Ele foi projetado para oferecer suporte a implantações globais de processamento de transações on-line, semântica SQL, escalonamento horizontal altamente disponível e consistência transacional. O Spanner consegue processar grandes volumes de dados. O uso não se limita a aplicativos grandes, mas permite a padronização de um único mecanismo de banco de dados para todas as cargas de trabalho que exigem RDBMS. Com o Spanner, não há tempo de inatividade para manutenção planejada nem falhas de região e ele oferece um SLA de disponibilidade de 99,999%. Ele oferece suporte a aplicativos modernos com alta disponibilidade e escalonabilidade.

O que você vai aprender

  • Como instalar o Magento no GCE
  • Como configurar o emulador do Spanner
  • Como migrar um esquema MySQL para o Spanner usando o HarbourBridge
  • O que você precisa mudar para integrar aplicativos PHP, como o Magento, que usam o MySQL para o back-end do banco de dados e trabalhar com o Spanner

O que você vai criar

Este codelab é focado na integração do Magento com o Spanner. Blocos de código e instruções de configuração são fornecidos para você copiar e colar, mas não são abordados em detalhes.

Neste codelab, você vai começar a integrar o Magento com o Spanner. Você vai:

O que é necessário

  • Um projeto na nuvem do Google Cloud conectado a uma conta de faturamento.
  • Conhecimento de PHP, Linux e configuração do Apache é um diferencial.
  • A experiência com o Magento é útil, mas não é obrigatória.

2. Como preparar a instância do GCE

Criar a instância do GCE

Crie uma instância do Compute Engine no Google Cloud Platform seguindo as etapas mencionadas aqui.

Ao criar a instância do GCE, mude o tipo de instância para e2-standard-2 e o tamanho do disco de inicialização para 20 GB. Você pode deixar tudo como padrão, mas selecione "Permitir tráfego HTTP" e "Permitir tráfego HTTPS", já que vamos usar a interface da Web do Magento.

Isso resulta em um tipo de máquina e2-standard-2, que não é uma instância de núcleo compartilhado e tem 2 vCPUs, 8 GB de RAM e 20 GB de espaço em disco.

O sistema operacional é o Debian 10. A criação da instância pode levar alguns minutos.

Depois de criar, faça login clicando em "SSH" no Console do Cloud:

4bf915ef8d37c942.png

Isso vai abrir uma nova janela do navegador e colocar você em um terminal.

Instalar o software de pré-requisito

O Magento precisa de alguns softwares pré-requisitos instalados antes de ser executado. Especificamente, você vai instalar o PHP, o Elastic, o MySQL e o Apache, conforme detalhado abaixo.

  1. Instale alguns pacotes necessários.
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. Instale os módulos PHP necessários para o 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. Instalar o Elasticsearch e iniciar o serviço
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. Instalar o MySQL

Você está instalando o MySQL para instalar o esquema padrão do Magento. Depois, você vai migrar o esquema para o Spanner usando o HarbourBridge.

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

sudo dpkg -i mysql-apt-config*

O comando dpkg acima vai abrir um prompt interativo para instalar o servidor MySQL 5.7. Selecione as opções:

  • Servidor e cluster do MySQL
  • mysql-5.7
  • Ok

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. Instale o Apache2
sudo apt -y install apache2

sudo a2enmod proxy_fcgi rewrite

Instalar e configurar o Magento2

O projeto do Magento Commerce Cloud inclui um esquema de banco de dados e serviços para acessar totalmente o site e a loja do Magento.

A maneira mais fácil de instalar e executar é seguir as instruções do Magento para instalar usando o Composer:

  1. Instale a versão 2.4.2 do Magento usando o Composer. O Magento 2 exige a versão 1.x do Composer. Talvez você veja alguns avisos sobre a descontinuação do suporte para essa versão.
composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition=2.4.2 magento2
  1. Definir permissões de pasta
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. Configure o host virtual do Magento criando /etc/apache2/sites-available/magento.conf com o conteúdo abaixo.
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. Crie os links simbólicos e reinicie o 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. Criar o banco de dados e o usuário do Magento no 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. Verifique seu espaço de trabalho local. Para verificar se o ambiente local está hospedando o servidor, acesse a loja usando o URL base transmitido no comando de instalação. Neste exemplo, é possível acessar a loja local do Magento usando os seguintes formatos de URL:
  • http://<GCEexternalIP>/
  • http://<GCEexternalIP>/<adminuri>

O GCEexternalIP pode ser encontrado no Cloud Console:

3947f1164e1d5409.png

Para mudar o URI do painel de administração, use este comando para localizá-lo:

php bin/magento info:adminuri
  1. Desativar o cache de página inteira Para fins de desenvolvimento, é possível desativar o cache de página inteira do Magento2. Isso permite modificar os dados no Spanner e refletir as mudanças no site sem ser afetado por valores em cache.
php bin/magento cache:disable full_page

Configurar o Spanner

Instalar o emulador do Spanner

O SDK do Cloud oferece um emulador local na memória, que você pode usar para desenvolver e testar seus aplicativos sem custo financeiro sem criar um projeto do GCP ou uma conta de faturamento. À medida que o emulador armazena dados apenas na memória, todo o estado, incluindo dados, esquema e configurações, é perdido na reinicialização. O emulador oferece as mesmas APIs que o serviço de produção do Spanner e destina-se ao desenvolvimento e teste locais, não para implantações de produção.

Use o link abaixo para mais informações sobre instalação, uso e implantação do emulador:

Como usar o emulador do 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

Migrar o MySQL do Magento para o Spanner

Antes de integrar o Spanner, vamos usar uma ferramenta chamada HarbourBridge para converter o banco de dados MySQL criado como parte da instalação do Magento acima para o Spanner.

Basicamente, o HarbourBridge oferece um fluxo de trabalho automatizado para carregar o conteúdo de um banco de dados MySQL ou PostgreSQL no Spanner. Ele não requer configuração: não é preciso escrever manifestos ou mapas de dados. Em vez disso, ele importa o banco de dados de origem, cria um esquema do Spanner, cria um novo banco de dados do Spanner preenchido com dados do banco de dados de origem e gera um relatório de avaliação detalhado. O HarbourBridge foi criado para carregar bancos de dados de até algumas dezenas de GB para fins de avaliação, não para migrações em grande escala.

O HarbourBridge inicializa a migração para o Spanner usando um banco de dados de origem MySQL ou PostgreSQL para que você comece a trabalhar rapidamente no Spanner. Ele gera um relatório de avaliação com uma pontuação geral de adequação da migração para o Spanner, uma análise tabela por tabela de mapeamentos de tipos e uma lista de recursos usados no banco de dados de origem que não são compatíveis com o Spanner.

O HarbourBridge pode ser usado com o emulador do Spanner ou diretamente com uma instância do Spanner.

O README do HarbourBridge contém um guia de início rápido detalhado para usar a ferramenta com uma instância do Spanner.

Instalar o HarbourBridge

Faça o download e instale a ferramenta na sua máquina. É necessário instalar o golang para que isso funcione. Pode levar um tempo para instalar todos os módulos necessários em uma instância nova sem o Go configurado anteriormente.

# 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

Migre os dados

Use o comando a seguir para migrar o banco de dados do Magento para o Spanner:

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

Configurar a ferramenta spanner-cli

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

3. Converter o Magento para trabalhar com o Spanner

Agora que o Magento está em execução e a instância do Spanner foi criada com o banco de dados do Magento migrado, vamos modificar o Magento para trabalhar com os dados armazenados no Spanner.

As etapas a seguir serão realizadas para converter a instalação do Magento:

  • Clone o projeto magento-spanner-port.
  • Mudar a conexão para o Spanner
  • Validar se os detalhes do catálogo foram preenchidos pelo Spanner

Clonar o fork do projeto Magento

Clone o código do aplicativo PHP para Magento, que contém as modificações dos módulos "Catálogo", "Lista de desejos" e "Carrinho" do URL do Git mencionado abaixo.

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

Seu diretório inicial vai ficar assim:

$ ls
go  harbourbridge  magento-spanner-port  magento2

Em que magento2 é a base de código que vamos modificar, usando o código de magento-spanner-port.

Mudar a conexão para o Spanner

Para verificar se as modificações no código aparecem na interface, siga as etapas abaixo:

Consulte o link do GitHub https://github.com/searceinc/magento-spanner-port para ver um exemplo de implementação.

  • Exigir a biblioteca de cliente do PHP google/cloud-spanner
  • Adicione o adaptador do Spanner para criar uma conexão com o Spanner.
  • Configure as informações da instância e do servidor do Spanner.
  • Adicione SpannerInterface e Spanner ao adaptador para implementar a conexão com o Spanner.

Primeiro, instale a biblioteca PHP cloud-spanner usando o Composer. No diretório magento2, execute este comando:

cd ~/magento2
composer require google/cloud-spanner

Em seguida, adicione os arquivos do adaptador do Spanner de magento-spanner-port à base de código 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

Agora, modifique o arquivo DB/Adapter/Spanner/Spanner.php para inserir as informações de conectividade do Spanner para $project_id, $instance e $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();
    }

Modifique a classe AbstractDB no Magento para se conectar ao Spanner usando a função Connection recém-criada no adaptador do Spanner. Adicione as linhas verdes depois das brancas no arquivo. Consulte 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;
    }
...

Depois que a conexão for estabelecida, será necessário modificar o método de busca de dados do adaptador do MySQL para o adaptador do Spanner . Modifique o método _loadAttributes em AbstractCollection para se conectar ao Spanner e buscar os dados dele. Substitua a linha vermelha pelas linhas em verde.

Consulte /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);

...

Validar se os detalhes do catálogo foram preenchidos pelo Spanner

Pronto! Agora, acesse a instalação do Magento no navegador e verifique se os dados estão sendo carregados.

Por exemplo, estas são as entradas de catálogo para relógios:

13b54ba4482408fc.png

Modifique os dados do Spanner no terminal para um dos produtos e consulte os dados no terminal para confirmar a modificação no 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)

Agora, recarregue a tela para confirmar que o nome do relógio mudou para "Aim Analog Spanner", conforme atualizado pelo terminal do Spanner.

63a9c7b065c7051f.png

4. Parabéns

Parabéns! Você conectou o módulo de catálogo do Magento para trabalhar com o Spanner. Não é uma integração completa, mas agora você conhece os elementos para conectar um aplicativo PHP, como o Magento, a uma instância do Spanner.

Limpar

Quando a configuração e a validação do POC forem concluídas, talvez você queira excluir os recursos do GCP criados durante o processo. Isso inclui a máquina virtual do Compute Engine e uma instância do Cloud Spanner, caso você decida usar uma em vez do emulador.

A seguir

Este é apenas um modelo de protótipo para uma POC do Spanner.

Para saber mais sobre como trabalhar com o Spanner e as tecnologias que usamos neste codelab, confira estes recursos adicionais: