ようへいの日々精進XP

よかろうもん

2017 年 07 月 19 日(水)

ジョギング

  • 香椎浜 x 2 周
  • 両足の太腿にピキッとした痛み

日課

  • (腕立て x 30 + 腹筋 x 30) x 3

夕飯

2017 年 07 月 18 日(火)

ジョギング

  • 香椎浜 x 2 周
  • 暑い、熱い
  • 右足太腿に突っ張ったような痛み

日課

  • (腕立て x 30 + 腹筋 x 30) x 3

夕飯

  • アボガド生ハムサラダ
  • トマトパスタ

を作った。今回のパスタは乳化が不足していたのでイマイチ。

俺の郷 〜 コマンドの実行結果を JSON で返す郷 〜

Golang を勉強中であります

以下の点について勉強しました

  • Golang で配列を含んだ JSON の生成について
  • Golang でコマンドの実行と結果の取得方法

出来たもの

gist.github.com

以下のように使う

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G1421

$ go version
go version go1.8.3 darwin/amd64

ヘルプ

$ ./cmdRunner -help
Usage of ./cmdRunner:
  -command string
        Specify a Command.
  -interval int
        Specify a Wait Interval Times. (default 3)
  -times int
        Specify a Loop Counts Number. (default 1)

date を 1 秒毎に 5 回実行

$ ./cmdRunner -command="date +%Y%m%d-%H:%M:%S" -times=5 -interval=1 | jq .
{
  "outputs": [
    "20170718-07:56:55",
    "20170718-07:56:56",
    "20170718-07:56:57",
    "20170718-07:56:58",
    "20170718-07:56:59"
  ]
}

date を 3 秒ごとに 3 回実行

$ ./cmdRunner -command="date +%Y%m%d-%H:%M:%S" -times=3 -interval=3 | jq .
{
  "outputs": [
    "20170718-07:57:54",
    "20170718-07:57:57",
    "20170718-07:58:00"
  ]
}

まとめ

コマンドの実行(実行結果もしくは実行エラーも取得したい場合)

CombinedOutput() を利用すると良いらしい。

func runCommand(command string) (output string){
    cmd := exec.Command("sh", "-c", command)
    stdout, err := cmd.CombinedOutput()
    output = strings.TrimRight(string(stdout), "\n")
    if err != nil {
        errMessage := err.Error() + ": " + output
        log.Printf(string(errMessage))
        return output
    }
    return output
}

配列を含んだ JSON の生成

// 配列を含んだ JSON の構造体を定義
type OutputMessages struct {
    Outputs []string    `json:"outputs"`
}

...
// JSON オブジェクトを生成
outputMessage := OutputMessages{Outputs: []string(stdouts)}

// Marshal 関数を利用して JSON を生成
jsonBytes, err := json.Marshal(outputMessage)

以上

メモでした。

2017 年 07 月 17 日(月)

海の日

ということでお休み。

ジョギング

  • 少し早起きして 7:30 くらいから走り始める
  • いつも走る時間と比べて、数十分しか変わらないのに多少走りやすかった
  • 香椎浜 x 3 周

日課

  • (腕立て x 30 + 腹筋 x 30) x 3

お昼ご飯

  • 新宮のインドカレー屋さん
  • 美味しかったけどご飯が山盛りだった

その後

帰宅して

  • 急に疲労感
  • あまりにも体がだるいのでベッドに横になって 2 時間程昼寝

はじめてのおつかい

  • 感動した

2017 年 07 月 16 日(日)

ジョギング

  • 9 キロ位(多分、45 分くらい)

Amazon Prime

  • 深夜食堂シーズン 2 を一気見した
  • シーズン 2 は第一話が神回

2017 年 07 月 15 日(土)

ジョギングも日課も

  • 今日はお休み

ドライブ

  • 雲が見たくなって奥さんとドライブ
  • 仙人も疲れを癒やしたかもしれない温泉に浸かって日頃の疲れを癒やした

AWS Step Functions の Activity Worker を "郷" で実装してみた系

どうも、郷です。

モチベーション

  • むかーし、むかーし、1 台の EC2 cron で動かしている複数のバッチ処理があったとさ
  • 村人(むらびと)たちはバッチ処理を動かす時だけ EC2 を起動したいと考えたとさ
  • 村人たちの思いを汲んだ禿兵衛は EC2 は Lambda で起動してから、バッチを実行しようと考えたとさ
  • ところが、禿兵衛は EC2 が正常に起動したことを正確に判断したり、バッチ処理の重複起動やハンドリングに頭を悩ましておりましたさ

そして、ちゃんと前後の処理をハンドリングしつつ、処理の流れをコード化(可視化)出来ればなあと黄昏れておりましたら…山の向こうから「AWS Step Functions というツールがあるばってん、こんツールはくさ、Activity を使えばくさ、EC2 やオンプレのタスクも制御出来るちゃんねー」という声を聞くのであった…

ということで、EC2 で動かしているバッチ処理を Activity で制御することを想定して、Golang で Worker を実装して Acitivity の挙動についてチュートリアルしてみたメモでござる。

AWS Step Functions とは

aws.amazon.com

Step Functions の詳しい説明については、以下の資料がとても参考になりました。

www.slideshare.net

有難うございます!!

郷で Activity Worker を実装

Activity

docs.aws.amazon.com

Activities are an AWS Step Functions concept that refers to a task to be performed by a worker that can be hosted on EC2, ECS, mobile devices—basically anywhere.

超ざっくりだけど…

  • Activity とは EC2 や ECS 等、オンプレミスのサーバーでも動く Worker によって実行されるタスクのこと
  • AWS SDKAWS CLI で Worker を実装出来る
  • Worker は Activity の ARN を指定して起動すると Activity に対してポーリングを行う

Activity は AWS CLI では以下のように作成します。

$ aws \
  --profile oreno-profile --region ap-northeast-1 \
    stepfunctions create-activity \
      --name=OrenoActivity

以下のように出力されます。

{
    "creationDate": 1500076193.843,
    "activityArn": "arn:aws:states:ap-northeast-1:012345678912:activity:OrenoActivity"
}

State Machine には以下のように指定します。

{
  "Comment": "Golang Demo",
  "StartAt": "Godesu1",
  "States": {
    "Godesu1": {
      "Type": "Task",
      "Resource": "arn:aws:states:ap-northeast-1:012345678912:activity:OrenoActivity",
      "Next": "wait_using_seconds"
    }
  }
}

参考

こちらこちらを目一杯参考にさせて頂きました。有難うございます!!

コード

gist.github.com

こうやって使うことを想定

./taskRunner -arn=${Activity ARN} -command=${実行したいコマンド}

Demo

Activity Worker を動かす環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G1421

$ go version
go version go1.8.3 darwin/amd64

$ go build taskRunner.go

State Machine: ビジュアルワークフロー

State Machine とは State をつなげたフローのことで、以下のようなフローで動かしてみます。

f:id:inokara:20170715075537p:plain

State Name State Type State で実行したいコマンド
Godesu1 Task demo01.sh
wait_using_seconds Wait 10 秒待ってから State: Godesu2 を実行
Godesu2 Task demo02.sh

State Machine: コード

{
  "Comment": "Golang Demo",
  "StartAt": "Godesu1",
  "States": {
    "Godesu1": {
      "Type": "Task",
      "Resource": "arn:aws:states:ap-northeast-1:123456789012:activity:OrenoFirstActivity",
      "Next": "wait_using_seconds"
    },
    "wait_using_seconds": {
      "Type": "Wait",
      "Seconds": 10,
      "Next": "Godesu2"
    },
    "Godesu2": {
      "Type": "Task",
      "Resource": "arn:aws:states:ap-northeast-1:123456789012:activity:OrenoSecondActivity",
      "End": true
    }
  }
}

State1 : Godesu1 で実行するコマンド

$ cat demo01.sh
#!/usr/bin/env bash

for i in $(seq 1 2 10);
do
  echo $i
done

Activity Worker を以下のように実行して待機させておきます。

./taskRunner -arn=arn:aws:states:ap-northeast-1:123456789012:activity:OrenoFirstActivity -command="./demo01.sh"

以下のように出力されます。

$ ./taskRunner -arn=arn:aws:states:ap-northeast-1:123456789012:activity:OrenoFirstActivity -command="./demo01.sh"
2017/07/15 08:00:49 taskRunner Started.

State2 : Godesu2 で実行するコマンド

$ cat demo02.sh
#!/usr/bin/env bash

for i in $(seq 2 2 10);
do
  echo $i
done

Activity Worker を以下のように実行して待機させておきます。

./taskRunner -arn=arn:aws:states:ap-northeast-1:123456789012:activity:OrenoSecondActivity -command="./demo02.sh"

以下のように出力されます。

$ ./taskRunner -arn=arn:aws:states:ap-northeast-1:123456789012:activity:OrenoSecondActivity -command="./demo02.sh"
2017/07/15 08:00:55 taskRunner Started.

State Machine の実行

以下のように AWS CLI で実行します。

$ aws \
  --profile oreno-profile --region ap-northeast-1 \
    stepfunctions start-execution \
      --state-machine-arn=arn:aws:states:ap-northeast-1:012345678912:stateMachine:DemoStateMachine-Go-3

以下のようにレスポンスが返ってきます。

{
    "startDate": 1500075053.349,
    "executionArn": "arn:aws:states:ap-northeast-1:012345678912:execution:DemoStateMachine-Go-3:859949c4-b3a4-4b7c-84ed-60f555e859e6"
}

そして、それぞれの Activity Worker では以下のように出力されています。

f:id:inokara:20170715083348p:plain

それぞれ別の Activity を利用しているので、順番も制御出来ている(Godesu1 → Godesu2 の順番)ことが判ります。

f:id:inokara:20170715092126p:plain

マネジメントコンソールでも上図のように State Machine の処理が正常に終了していることが判ります。

このフロー図を見ているだけでウキウキしますね。

ということで

Step Functions = Lambda という印象がありましたが、Activity を使うことで従来のバッチ処理等について変更を最小限に処理フロー(State Machine)に組み込めるのはとても嬉しいです。しかし、こちらでも言及されている通り、Activity は Worker を実装する必要があったり、Worker の運用管理が必要になる点は注意が必要です。

今回、禿兵衛の目の前にあるシチュエーションの場合、Activity Worker は EC2 が起動したタイミングで必ず起動することを保証する必要があったりしますが、それ自体も State の一つとして Lambda ファンクションに組み込んでしまうのもありかなと思ったりしています。

Step Functions とても面白いサービスで好きになっちゃいました。

2017 年 07 月 14 日(金)

ジョギング

  • 香椎浜 x 2 周
  • 8 時過ぎから走っているけど暑さでフラフラ

日課

  • (腕立て x 30 + 腹筋 x 30) x 3

右手薬指の根本

が痛い。おそらく肘から来ている。

夕飯

買い物に行けなかったので外食。

担々麺が美味しいお店で担々麺と水餃子、ビール。

2017 年 07 月 13 日(木)

今日は

ジョギングも日課は無し。

久しぶりの JAWS-UG 福岡

jaws-ug-kyushu.doorkeeper.jp

乾杯から始まるゆるっとした勉強会。これがイイ。

香椎に付いたのが 23 時過ぎだったけど、森田さんとコンテナ街の十蔵で一杯。

2017 年 07 月 12 日(水)

寝苦しい夜だった

  • 何度も目覚めてエアコン付けたり

ジョギング

  • 香椎浜 x 2 周
  • 夜中に右足親指を捻ったみたいで痛いけど走った

日課

  • (腕立て x 30 + 腹筋 x 30) x 3

夕飯