Magento와 Cloud Spanner 통합

1. 소개

424db48d9db91638.png

Magento를 Cloud Spanner 백엔드와 통합

Magento는 널리 사용되는 PHP 기반 오픈소스 전자상거래 플랫폼으로, MySQL에 데이터를 저장합니다.

이 Codelab은 카탈로그 모듈에 MySQL 대신 Cloud Spanner를 활용하기 위한 개념 증명입니다. 이는 Magento 또는 기타 PHP 애플리케이션을 Spanner와 통합, 테스트, 배포하는 데 관심이 있는 모든 사용자에게 유용합니다.

Spanner는 관계형 데이터베이스 모델의 이점과 비관계형 수평적 확장성을 결합한 Google Cloud의 완전 관리형 엔터프라이즈급 분산형 데이터베이스입니다. 또한 글로벌 온라인 트랜잭션 처리 배포, SQL 시맨틱스, 고가용성 수평 확장, 트랜잭션 일관성을 지원하도록 설계되었습니다. Spanner는 대량의 데이터를 처리할 수 있습니다. 대규모 애플리케이션에 국한되지 않고 RDBMS가 필요한 모든 워크로드에 단일 데이터베이스 엔진을 표준화할 수 있습니다. Spanner는 99.999% SLA 가용성과 함께 계획된 유지보수 또는 리전 오류에 대해 제로 다운타임을 제공합니다. 고가용성과 확장성을 제공하여 최신 애플리케이션을 지원합니다.

학습할 내용

  • GCE에 Magento를 설치하는 방법
  • Spanner 에뮬레이터 설정 방법
  • HarbourBridge를 사용하여 기존 MySQL 스키마를 Spanner로 마이그레이션하는 방법
  • 데이터베이스 백엔드가 Spanner와 연동되도록 MySQL을 사용하는 Magento와 같은 PHP 애플리케이션을 통합하기 위해 변경해야 하는 사항

빌드할 항목

이 Codelab에서는 Magento와 Spanner를 통합하는 방법을 중점적으로 설명합니다. 코드 블록과 설정 안내는 복사하여 붙여넣을 수 있도록 제공되지만 자세히 설명되지는 않습니다.

이 Codelab에서는 Magento를 Spanner와 통합하는 작업을 시작합니다. 실습할 내용은 다음과 같습니다.

필요한 항목

  • 결제 계정에 연결된 Google Cloud 프로젝트입니다.
  • PHP, Linux, Apache 구성에 대한 지식이 있으면 좋습니다.
  • Magento 환경이 도움이 되지만 필수는 아닙니다.

2. GCE 인스턴스 준비

GCE 인스턴스 만들기

여기에 설명된 단계에 따라 Google Cloud Platform에서 Compute Engine 인스턴스를 만듭니다.

GCE 인스턴스를 만들 때 인스턴스 유형을 e2-standard-2로, 부팅 디스크 크기를 20GB로 변경합니다. 모두 기본값으로 둘 수 있지만, Magento의 웹 인터페이스를 활용할 것이므로 'HTTP 트래픽 허용' 및 'HTTP 트래픽 허용'을 선택해야 합니다.

이렇게 하면 공유 코어 인스턴스가 아니며 vCPU 2개, RAM 8GB, 디스크 공간 20GB가 있는 머신 유형이 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 설치

기본 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 서버를 설치하라는 대화형 프롬프트가 표시됩니다. 다음 옵션 중 하나를 선택합니다.

  • MySQL 서버 및 클러스터
  • mysql-5.7
  • 확인

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://&lt;GCEexternalIP&gt;/&lt;adminuri&gt;

GCEexternalIP는 Cloud 콘솔에서 확인할 수 있습니다.

3947f1164e1d5409.png

관리 패널의 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 리드미에는 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 연결 변경
  • 카탈로그 세부정보가 Spanner에서 채워졌는지 확인

Magento 프로젝트의 포크 클론

아래 언급된 Git URL에서 카탈로그, 위시리스트 및 장바구니 모듈에 대한 수정사항이 포함된 Magento용 PHP 애플리케이션 코드를 복제합니다.

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

홈 디렉터리는 다음과 같이 표시됩니다.

$ ls
go  harbourbridge  magento-spanner-port  magento2

여기서 magento2magento-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

그런 다음 magento-spanner-port의 Spanner 어댑터 파일을 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();
    }

이제 Spanner 어댑터 내에서 새로 만든 Connection 함수를 사용하여 Spanner에 연결하도록 Magento 내의 AbstractDB 클래스를 수정합니다. 파일의 흰색 선 다음에 녹색 줄을 추가합니다. 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);

...

카탈로그 세부정보가 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 POC의 프로토타입 모델일 뿐입니다.

Spanner 사용 방법과 이 Codelab에서 활용한 기술에 대해 자세히 알아보려면 다음 추가 리소스를 참고하세요.