Magento と Cloud Spanner の統合

1. はじめに

424db48d9db91638.png

Magento と Cloud Spanner バックエンドの統合

Magento は、MySQL にデータを保存する PHP ベースのオープンソース e コマース プラットフォームです。

この Codelab は、Catalog モジュールに MySQL ではなく Cloud Spanner を活用するための概念実証です。Magento やその他の PHP アプリケーションを Spanner と統合、テスト、デプロイすることに関心があるすべての方に役立ちます。

Spanner は、Google Cloud のフルマネージドでエンタープライズ グレードの分散型で整合性のあるデータベースで、リレーショナル データベース モデルの利点と非リレーショナルの水平方向のスケーラビリティを兼ね備えています。グローバルなオンライン トランザクション処理のデプロイ、SQL セマンティクス、高可用性の水平スケーリング、トランザクションの整合性をサポートするように設計されています。Spanner は大量のデータを処理できます。大規模なアプリケーションに限定されず、RDBMS を必要とするすべてのワークロードに対して単一のデータベース エンジンを標準化できます。Spanner は、計画的なメンテナンスやリージョン障害に対してゼロ ダウンタイムを提供し、可用性 SLA 99.999% を実現します。高可用性とスケーラビリティを提供することで、最新のアプリケーションをサポートします。

学習内容

  • GCE に Magento をインストールする方法
  • Spanner エミュレータの設定方法
  • HarbourBridge を使用して既存の MySQL スキーマを Spanner に移行する方法
  • データベース バックエンドに MySQL を使用する Magento などの PHP アプリケーションを Spanner と統合するために変更する必要がある点

作成するアプリの概要

この Codelab では、Magento と Spanner のインテグレーションに重点を置いています。コードブロックと設定手順が用意されているため、コピーして貼り付けることができますが、ここでは詳しく説明しません。

この Codelab では、Magento と Spanner の統合を開始します。次のことを行います。

必要なもの

  • 請求先アカウントに接続されている Google Cloud プロジェクト。
  • PHP、Linux、Apache の構成に関する知識があれば大丈夫です。
  • Magento の使用経験は役立ちますが、必須ではありません。

2. GCE インスタンスの準備

GCE インスタンスを作成する

こちらの手順に沿って、Google Cloud Platform で Compute Engine インスタンスを作成します。

GCE インスタンスを作成するときに、インスタンス タイプを e2-standard-2 に、ブートディスクのサイズを 20 GB に変更します。すべてをデフォルトのままにしてかまいませんが、[HTTP トラフィックを許可する] を選択してください。Magento のウェブ インターフェースを利用するため、[HTTPS トラフィックを許可する] を選択します。

これにより、共有コア インスタンスではなく、2 個の vCPU、8 GB の RAM、20 GB のディスク容量を備えたマシンタイプ e2-standard-2 になります。

オペレーティング システムは Debian 10 です。インスタンスの作成には 1 ~ 2 分かかる場合があります。

作成したら、[SSH] をクリックしてログインしますCloud コンソールで次の操作を行います。

4bf915ef8d37c942.png

新しいブラウザ ウィンドウが開き、ターミナルが表示されます。

前提条件のソフトウェアをインストールする

Magento を実行するには、前提条件となるソフトウェアをインストールする必要があります。具体的には、以下で説明するように、PHP、Elastic、MySQL、Apache をインストールします。

  1. 必要なパッケージをいくつかインストールします。
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. Magento に必要な PHP モジュールをインストールします。
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. Elasticsearch をインストールしてサービスを開始する
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. MySQL のインストール

デフォルトの Magento スキーマをインストールするために MySQL をインストールします。後で、HarbourBridge を使用してスキーマを Spanner に移行します。

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

sudo dpkg -i mysql-apt-config*

上記の dpkg コマンドは、MySQL 5.7 Server をインストールするように促すインタラクティブ プロンプトを表示します。オプションを選択します。

  • 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. Apache2 をインストールする
sudo apt -y install apache2

sudo a2enmod proxy_fcgi rewrite

Magento2 をインストールして構成する

Magento Commerce Cloud プロジェクトには、Magento のサイトと店舗に完全にアクセスするためのデータベース スキーマとサービスが含まれています。

これをインストールして実行する最も簡単な方法は、Magento の手順に沿って Composer を使用してインストールすることです。

  1. Composer を使用して Magento バージョン 2.4.2 をインストールします。Magento 2 には Composer 1.x バージョンが必要です。このバージョンのサポートが終了することに関する警告が表示されることがあります。
composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition=2.4.2 magento2
  1. フォルダの権限を設定する
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. 以下の内容で /etc/apache2/sites-available/magento.conf を作成し、Magento 仮想ホストを構成します。
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. シンボリック リンクを作成し、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. MySQL で Magento のデータベースとユーザーを作成する
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. ローカル ワークスペースを確認する ローカル環境がサーバーをホストしていることを確認するには、インストール コマンドで渡したベース URL を使用してストアにアクセスします。この例では、以下の URL 形式を使用してローカルの Magento ストアにアクセスできます。
  • http://&lt;GCEexternalIP&gt;/
  • http://&lt;GCEexternalIP&gt;/&lt;adminuri&gt;

GCEexternalIP は Cloud コンソールで確認できます。

3947f1164e1d5409.png

管理パネルの URI を変更するには、次のコマンドを使用して URI を検索します。

php bin/magento info:adminuri
  1. フルページ キャッシュを無効にする 開発目的で、Magento2 のフルページ キャッシュを無効にできます。これにより、Spanner でデータを変更し、キャッシュに保存された値の影響を受けずにウェブサイトに反映させることができます。
php bin/magento cache:disable full_page

Spanner を設定する

Spanner エミュレータをインストールする

Cloud SDK が提供するローカルのインメモリ エミュレータを使用すると、GCP プロジェクトや請求先アカウントを作成しなくても、アプリケーションを無料で開発してテストできます。エミュレータはデータをメモリにのみ保存するため、データ、スキーマ、構成を含むすべての状態が再起動時に失われます。このエミュレータは Spanner の本番環境サービスと同じ API を提供し、ローカルでの開発とテストを目的としており、本番環境へのデプロイ用ではありません。

エミュレータのインストール、使用、デプロイについて詳しくは、以下のリンクをご利用ください。

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

Magento MySQL を Spanner に移行する

Spanner の統合について説明する前に、HarbourBridge というツールを使用して、上記の Magento のインストールの一部として作成された MySQL データベースを Spanner に変換します。

HarbourBridge の中核となるのは、既存の MySQL または PostgreSQL データベースのコンテンツを Spanner に読み込む自動ワークフローです。構成は不要で、マニフェストやデータマップを書き込む必要もありません。代わりに、ソース データベースをインポートして Spanner スキーマを構築し、ソース データベースのデータを格納した新しい Spanner データベースを作成して、詳細な評価レポートを生成します。HarbourBridge は、評価目的で最大数十 GB のデータベースを読み込むことを目的としており、本格的な移行には適していません。

HarbourBridge は、既存の MySQL または PostgreSQL ソース データベースを使用して、Spanner への移行の初期段階をブートストラップし、Spanner を迅速に稼働させます。Spanner の全体的な移行適合性スコア、タイプ マッピングのテーブルごとの分析、ソース データベースで Spanner でサポートされていない機能のリストを含む評価レポートを生成します。

HarbourBridge は Spanner エミュレータで使用できます。直接 Spanner インスタンスと一緒に使用することもできます。

HarbourBridge README には、Spanner インスタンスでこのツールを使用するための詳細なクイックスタート ガイドが含まれています。

HarbourBridge をインストールする

マシンにツールをダウンロードしてインストールします。そのためには、golang をインストールする必要があります。Go を事前に設定していない場合、必要なすべてのモジュールを新しいインスタンスにインストールするのに時間がかかることがあります。

# 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

データを移行する

次のコマンドを使用して、Magento データベースを Spanner に移行します。

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

spanner-cli ツールを設定する

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

3. Spanner で動作するように Magento を変換する

Magento が稼働し、Magento データベースで作成された Spanner インスタンスが移行されたので、Spanner に格納されているデータを操作できるように Magento を変更します。

Magento インストール環境を変換する手順は次のとおりです。

  • magento-spanner-port プロジェクトのクローンを作成します。
  • Spanner への接続を変更する
  • Catalog の詳細が Spanner から入力されていることを確認する

Magento プロジェクトのフォークのクローンを作成する

下記の Git URL から Catalog、Wishlist、Cart モジュールの変更を含む Magento の PHP アプリケーション コードのクローンを作成します。

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

ホーム ディレクトリは次のようになります。

$ ls
go  harbourbridge  magento-spanner-port  magento2

ここで、magento2 は、magento-spanner-port のコードを使用して変更するコードベースです。

Spanner への接続を変更する

コードの変更が UI に反映されているかどうかを確認するには、次の手順を行います。

実装例については、GitHub のリンク https://github.com/searceinc/magento-spanner-port をご覧ください。

  • google/cloud-spanner PHP クライアント ライブラリが必要
  • Spanner への接続を作成するための Spanner アダプタを追加します。
  • Spanner インスタンスとサーバーの情報を構成します。
  • アダプタに SpannerInterface と Spanner を追加して、Spanner への接続を実装します。

まず、Composer を使用して cloud-spanner PHP ライブラリをインストールする必要があります。magento2 ディレクトリで、次のコマンドを実行します。

cd ~/magento2
composer require google/cloud-spanner

次に、Spanner Adapter ファイルを magento-spanner-port から 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

次に、DB/Adapter/Spanner/Spanner.php ファイルを変更して、$project_id、$instance$database の Spanner 接続情報を入力します。

$ 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();
    }

Magento 内の AbstractDB クラスを変更し、Spanner Adapter 内に新しく作成された Connection 関数を使用して Spanner に接続する。ファイル内の白い行の後に緑色の行を追加します。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;
    }
...

接続が確立されたら、MySQL アダプタから Spanner アダプタにデータ取得方法を変更する必要があります。Spanner に接続して Spanner からデータを取得するように、AbstractCollection の _loadAttributes メソッドを変更します。赤い行を緑色の行に置き換えます。

詳しくは、/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);

...

Catalog の詳細が Spanner から入力されていることを確認する

これで、ブラウザで Magento をインストールし、データが読み込まれることを確認します。

たとえば、スマートウォッチのカタログ エントリは次のとおりです。

13b54ba4482408fc.png

いずれかのプロダクトのターミナルで Spanner のデータを変更し、ターミナルでそのデータに対するクエリを実行して 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)

画面を再読み込みして、スマートウォッチの名前が「Aim Analog Spanner」に変わったことを確認します。Spanner ターミナルで 更新されると想定されます

63a9c7b065c7051f.png

4. 完了

これで、Spanner で動作する Magento の Catalog モジュールが正常に接続されました。完全な統合ではありませんが、Magento のような PHP アプリケーションを Spanner インスタンスに接続するための要素については理解できました。

クリーンアップ

POC の設定と検証が完了したら、プロセス中に作成した GCP リソースを削除することをおすすめします。これには、Compute Engine 仮想マシンと、エミュレータの代わりに Cloud Spanner インスタンスを使用する場合が含まれます。

次のステップ

これは Spanner 概念実証のプロトタイプ モデルにすぎません。

Spanner の操作と、この Codelab で使用したテクノロジーの詳細については、以下の追加リソースをご覧ください。