75
Amazon Simple Workflow Service NRIネットコム株式会社  佐々木拓郎 2015/2/7 JAWSUG関西特別編

JAWSUG Kansai Simple Workflow Service (SWF)

Embed Size (px)

Citation preview

Amazon Simple Workflow Service

NRIネットコム株式会社  佐々木拓郎

2015/2/7JAWSUG関西特別編

佐々木拓郎 @dkfj

課長

AWSの事業推進の他に モバイルとデータ解析チームのマネジメントをしています

blog: http://blog.takuros.net

自己紹介

ちょっと宣伝

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例

http://amzn.to/1lsJ5id

ジュンク堂書店 コンピュータ書年間 総合ランキング14位

もう1つ宣伝

AWS本を執筆中

ある程度、AWSを理解した上で、 ・AWSのサービスの選択のポイント ・セキュリティの考え方 ・運用のノウハウ ・サードパーティ製の便利なサービスの紹介 ・パターン別構築例 ⇒もう一歩レベルが上げられるような内容を目指しています。

想定の対象読者は、JAWSUGに参加している皆さんです

NRIネットコム

Web周りのビジネスを専門としている会社

• Webシステムの企画・設計・開発・運用 • 24時間365日の運用体制 • デザインを重視し、自社内でディレクタ/デザイナが多数在籍 • スマホ/タブレットも得意 • もちろんAWSをはじめとするクラウドにも力を入れている

会社の紹介

Amazon Simple Workflow Service

SWFは、SQSの上位互換

Simple Workflow Service ワークフローエンジン

AWSのアプリケーションサービス(の一部)

SWF

SQS

SNS

SES

Simple Queue Service キューサービス

Simple Notification Service メッセージ通知サービス

Simple Email Service メール送信サービス

SWFとは?

ワークフローエンジン 実行するタスクの決定 タスクのステータス管理 タスクの一貫性の管理

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定URL

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定 HTMLの取得&保存

URL

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定 HTMLの取得&保存

URL

インターネット

ダウンロード

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定 HTMLの取得&保存

URL

インターネット

ダウンロード

保存

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定 HTMLの取得&保存

URL

インターネット

ダウンロード

保存

作業対象の 通知

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定 HTMLの取得&保存

任意のデータの抜き出し

URL

インターネット

ダウンロード

保存

作業対象の 通知

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定 HTMLの取得&保存

任意のデータの抜き出し

URL

インターネット

ダウンロード

保存

作業対象の 通知

対象データ取得

単純なクローラーの動き 取得対象のURLを決める WebからHTMLを収集し、保存する HTMLから任意のデータを抜き出す

クローラープログラムで考えてみる

URLの決定 HTMLの取得&保存

任意のデータの抜き出し

URL

インターネット

ダウンロード

保存

作業対象の 通知

対象データ取得

データの抜き出し

密結合の為に、部分再実行が出来ない

SQSを使って、疎結合にする

ダウンロード 対象キュー

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定

ダウンロード 対象キュー

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定

ダウンロード 対象キュー

URL格納

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

ダウンロード 対象キュー

URL格納

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

ダウンロード 対象キュー

URL格納 URL取得

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

ダウンロード 対象キュー

URL格納 URL取得

インターネット

ダウンロード

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

保存

ダウンロード 対象キュー

URL格納 URL取得

インターネット

ダウンロード

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

保存

作業対象の 格納

ダウンロード 対象キュー

URL格納 URL取得

インターネット

ダウンロード

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

任意のデータの抜き出し

保存

作業対象の 格納

ダウンロード 対象キュー

URL格納 URL取得

インターネット

ダウンロード

作業対象の 対象キュー

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

任意のデータの抜き出し

保存

作業対象の 格納

ダウンロード 対象キュー

URL格納 URL取得

インターネット

ダウンロード

作業対象の 対象キュー

作業対象の 取得

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

任意のデータの抜き出し

保存

作業対象の 格納

ダウンロード 対象キュー

URL格納 URL取得

インターネット

ダウンロード

作業対象の 対象キュー

作業対象の 取得

対象データ取得

SQSを使って、疎結合にする

URLの決定 HTMLの取得&保存

任意のデータの抜き出し

保存

作業対象の 格納

ダウンロード 対象キュー

URL格納 URL取得

インターネット

ダウンロード

作業対象の 対象キュー

作業対象の 取得

対象データ取得

データの抜き出し

これで、ええやん

これで、ええやんでも、少しだけ課題があります

残る課題

重複実行の可能性 SQSは、複数のワーカーが同一のキューを取得する可能性がある アプリ側で、一貫性を保つためのロジックが必要

実行制御の問題 エラー時に単純再実行の作りであれば、問題ない 処理ごとに分岐する場合は、自前で制御ロジック実装する必要 途中で処理の追加・変更・削除をする場合、前後の調整が必要

ワークフロー エグゼキューション

SWFを使うと

URLの決定

ワークフロー スターター

ワークフロー エグゼキューション

ワークフロー エグゼキューション

ディシジョン タスクリスト

アクティビティ タスクリスト

次のタスクを 決める

処理の実行

デサイダー

アクティビティ

ポーリング

ポーリング

ワークフロー エグゼキューション

SWFを使うと

URLの決定

ワークフロー スターター

ワークフロー エグゼキューション

ワークフロー エグゼキューション

ディシジョン タスクリスト

アクティビティ タスクリスト

次のタスクを 決める

処理の実行

デサイダー

アクティビティ

ポーリング

ポーリング

ワークフロー エグゼキューション

SWFを使うと

URLの決定

ワークフロー スターター

ワークフロー エグゼキューション

ワークフロー エグゼキューション

ディシジョン タスクリスト

アクティビティ タスクリスト

次のタスクを 決める

処理の実行

デサイダー

アクティビティ

ポーリング

ポーリングデサイダーが、 次の処理を決める

ワークフロー エグゼキューション

SWFを使うと

URLの決定

ワークフロー スターター

ワークフロー エグゼキューション

ワークフロー エグゼキューション

ディシジョン タスクリスト

アクティビティ タスクリスト

次のタスクを 決める

処理の実行

デサイダー

アクティビティ

ポーリング

ポーリングデサイダーが、 次の処理を決める

ワークフロー エグゼキューション

SWFを使うと

URLの決定

ワークフロー スターター

ワークフロー エグゼキューション

ワークフロー エグゼキューション

ディシジョン タスクリスト

アクティビティ タスクリスト

次のタスクを 決める

処理の実行

デサイダー

アクティビティ

ポーリング

ポーリングデサイダーが、 次の処理を決める

ここだけ見ると、 SQSと同じ

用語の説明

ワークフロースターター ワークフローをキックするプログラム キックするたびに「ワークフローエグゼキューション」が作成される

ワークフローエグゼキューション ワークフローのインスタンス タスクを管理する為の情報をもつ

タスクリスト 処理すべきキュー デサイダーとアクティビティごとにキューを設定

用語の説明

デサイダー ワークフローの実体 タスクリストをポーリングし、タスクがあったら次に実行するアクティビティを指定

アクティビティ 個々のタスク処理 タスクリストをポーリングし、タスクがあったら処理を実行

解らん。

解らん。実際にワークフローを動かしてみよう

SDK

言語別の各SDKからSWFは利用可能 Android iOS Java .NET Node.js PHP Python Ruby ブラウザ(JavaScript)

AWS Flow Framework SWFの各種APを隠蔽して実行するフレームワーク RubyとJavaのみ提供されている

Rubyで始めるSWF

事前に見ておくもの Getting Started with AWS Flow Framework for Ruby for Amazon SWF https://www.youtube.com/watch?v=Z_dvXy4AVEE

準備するもの AWSのAccessKeyIDとSecretAccessKey Rubyの実行環境 Gemのダウンロード

Gemのインストール

$ gem install aws-sdk $ gem install aws-flow

サンプルプログラム

Samples/HelloWorld/ └── lib ├── aws-config.txt ├── hello_activity.rb ├── hello_workflow.rb ├── hello_world.rb ├── kill_hello.rb ├── run_hello └── utils.rb

http://aws.amazon.com/code/Amazon-SWF/3015904745387737

サンプルプログラム

Samples/HelloWorld/ └── lib ├── aws-config.txt ├── hello_activity.rb ├── hello_workflow.rb ├── hello_world.rb ├── kill_hello.rb ├── run_hello └── utils.rb

http://aws.amazon.com/code/Amazon-SWF/3015904745387737

アクティビティ

サンプルプログラム

Samples/HelloWorld/ └── lib ├── aws-config.txt ├── hello_activity.rb ├── hello_workflow.rb ├── hello_world.rb ├── kill_hello.rb ├── run_hello └── utils.rb

http://aws.amazon.com/code/Amazon-SWF/3015904745387737

デサイダーアクティビティ

サンプルプログラム

Samples/HelloWorld/ └── lib ├── aws-config.txt ├── hello_activity.rb ├── hello_workflow.rb ├── hello_world.rb ├── kill_hello.rb ├── run_hello └── utils.rb

http://aws.amazon.com/code/Amazon-SWF/3015904745387737

デサイダーアクティビティ

ワークフロースターター

初期設定

$ vi aws-config.txt

--- :access_key_id: “your key" :secret_access_key: “your key"

アクセスキーとシークレットアクセスキーを埋め込む

ワークフロー

require_relative 'utils' require_relative "./hello_activity"

class HelloWorldWorkflow extend AWS::Flow::Workflows

workflow :hello_workflow do { :version => "1", :execution_start_to_close_timeout => 3600, :task_list => $TASK_LIST } end

activity_client(:activity) { {:from_class => "HelloWorldActivity"} }

def hello_workflow(name) activity.hello_activity(name) end end

worker = AWS::Flow::WorkflowWorker.new($SWF.client, $HELLOWORLD_DOMAIN, $TASK_LIST, HelloWorldWorkflow) # Start the worker if this file is called directly from the command line. worker.start if __FILE__ == $0

hello_workflow.rb

呼び出すアクティビティの設定

ワークフローの設定

アクティビティ

require_relative 'utils'

class HelloWorldActivity extend AWS::Flow::Activities

activity :hello_activity do { :default_task_list => $TASK_LIST, :version => "my_first_activity", :default_task_schedule_to_start_timeout => 30, :default_task_start_to_close_timeout => 30 } end

def hello_activity(name) puts "Hello, #{name}!" end end

activity_worker = AWS::Flow::ActivityWorker.new($SWF.client, $HELLOWORLD_DOMAIN, $TASK_LIST, HelloWorldActivity) { {:use_forking => false} }

# Start the worker if this file is called directly from the command line. activity_worker.start if __FILE__ == $0

hello_activity.rb

アクティビティ

require_relative 'utils'

class HelloWorldActivity extend AWS::Flow::Activities

activity :hello_activity do { :default_task_list => $TASK_LIST, :version => "my_first_activity", :default_task_schedule_to_start_timeout => 30, :default_task_start_to_close_timeout => 30 } end

def hello_activity(name) puts "Hello, #{name}!" end end

activity_worker = AWS::Flow::ActivityWorker.new($SWF.client, $HELLOWORLD_DOMAIN, $TASK_LIST, HelloWorldActivity) { {:use_forking => false} }

# Start the worker if this file is called directly from the command line. activity_worker.start if __FILE__ == $0

hello_activity.rb

アクティビティの設定

アクティビティ

require_relative 'utils'

class HelloWorldActivity extend AWS::Flow::Activities

activity :hello_activity do { :default_task_list => $TASK_LIST, :version => "my_first_activity", :default_task_schedule_to_start_timeout => 30, :default_task_start_to_close_timeout => 30 } end

def hello_activity(name) puts "Hello, #{name}!" end end

activity_worker = AWS::Flow::ActivityWorker.new($SWF.client, $HELLOWORLD_DOMAIN, $TASK_LIST, HelloWorldActivity) { {:use_forking => false} }

# Start the worker if this file is called directly from the command line. activity_worker.start if __FILE__ == $0

hello_activity.rb

処理内容

アクティビティの設定

ワークフロースターター

require 'aws/decider' require_relative 'utils' require_relative 'hello_workflow'

# Get a workflow client to start the workflow my_workflow_client = AWS::Flow.workflow_client($SWF.client, $HELLOWORLD_DOMAIN) do {:from_class => "HelloWorldWorkflow"} end

puts "Starting an execution..." workflow_execution = my_workflow_client.start_execution("AWS Flow Framework for Ruby")

hello_world.rb

SWFの実行

$ ruby hello_activity.rb & $ ruby hello_workflow.rb & $ ruby hello_world.rb

バックグランドで実行WorkFlow Starterで ワークフローの開始

AWSコンソールで確認US East

AWSコンソールで確認US East

HelloWorldドメインが作成されている

アクティビティだけを落として、実行

$ kill <アクティビティのプロセスID> $ ruby hello_world.rb

AWSコンソールで確認

一定時間後に、Failedに

デサイダーだけを落としてみる

$ kill <デサイダーのプロセスID> $ ruby hello_world.rb

AWSコンソールで確認

AWSコンソールで確認

Active Excecutionに残る

AWSコンソールで確認

Active Excecutionに残る

AWSコンソールで確認

Active Excecutionに残る

AWSコンソールで確認

Active Excecutionに残る

AWSコンソールで確認

Active Excecutionに残る

AWSコンソールで確認

設定値である3600秒後に、TimeOut

Active Excecutionに残る

まとめ

SWFの実行処理は、どこでも動く タスクの状態は、AWS上で管理されている 自分で動かすと、何となく解る

参考資料

Amazon Simple Workflow Service(SWF) AWS Black Belt Tech http://www.slideshare.net/AmazonWebServicesJapan/amazon-simple-workflow-service-swf

Amazon Simple Workflow Service (SWF) 入門 | Developers.IO http://dev.classmethod.jp/cloud/aws/introduction-to-amazon-simple-workflow-service/

20140315 ACEに聞け! SWFで始めるWorkFlow - jawsdays2014 http://www.slideshare.net/okeee0315/20140315-jawsdays2014-swf

ご静聴、ありがとうございました。