[ 1 ] NodeJSとExpressを使ったマルチコンテナ環境でバッチジョブを実行する.


高いインターネットの採用と浸透は、バックエンドアプリケーションのスケールのために構築するために必要としている.トラフィックに基づいて動的にインフラストラクチャを上下にスケーリングすることは、技術がバリアではなくビジネスのイネーブラとして機能することを保証します.低負荷の時間の縮小は、アイドルサイクルでドルを無駄にしていないことを確認します.成長は技術によって制限されるべきではない
ほとんどの複雑なアプリケーションでは、いくつかの時点でバッチ/cronジョブを書く必要があります.
コンテナアプリケーションとバッチジョブを使用する場合は、次の手順を実行する必要があります.
  • ジョブは1つのコンテナだけで実行する必要があります.
    あなたが毎日12時に走る予定であるバッチ仕事があるならば、配備された容器のうちの1つだけはそれを実行しなければなりません.それ以外の場合、および/または意図しない結果につながる可能性があります.たとえば、支払い会社は、請求書がある顧客に支払い通知を送るバッチ仕事をします.各コンテナがジョブを実行すると、ユーザーはメッセージをスパムになります.
  • ジョブのステータスとキューはコンテナに結び付けてはいけません.
    デザインによって、オーケストラータは現在の負荷に基づいてコンテナを生成または破棄します.ジョブからキューイングジョブのキューイングとステータスは、バッチジョブを実行するコンテナの不可知性をすることができます.
  • 上記の要件を満たすために、我々はRedisの仕事待ち行列と仕事のステータスを持ちます.コンテナはRedisからキューを取得し、ジョブのステータスを取得するように問い合わせます.既に処理中であればジョブを実行しません.
    このチュートリアルでは
  • JavaScript
  • Nodejs
  • Redis
  • この3部シリーズでは、あなたは
  • ジョブをスケジュールするエンドポイントを作成する(その1 )
  • 12 amで実行されるセットアップバッチジョブ(パート2)
  • Redisサポートを用いたGraphSQLの設定
  • スタータープロジェクト


    次のリポジトリをクローンしてください.https://github.com/wednesday-solutions/node-express-batch-jobs-starter . これは完全に機能的なGraphSQLノードエクスプレスサーバーが含まれます.
    注:もしあなたがここでスペックを読むために数分かかることがあります.( https://graphql.org/ )

    ローカルでRedisを設定する


    この手順では、ローカルにRedisをインストールして設定し、アプリケーションが接続できるようにします.を使ってキューを作成します.https://optimalbits.github.io/bull/ ) です.
  • プロセススケジュールジョブ
  • 真夜中に仕事を実行する
  • 自動通知を毎分公開する
  • ステップ1
    Redisをローカルにインストールします.Macを使用している場合は、それをインストールするhomebrewを使用することができます
    brew update
    brew install redis
    
    以下のコマンドを使用してRedisを起動します.
    brew services start redis
    
    Windows/Linuxシステム用のRedisをインストールして設定するには、関連するリンクを見てください
  • https://flaviocopes.com/redis-installation/

  • ステップ2
    インストールbull and string-replace-loader
    yarn add bull string-replace-loader
    
    このルールをWebPackに追加します.サーバ.設定.jsこの雄牛なしでは、見つけることができません...Luaファイル.
    module.exports = (options = {}) => ({
      mode: options.mode,
      entry: options.entry,
      optimization: options.optimization,
      ...,
      externals: {
        bull: 'commonjs2 bull'
      },
      ...,
      module: {
        rules: [
          ...,
          {
            test: /node_modules\/bull\/lib\/commands\/index\.js$/,
            use: {
              loader: 'string-replace-loader',
              options: {
                search: '__dirname',
                replace: `"${path.dirname(require.resolve('bull'))}/lib/commands"`
              }
            }
          },
          ...,
    
    ステップ3
    次の値を.env.local ファイル
    REDIS_DOMAIN=localhost
    REDIS_PORT=6379
    
    ステップ4
    クリエイトserver/utils/queue.js ファイル
    touch server/utils/queue.js
    
    以下のコードを追加します
    import Bull from 'bull';
    import moment from 'moment';
    const queues = {};
    
    // 1
    export const QUEUE_NAMES = {
      SCHEDULE_JOB: 'scheduleJob'
    };
    
    // 2
    export const QUEUE_PROCESSORS = {
      [QUEUE_NAMES.SCHEDULE_JOB]: (job, done) => {
        console.log(`${moment()}::Job with id: ${job.id} is being executed.\n`, {
          message: job.data.message
        });
        done();
      }
    };
    // 3
    export const initQueues = () => {
      console.log('init queues');
      Object.keys(QUEUE_PROCESSORS).forEach(queueName => {
          // 4
          queues[queueName] = getQueue(queueName);
          // 5
          queues[queueName].process(QUEUE_PROCESSORS[queueName]);
      });
    };
    
    export const getQueue = queueName => {
      if (!queues[queueName]) {
        queues[queueName] = new Bull(queueName, `redis://${process.env.REDIS_DOMAIN}:${process.env.REDIS_PORT}`);
        console.log('created queue: ', queueName, `redis://${process.env.REDIS_DOMAIN}:${process.env.REDIS_PORT}`);
      }
      return queues[queueName];
    };
    
  • キュー名の定数を作成する
  • プロセッサをキューに関連づける.
  • 全てのキューを初期化するinitQueues メソッド.キュープロセッサのすべてのキーを繰り返します.
  • getQueue は、queueName それがすでに存在しないならば、それを返してください.
  • queues[queueName].process(QUEUE_PROCESSORS[queueName]);QUEUE_PROCESSORS ジョブを適切なキューから処理する.
  • ステップ5
    キューを初期化するには
  • 輸入initQueuesserver/index.js ファイル
  • import { initQueues } from '@utils/queue';
    
  • 呼び出すinitQueues ライクソー
  • ...
    
    export const init = () => {
      ...
      if (!isTestEnv()) {
        app.listen(9000);
        initQueues();
      }
      ...
    }
    
  • セットアップデータベースとアプリケーションを使用して実行./setup-local.sh
  • DBが既に設定されているなら、アプリケーションを実行する必要がありますyarn start:local

  • 上のログがコンソールに表示されます.
    次のgitコマンドを使用してコードをコミットします
    git add .
    git commit -m 'Local redis setup done'
    

    ジョブスケジューリングのための書込み突然変異


    このステップでは、私たちはscheduleJob.
    ステップ1
    ジョブスケジューラの新しいファイルを作成する
    mkdir -p server/gql/custom
    touch server/gql/custom/scheduleJobMutation.js
    
    ステップ2
    次のスニペットを新しく作成したファイルにコピーします.
    import { GraphQLNonNull, GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLBoolean } from 'graphql';
    
    export const scheduleJob = {
      type: new GraphQLObjectType({
        name: 'ScheduleJob',
        fields: () => ({
          success: {
            type: GraphQLNonNull(GraphQLBoolean),
            description: 'Returns true if the job was scheduled successfully'
          }
        })
      }),
      args: {
        scheduleIn: {
          type: GraphQLNonNull(GraphQLInt),
          description: 'Milliseconds from now that the job should be scheduled'
        },
        message: {
          type: GraphQLNonNull(GraphQLString),
          description: 'Message that should be consoled in the scheduled job'
        }
      },
      async resolve(source, args, context, info) {
        // since currently there is no logic to schedule the job
        // this will always return false
        return { success: false };
      },
      description: 'Schedule a job that will be executed in ${scheduleIn} milliseconds. This job will console ${message}.'
    };
    
    この突然変異は2つの入力パラメータを受け取ります:
  • scheduleIn ジョブが現在実行する予定であるミリ秒単位の時間を表します.
  • message ジョブが実行されたときにログオンするメッセージを表します.
    の値を使用しますscheduleIn to delay キューに追加されたジョブの実行.
  • ジョブが正常にスケジュールされている場合、突然変異は戻ります{ success: true } 他の{ success: false }
    ステップ3
    今、突然変異を公開する必要があります.我々は、次のコードを追加することによってこれを行うことができますgql/mutations.js ファイル.
    import { scheduleJob } from '@gql/custom/scheduleJobMutation';
    ...
    ...
    
    export const addMutations = () => {
      ...
      ...
      // custom mutations
      mutations.scheduleJob = scheduleJob;
      return mutations;
    };
    
    今すぐアプリケーションを起動yarn start:local . 移動する http://localhost:9000/graphql ブラウザで.クリックDocs 右上に.検索ScheduleJob

    ステップ4
    左区画に次のスニペットを追加します.
    mutation ScheduleJob {
      scheduleJob(scheduleIn: 2000, message: "This message should be consoled at the scheduled time") {
        success
      }
    }
    
    左上にヒットプレー.また、要求を実行するにはCmd + Enterをヒットすることができます.

    APIは{ success: false } 仕事をスケジューリングするためのロジックを追加していないので.私たちは少しそれに着きます
    {
      "data": {
        "scheduleJob": {
          "success": false
        }
      }
    }
    
    ステップ5
    今、突然変異が呼び出されたときに、ジョブをスケジュールするロジックを追加します.以下のスニペットを解決関数にペーストします
    import moment from 'moment';
    import { getQueue, QUEUE_NAMES } from '@utils/queue';
    ...
    ...
    
    async resolve(source, args, context, info) {
        // 1
        return getQueue(QUEUE_NAMES.SCHEDULE_JOB)
          .add({ message: args.message }, { delay: args.scheduleIn })
          .then(job => {
            // 2
            console.log(`${moment()}::Job with id: ${job.id} scheduled in ${args.scheduleIn} milliseconds`);
            return { success: true };
          })
          .catch(err => {
            console.log(err);
            return { success: false };
          });
      },
    
  • 私たちはその名前でキューを得る
  • 帰ります{ success: true } スケジューリング中にエラーがない場合.
    他に我々は戻る{ success: false }

  • ああ!ジョブをスケジュールされた時間後に実行するスケジュールを作成する突然変異を作成しました.今すぐあなたの価値を変更することによって、新しく作成されたスケジューラをテストしますscheduleIn and message次のgitコマンドを使用してコードをコミットします
    git add .
    git commit -m 'Add mutation to schedule Job'
    

    ここからどこへ行くか


    あなたは今、彼らは特定の時間で実行されるようにジョブをスケジュールする機能を持っている!
    この記事を読んで楽しんだことを願っています.これがあなたの関心をピークにするならば、私はあなたがマルチコンテナ環境で毎日12時に実行するcron仕事を予定する方法を通して、あなたを連れて行くシリーズの次の記事のために調整されます.
    何か質問やコメントがあれば、下記のフォーラムディスカッションに参加してください.
    ➤このブログはもともと投稿されましたhttps://wednesday.is 水曜日に私たちに従って動作するようにそれが何であるかについての詳細を知るために