AEM as a Cloud Service のリーダーインスタンスでのジョブの実行方法

AEM as a Cloud Service の一部として、AEM オーサーサービスのリーダーインスタンスでのジョブの実行方法と、1 回のみの実行の設定方法について説明します。

Sling ジョブは、バックグラウンドで動作する非同期タスクで、システムまたはユーザーがトリガーするイベントを処理するように設計されています。デフォルトでは、これらのジョブはクラスター内のすべてのインスタンス(ポッド)に均等に分散されます。

詳しくは、Apache Sling のイベントとジョブの取り扱いを参照してください。

ジョブの作成と処理

デモの目的で、ジョブプロセッサーにメッセージをログに記録するように指示するシンプルなジョブ ​を作成しましょう。

ジョブの作成

次のコードを使用して、Apache Sling ジョブを​ 作成 ​します。

package com.adobe.aem.guides.wknd.core.sling.jobs.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.sling.event.jobs.JobManager;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(immediate = true)
public class SimpleJobCreaterImpl {

    private static final Logger log = LoggerFactory.getLogger(SimpleJobCreaterImpl.class);

    // Define the topic on which the job will be created
    protected static final String TOPIC = "wknd/simple/job/topic";

    // Inject a JobManager
    @Reference
    private JobManager jobManager;

    @Activate
    protected final void activate() throws Exception {
        log.info("SimpleJobCreater activated successfully");
        createJob();
        log.info("SimpleJobCreater created a job");
    }

    private void createJob() {
        // Create a job and add it on the above defined topic
        Map<String, Object> jobProperties = new HashMap<>();
        jobProperties.put("action", "log");
        jobProperties.put("message", "Job metadata is: Created in activate method");
        jobManager.addJob(TOPIC, jobProperties);
    }
}

上記のコードで注意すべき重要なポイントは次のとおりです。

  • ジョブペイロードには、actionmessage という 2 つのプロパティがあります。
  • JobManageraddJob(...) メソッドを使用すると、ジョブがトピック wknd/simple/job/topic に追加されます。

ジョブの処理

次のコードを使用して、上記の Apache Sling ジョブを​ 処理 ​します。

package com.adobe.aem.guides.wknd.core.sling.jobs.impl;

import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(service = JobConsumer.class, property = {
        JobConsumer.PROPERTY_TOPICS + "=" + SimpleJobCreaterImpl.TOPIC
}, immediate = true)
public class SimpleJobConsumerImpl implements JobConsumer {

    private static final Logger log = LoggerFactory.getLogger(SimpleJobConsumerImpl.class);

    @Override
    public JobResult process(Job job) {
        // Get the action and message properties
        String action = job.getProperty("action", String.class);
        String message = job.getProperty("message", String.class);

        // Log the message
        if ("log".equals(action)) {
            log.info("Processing WKND Job, and {}", message);
        }

        // Return a successful result
        return JobResult.OK;
    }

}

上記のコードで注意すべき重要なポイントは次のとおりです。

  • SimpleJobConsumerImpl クラスは、JobConsumer インターフェイスを実装しています。
  • これは、トピック wknd/simple/job/topic からのジョブを使用するために登録されたサービスです。
  • process(...) メソッドは、ジョブペイロードの message プロパティをログに記録してジョブを処理します。

デフォルトのジョブ処理

上記のコードを AEM as a Cloud Service 環境にデプロイし、複数の AEM オーサー JVM を持つクラスターとして動作する AEM オーサーサービスで実行すると、ジョブは各 AEM オーサーインスタンス(ポッド)で 1 回実行されます。つまり、作成したジョブの数はポッドの数と一致します。ポッドの数は常に 1 個以上になります(非 RDE 環境の場合)が、AEM as a Cloud Service の内部リソース管理に基づいて変動します。

wknd/simple/job/topic は AEM のメインキューに関連付けられて、使用可能なすべてのインスタンスにジョブを分散するので、ジョブは各 AEM オーサーインスタンス(ポッド)で実行されます。

リソースや外部サービスの作成や更新など、ジョブが状態の変更を担当している場合は、これが問題になることがよくあります。

AEM オーサーサービスでジョブを 1 回のみ実行する場合は、次に説明するジョブキューの設定を追加します。

これを確認するには、Cloud Manager で AEM オーサーサービスのログを確認します。

すべてのインスタンスで処理されるジョブ

以下が表示されます。

<DD.MM.YYYY HH:mm:ss.SSS> [cm-pxxxx-exxxx-aem-author-68775db964-nxxcx] *INFO* [sling-oak-observation-15] org.apache.sling.event.impl.jobs.queues.JobQueueImpl.<main queue> Starting job queue <main queue>
<DD.MM.YYYY HH:mm:ss.SSS> INFO [com.adobe.aem.guides.wknd.core.sling.jobs.impl.SimpleJobConsumerImpl] Processing WKND Job, and Job metadata is: Created in activate method

<DD.MM.YYYY HH:mm:ss.SSS> [cm-pxxxx-exxxx-aem-author-68775db964-r4zk7] *INFO* [sling-oak-observation-11] org.apache.sling.event.impl.jobs.queues.JobQueueImpl.<main queue> Starting job queue <main queue>
<DD.MM.YYYY HH:mm:ss.SSS> INFO [com.adobe.aem.guides.wknd.core.sling.jobs.impl.SimpleJobConsumerImpl] Processing WKND Job, and Job metadata is: Created in activate method

ログエントリは 2 つあり、AEM オーサーインスタンス(68775db964-nxxcx68775db964-r4zk7)ごとに 1 つずつあり、各インスタンス(ポッド)がジョブを処理したことを示しています。

リーダーインスタンスでのジョブの実行方法

AEM オーサーサービスでジョブを 1 回のみ ​実行するには、順序付き ​タイプの新しい Sling ジョブキューを作成し、ジョブトピック(wknd/simple/job/topic)をこのキューに関連付けます。この設定では、リーダーの AEM オーサーインスタンス(ポッド)のみがジョブを処理できます。

AEM プロジェクトの ui.config モジュールで、OSGi 設定ファイル(org.apache.sling.event.jobs.QueueConfiguration~wknd.cfg.json)を作成し、ui.config/src/main/content/jcr_root/apps/wknd/osgiconfig/config.author フォルダーに保存します。

{
    "queue.name":"WKND Queue - ORDERED",
    "queue.topics":[
      "wknd/simple/job/topic"
    ],
    "queue.type":"ORDERED",
    "queue.retries":1,
    "queue.maxparallel":1.0
  }

上記の設定で注意すべき重要なポイントは次のとおりです。

  • キュートピックは wknd/simple/job/topic に設定されています。
  • キュータイプは ORDERED に設定されています。
  • 並列ジョブの最大数は 1 に設定されています。

上記の設定をデプロイすると、ジョブはリーダーインスタンスによって排他的に処理され、AEM オーサーサービス全体で 1 回のみ実行されるようになります。

<DD.MM.YYYY HH:mm:ss.SSS> [cm-pxxxx-exxxx-aem-author-7475cf85df-qdbq5] *INFO* [FelixLogListener] Events.Service.org.apache.sling.event Service [QueueMBean for queue WKND Queue - ORDERED,7755, [org.apache.sling.event.jobs.jmx.StatisticsMBean]] ServiceEvent REGISTERED
<DD.MM.YYYY HH:mm:ss.SSS> INFO [com.adobe.aem.guides.wknd.core.sling.jobs.impl.SimpleJobConsumerImpl] Processing WKND Job, and Job metadata is: Created in activate method
<DD.MM.YYYY HH:mm:ss.SSS> [com.adobe.aem.guides.wknd.core.sling.jobs.impl.SimpleJobConsumerImpl] Processing WKND Job, and Job metadata is: Created in activate method
recommendation-more-help
4859a77c-7971-4ac9-8f5c-4260823c6f69