SQSを使ったバッチ処理システムを考える

# はじめに
## この記事は何か
* AWSのSQSをJob queueとしたバッチ処理システムの構成について、比較検討しています。
  * 特にconsumerにフォーカスしています。
* 用語はこちらのスライドを参考にさせていただきました
  * [AWSにおけるバッチ処理の ベストプラクティス - Developers.IO Meetup 05](https://www.slideshare.net/daisuke_m/20140628-cmsapporojobworkers)

## この記事を書いた理由
* SQSを使ってバッチ処理システムを作ろうとしたが、  
  lamnda以外で最近(2019年)のベストプラクティスが見つからなかった。
* lambdaがユースケースに合わない人はまだまだいるんじゃない？と思い、記事にしました

## どんな人が検討したか
* 普段の業務スキルと若干離れた事を検討しているので、  
間違ったこと書いてたり、あきらかな改善点があるかもしれません。
  * ツッコミもらえると嬉しいです。

### スキル
* サーバサイド(API)
  * ruby/Rails
  * python
      * フレームワークを使用した、規模の大きいシステムとしての使用経験はあまりないです
  * Mysql
  * etc...
* インフラ(AWS: オンプレ使ったことないゆとり)
    * EC2,RDS,SQS,etc...

### 考え方など
* マネージド・サービスなどで可能な限り、実装、運用の手間を削減したい。

# 課題
## どんなシステムのために検討をしたか
* 調査時の視点として以下のようなシステムを前提としました

### 概要
* 既存のRailsのAPIシステム(以下: MobileApp System)があり、  
pythonのバッチ処理(以下: Worker System)を無理なく追加したい

### システム構成
![system_diagram_for_publish.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57898/c412fba5-6e20-407f-cba0-1d9f950c5868.jpeg)

### インフラ
* AWSの使用を前提とする
  * 既存のシステムは全てAWS
* Worker Systemの不具合をMobileApp Systemに影響させてはいけない
    * 安定したマネージド・サービスでシステム間を疎結合に分離する
        * IN: MobileApp System -> Worker System
            * AWS SQS
        * OUT: Worker System -> Mobile App System
            * Cache(Redis)にデータをいれてやり取り 

### 処理内容
* Worker Systemにやらせたい処理
  * 処理の中には、15分以上かかるものがある
  * 処理の中には、バッチ処理だけどできるだけ早く(数秒で)完了したいものがある

# 検討内容
## 概要
![スクリーンショット 2019-07-13 16.39.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57898/c083d286-85fb-2546-3e5d-b6d42789ecca.png)

## 比較
### consumer
| consumer | 良さげ度 | pros | cons |
|:------|:----|:------|:------|
| lambda | x | * サーバレス<br/>*事例多数<br/> *安心・安全・みんな大好きLambda | * 状態によっては起動遅い<br/>レスポンス: 250ms~8000msらしい<br/><br/>* 15分で強制終了 |
| Beanstalk worker(sqsd)+<br/>python API Server(flask?) | △ | * マネージド・ツール・バンザイ | sqsdからpythonの受け取りが/postなので、<br/>内部でAPIサーバ稼働させるのがだるい |
| celery | △ | * pythonで完結<br/>* 動作実績豊富<br/>(python業界のデファクトスタンダードぽい)<br/>* AirFlowとかと相性バツグンぽい | * celery 大きすぎ・デバッグ大変らしい<br/>* celery最近活発じゃないぽい |
| pyqs | x | * pythonで完結<br/>* celery的な問題起きづらいとのこと<br/>(celeryの問題を解決するためできたプロジェクトらしい) | * 仕組みが非同期メソッド呼び出し(?)xxx.delay.yyy()をするためのものなので、<br/>別システム間のqueueとしては違いそう<br/>(キューされるデータがcelery serialized みたいなデータ)<br/>* 若干こなれてない感が怖い |
| <br/>SQSなんだから、<br/>それぐらい自分で書く? | △ | - | * 類似したソースをgithubとかで探してみたけど<br/>いずれもbeta感が怖い<br/>* 負債の予感 |
| shoryuken | o | * 割とコンパクト(sidekiq比較)<br/>* 日本語ドキュメント/事例多く、成熟度高そう<br/>https://github.com/phstc/shoryuken/wiki<br/>http://tech.toreta.in/entry/2016/06/09/120610<br/><br/>* 使い慣れたrubyで運用楽そう | * サーバにpythonとruby両方インストールしなきゃいけない |
| sidekiq | △ | * 使い慣れたrubyで多い日も安心 | * sqsではなくredisを使うのが基本なので<br>ちょっとトリッキーになる |

### infra   
* こちらは正直そんなに選択肢はない感じでした。
* 選び方(?)
  * 1. ユースケースが合うならlambda
  * 2. docker使えればdocker系
  * 3. 安心のEC2 or Beanstalk

#### 検討したもの
* Lambda 
* Dockerマネージド系
  * オーケストレーション 
     * ECS
     * Kubernetes 
  * マネージドサーバ
     * Fargate
     * EC2
* 自前で管理する系
  * Beanstalk
  * EC2

# 結果
## 課題となったシステムでの結論
* infra
    * EC2
        * dockerの経験が浅いので、実装速度優先
        * 今後ECSなど、マネージド寄りのdocker系のスケールしやすいアーキテクチャに変更したい
* consumer
    * shoryuken
       *  プロジェクトとしてある程度成熟していながら、依存ミドルウェアやconfigが少なくシンプルに使える印象が強い

* worker
    * python
        * shoryukenからpythonスクリプトを起動

## 結果
* 処理速度: 今のとこ問題なし
  * SQSにタスクが入ってから0.5秒程度でpython scriptが起動され、  
    早く完了してほしい処理は概ね３秒以内に完了している