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 の統合を開始します。次のことを行います。

  • Magento がインストールされた GCE インスタンスを設定する
  • Spanner Emulator をインストールする
  • MySQL から Spanner にデータを移行するための HarbourBridge ツールをインストールする
  • Magento コレクションを変更して、Spanner から商品カタログを読み込む

必要なもの

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

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

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

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

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

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

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

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

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 のインストール

MySQL をインストールして、デフォルトの Magento スキーマをインストールします。後で、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 サーバーをインストールするためのインタラクティブなプロンプトが表示されます。次のオプションを選択します。

  • 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://<GCEexternalIP>/
  • http://<GCEexternalIP>/<adminuri>

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 Emulator で使用することも、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 プロジェクトのフォークのクローンを作成する

カタログ モジュール、ウィッシュリスト モジュール、カート モジュールの変更を含む Magento の PHP アプリケーション コードを、以下の Git URL からクローンを作成します。

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 インスタンスとサーバー情報を構成します。
  • Adapter に 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 アダプタにデータ取得方法を変更する必要があります。AbstractCollection の _loadAttributes メソッドを変更して、Spanner に接続し、Spanner からデータを取得します。赤い線を緑色の線に置き換えます。

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

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

63a9c7b065c7051f.png

4. 完了

Magento のカタログ モジュールを Spanner と連携するように接続できました。完全な統合ではありませんが、Magento のような PHP アプリケーションを Spanner インスタンスに接続するための要素については理解できました。

クリーンアップ

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

次のステップ

これは、Spanner の概念実証用のプロトタイプ モデルです。

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