BackEnd

Go言語 gocraft/workを使って常駐プロセスでジョブを処理させる

投稿日:2018年10月17日 更新日:

はじめに

こんにちは。カイザーです。今回、Goシリーズ第6回目を担当させていただきます!
今回はGoでバックグラウンドでジョブを処理する「gocraft/work」を使用して、常駐プロセスでのジョブ処理について説明します。(以下workと呼びます)
https://github.com/gocraft/work

workの特徴

公式のREADMEに挙げられていますが、その中からピックアップして紹介します。

  • 実行速度が速く、かつ効率的に動作するとのことです。Benchmarksによると、他の3ライブラリと比較して、最も早いことが分かります。
  • プロセスがクラッシュしてもジョブが失われない。
  • Middlewareという仕組みがあり、ジョブ実行時に呼び出され、メトリック計測・ログ出力に適しています。
  • cronライクなスケジュールでジョブをエンキューすることも可能

様々な特徴がありますが、サンプルを動かしながら主要な機能を説明していきます。

workを使えるようにする

Redisのインストール

workによるジョブ実行のバックエンドには、Redisの通知があるため、Redisをインストールする必要があります。もうインストールしている人は飛ばしていただいて構いません。
macOSの人はHomeBrewでインストールできます。

Go用のライブラリインストール

「go get」コマンドを使用し、今回使用するworkと、依存するredigoのredisをインストールします。

これで準備完了です。

Enqueue〜ジョブ実行まで

公式のサンプルを参考に、Enqueue〜ジョブ実行まで作ってみました。
また、Enqueue側とジョブ実行は、別のGoプロジェクトとしました。

Enqueue側

ほぼ公式サンプルですが、1回実行するごとに、1回エンキューするシンプルなものです。
(日本語でのコメントを記入しました。)

「Redisプールの作成」はRedis周りの設定になります。この場合はエンキュー側の設定になるため、エンキューされる契機が多ければ、MaxActiveやMaxIdleの設定を上げても良いと思います。
こちらの設定については、こちらの記事が参考になります。

あとは、main関数で、ジョブに名前を付け、データを指定することができます。

ジョブ実行側

こちらは起動させておいて、エンキューされたらジョブを実行する側になります。

main関数の流れを簡単に説明します。
まず、Workerプールを作成し、ミドルウェアの設定、ジョブと関数のマッピングといった設定を行います。
設定が完了したら、Workerプールを開始します。
その後は、OSシグナルで終了するまで待機させておくことにより、その間エンキューを受け付けて処理を実行させることが可能になります。

ミドルウェア用の関数や、ジョブ処理用の関数は、Context構造体のメソッドとなっています。(後述のContextで説明します)

一通りの流れを試してみるには、まずジョブ実行側を「go run」しておき、後からEnqueue側を「go run」すると、ビルド実行側にログが表示されることが分かります。(あらかじめRedisは起動しておいてください)

また、ジョブ実行側はOSシグナルが無い限り待機し続けるため、Enqueue側を何度も実行すれば、ジョブ実行側にその分ログが出力されます。

バックエンドはRedisなので、先にEnqueue側を何度か実行しておけば、ジョブ実行側が後から立ち上がった時に、Enqueueされた分だけジョブが実行されます。

Context

workにおけるContextは実装者が自由に定義できる構造体ですが、WorkerPoolに必要です。
フィールドは空でも、様々なフィールドがあっても構いません。
また、Middlewareやジョブ実行用のメソッドはこのContextに実装する必要があります。
そのため、Middlewareやジョブ実行時に、Contextのフィールドを書き換えることも可能です。

Middleware

Middlewareはジョブ実行時に、任意のコードを実行できる機能です。
ジョブでは本質的に行いたい機能を、Middlewareではログ取りや計測といった、付属的かつ各ジョブでの共通機能、といった使い分けが可能です。

ジョブ実行中のタスクキル

ジョブ実行側では、Redisからの通知を待機するため、「signal.Notify()」を使用して、OSシグナルを受信するまで待機するように実装しました。

signalがos.Interrupt, os.Kill, syscall.SIGHUPのいずれかを受信すると、signalChanに受信され、5行目以降の処理に移ります。
その後はそのまま「pool.Stop()」でWorkerPoolを止めますが、実行中のジョブに関しては、完了を待ってから終了されます。

そのため、ジョブの実行中(今回の場合は10秒待機中)に「control+c」や「 kill -9」、「kill -HUP」でシグナル送信を行うと、ジョブが完了するまでは、プロセスキルされません。

Cronライクなスケジュール

PeriodicallyEnqueueを使用すると、WorkerPoolを使用して、Cronライクにジョブの定期実行ができます。
GoのCron構文仕様は下記が参考になります。
https://godoc.org/github.com/robfig/cron#hdr-CRON_Expression_Format

例えば、「0 0 * * * *」の場合は、毎時実行されます。
(フィールドは、それぞれ秒、分、時、日、曜日を表します。)

PeriodicallyEnqueueは、先ほどのEnqueueとは異なり、WorkerPoolに対して設定します。

実行すると、毎秒SampleProcess()が呼び出され、ログ出力されます。

Enqueueした時のRedisについて

最初のサンプルでEnqueueした直後に、redis-cliで実際の値を確認してみました。

これを読んでみると、「設定した名前空間:jobs:設定したジョブ名」をキーにして、JSON文字列でEnqueueされたジョブ情報が入っています。(リスト型)
また、「設定した名前空間:known_jobs」には、上記でEnqueueしたジョブ名が入っています。こちらはセット型なので、ジョブ名は重複せずに管理されていることが分かります。
上記を踏まえ、RubyからEnqueueするプログラムを作成してみました。
(「$ gem install redis」が必須です)

今回は、先ほどのサンプルのEnqueueをRubyで呼び出してみました。workで動作させることが目的であるため、Redisに格納するキーと値は、workの仕様に基づいたものになります。
valueのidは、12バイトの乱数をHex文字列で渡します。tは現在時刻をタイムスタンプで渡します。
Redisを使用しているので、Enqueueする側の自由度はかなり高いですね。

WebUI

同じくgocraftが提供している「workwebui」を導入すると、ジョブの状況について、WebUIで可視化できます。

workwebuiの導入〜起動

「go get」した後、「go install」することで使用可能になります。

下記コマンドでWebUIが起動します。

起動できたらブラウザから「http://localhost:5040/」にアクセスしてください。

先ほどのサンプルをWebUIで見てみる


このように、実行中のジョブを確認することができます。処理中のジョブ、再施行されたジョブ、スケジュールされた(Cronライクな)ジョブ等、各ジョブの状況ごとに表示することができます。

さいごに

workはシンプルなインターフェースでありながら、柔軟性の高いライブラリでした。
Redisを使用しているため、エンキュー側は何でもよく、ワーカー側もContextへの実装により様々なジョブ処理が可能です。
Goでバックグラウンドジョブを実装する際は、ぜひ使って見てください。

Go記事の連載などは、こちらをご覧ください。

おすすめ書籍

スターティングGo言語  Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る impress top gearシリーズ  みんなのGo言語[現場で使える実践テクニック]  Go言語でつくるインタプリタ

page_footer_300rect




page_footer_300rect




-BackEnd
-,

執筆者:


comment

メールアドレスが公開されることはありません。

CAPTCHA


関連記事

【Ruby Advent Calender 2017】Rubyでスクレイピングをしてみる【11日目】

1 はじめに1.1 概要2 仕様3 ソースコード4 使用したモジュール、Gem5 対象ページを取得6 XPATHから目的のものを抜き出す7 次のページのリンクを取得する8 他のサイトの記事でも試してみ ...

rails

半年ぶりにRails Tutorialをやったメモ

はじめに Railsを触り始めて半年ほどたちました、tonnyです。 復習もかねてRails Tutorialを実施したので、そのメモを残します。 やはり2回目でも気づくことは多いので、非常に勉強にな ...

aws

ALB+EC2な環境でhttpをhttpsにリダイレクトする

1 はじめに1.1 前提条件2 ALBの設定3 Nginxの設定3.1 注意点4 さいごに はじめに httpsに対応済みのWebサイトの場合、httpでアクセスされた時にhttpsでリダイレクトする ...

rails

さらば「rails migrate」、よろしく「ridgepole」

1 はじめに2 Ridgepoleとは3 rails migrateではなく、Ridgepoleを選定した理由4 rails migrateからRidgepoleへの移行手順5 capistrano3 ...

【Git】マージコミットを消したい

1 はじめに2 例えばこんなことってないでしょうか?3 マージコミットを消す4 さいごに はじめに こんにちは、tonnyです。 今回はGitのケーススタディ的なものを書きたいと思います。 反面教師と ...

フォロー

follow us in feedly

AppLink

英語

page_side_300rect

2018年10月
« 9月 11月 »
 123456
78910111213
14151617181920
21222324252627
28293031 

アプリ情報

目標を達成したい方を応援する、TODOアプリもリリースしております。 下記のアイコンから無料でダウンロードできます。

Web版MyCoach

私たちはより広い方にコーチングを知ってもらいたいと考えています。 下記のサイトにて、コーチの方々を紹介しておりますので、よろしければご覧ください。