ラベル aws の投稿を表示しています。 すべての投稿を表示
ラベル aws の投稿を表示しています。 すべての投稿を表示

2014年1月16日木曜日

SQSってなんじゃ?(supervisordでSQS)

いまさらですが、SQS+supervisordです。

supervisorはプログラムの起動監視と、自動起動/復帰などを行ってくれるツールです。
これをつかってSQSの受信処理プログラムをワーカーとして管理してみます。


受信テスト用のスクリプトを作成


メッセージの受信は、一度に最大の10件まで、ポーリング20秒で受信したメッセージをログファイルに出力するようにします。
また、今回はログの出力タイミングがわかりやすいように、1回のポーリング後10秒間sleepしています。
$ vim /home/ec2-user/svsqs.rb
#!/usr/local/bin/ruby

require 'aws-sdk'
require 'logger'

access_key = 'XXXXXXXXXXXXXXXX'
secret_key = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
queue_url = 'https://sqs.ap-northeast-1.amazonaws.com/ZZZZZZZZZZZ/svsqs'

log = Logger.new("/home/ec2-user/test.log");

AWS.config(:access_key_id => access_key,
  :secret_access_key => secret_key,
  :region => "ap-northeast-1")
sqs = AWS::SQS.new

while true
  messages = sqs.queues[queue_url].receive_message({:limit => 10, :wait_time_seconds => 20}).map do |m|
    json = JSON.parse(m.body)
    log.debug("#{$$} #{json['msg']}")
    m.delete()
  end
  log.debug("#{$$} -------")
  sleep 10
end
$ chmod 755 /home/ec2-user/svsqs.rb



supervisorのインストールと設定


次に、supervisorをインストールして、上記のスクリプトの起動管理するように設定します。
# easy_install supervisor
# vim /etc/init.d/supervisord

次にsupervisor自体の起動スクリプトをつくってサービス登録します。
#!/bin/sh
#
# /etc/rc.d/init.d/supervisord
#
# Supervisor is a client/server system that
# allows its users to monitor and control a
# number of processes on UNIX-like operating
# systems.
#
# chkconfig: - 64 36
# description: Supervisor Server
# processname: supervisord

# Source init functions
. /etc/init.d/functions

RETVAL=0
prog="supervisord"
pidfile="/tmp/supervisord.pid"
lockfile="/var/lock/subsys/supervisord"

start()
{
   echo -n $"Starting $prog: "
   daemon --pidfile $pidfile supervisord
   RETVAL=$?
   echo
   [ $RETVAL -eq 0 ] && touch ${lockfile}
}
stop()
{
   echo -n $"Shutting down $prog: "
   killproc -p ${pidfile} /usr/bin/supervisord
   RETVAL=$?
   echo
   if [ $RETVAL -eq 0 ] ; then
      rm -f ${lockfile} ${pidfile}
   fi
}
case "$1" in
  start)
    start
  ;;
  stop)
    stop
  ;;
  status)
    status $prog
  ;;
  restart)
    stop
    start
  ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
  ;;
esac


# chmod 755 /etc/init.d/supervisord
# chkconfig --add supervisord
# chkconfig supervisord on
# chkconfig --list



監視対象プロセスの設定


子設定ファイルの読込み設定

主設定ファイルの末尾に、アプリケーションごとの設定ファイルをインクルードするように設定しておきます。
# echo_supervisord_conf > /etc/supervisord.conf
# echo "[include]" >> /etc/supervisord.conf
# echo "files = supervisord/conf/*.conf" >> /etc/supervisord.conf

子設定ファイルの作成

svsqsという名前で最初に書いたスクリプトの起動設定をします。 自動起動や、自動復帰をONにします。
# mkdir -p  /etc/supervisord/conf/
# vim /etc/supervisord/conf/svtest.conf
[program:svsqs]
command = /home/ec2-user/svsqs.rb
process_name = svsqs
autostart   = true
autorestart = true



supervisorのデーモン起動


ここまで設定できたらsupervisord自体を起動します。
# service supervisord start



supervisorのコンソールでstop/startテスト


supervisorctlというコマンドで管理対象プロセスの操作や状態確認が簡単にできます。
 supervisorが起動すると、autostartがONになっているため対象のスクリプトも起動していることが分かります。
# supervisorctl
svtest                           RUNNING    pid 18770, uptime 15:44:07
supervisor> stop svtest
svtest: stopped
supervisor> status
svtest                           STOPPED    Jan 16 05:12 AM
supervisor> start svtest
svtest: started
supervisor>
supervisor>
supervisor> status
svtest                           RUNNING    pid 10876, uptime 0:00:03
supervisor>
supervisor>
supervisor> exit



自動復帰の確認


プロセスを強制的に落としてみます。
するとsupervisorにより、新しいプロセスとして自動復帰します。
# ps -ax | grep svtest
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
10876 ?        S      0:00 /bin/sh /home/ec2-user/svsqs.rb
10892 pts/0    D+     0:00 grep svtest

# kill -9 10876
# ps -ax | grep svtest
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
10898 ?        S      0:00 /bin/sh /home/ec2-user/svsqs.rb
10901 pts/0    S+     0:00 grep svtest



メッセージの確認


このプログラムで扱うSQSのキューに対し、いくつかメッセージを送ってみると、受信できているのがわかります。
# tail -1000f test.log
D, [2014-01-16T07:02:28.085909 #13119] DEBUG -- : 10898 aaaaaa
D, [2014-01-16T07:02:28.176748 #13119] DEBUG -- : 10898 -------
D, [2014-01-16T07:02:38.347694 #13119] DEBUG -- : 10898 bbbbbbb
D, [2014-01-16T07:02:38.364416 #13119] DEBUG -- : 10898 cccccccc
D, [2014-01-16T07:02:38.414742 #13119] DEBUG -- : 10898 ddddddd
D, [2014-01-16T07:02:38.466001 #13119] DEBUG -- : 10898 -------
D, [2014-01-16T07:02:48.655003 #13119] DEBUG -- : 10898 eeeeeee
D, [2014-01-16T07:02:48.666323 #13119] DEBUG -- : 10898 ffffffff
D, [2014-01-16T07:02:48.718459 #13119] DEBUG -- : 10898 gggggggg
D, [2014-01-16T07:02:48.771584 #13119] DEBUG -- : 10898 -------
D, [2014-01-16T07:02:58.947327 #13119] DEBUG -- : 10898 hhhhhhhh
D, [2014-01-16T07:02:58.957724 #13119] DEBUG -- : 10898 iiiiiii
D, [2014-01-16T07:02:59.023820 #13119] DEBUG -- : 10898 -------
D, [2014-01-16T07:03:09.171886 #13119] DEBUG -- : 10898 jjjjjjj



複数プロセス


次に、このプログラムを並列で複数のワーカーとして起動管理するようにしてみます。
# vim /etc/supervisord/conf/svsqs.conf

複数のプロセスとして管理するには、numprocsというパラメータを2以上に設定します。
また、このときprocess_nameにはワーカーの番号を含める必要があるため、
supervisorの特殊変数 %(program_name)と%(process_num)を利用します。
[program:svsqs]
command = /home/ec2-user/svsqs.rb
process_name = %(program_name)s_%(process_num)02d
numprocs = 2
autostart   = true
autorestart = true

設定を変えたので再起動し、プロセスを見てみると、2つ起動しているのが分かります。
# /etc/init.d/supervisord restart

supervisorctlでは、先ほど設定した名前でワーカー名が動的に付与されているのが分かります。
[root@ip-10-160-79-47 ec2-user]# supervisorctl
svsqs:svsqs_00                   RUNNING    pid 14286, uptime 0:36:24
svsqs:svsqs_01                   RUNNING    pid 14287, uptime 0:36:24

プロセスを落としてみると、自動で2プロセスにもどります。
#
# ps -ax | grep rb
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
14286 ?        Sl     0:00 /usr/local/bin/ruby /home/ec2-user/svsqs.rb
14287 ?        Sl     0:00 /usr/local/bin/ruby /home/ec2-user/svsqs.rb
14516 pts/0    S+     0:00 grep rb
#
# kill -9 14286
#
# ps -ax | grep rb
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
14287 ?        Sl     0:00 /usr/local/bin/ruby /home/ec2-user/svsqs.rb
14526 ?        Rl     0:00 /usr/local/bin/ruby /home/ec2-user/svsqs.rb

また、ログをみてみると、2つのプロセスできちんと動作しているようです。
# tail -1000f test.log
D, [2014-01-16T07:25:13.175073 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:25:23.311352 #14286] DEBUG -- : 14286 aaaaaaaa
D, [2014-01-16T07:25:23.326240 #14286] DEBUG -- : 14286 bbbbbbbb
D, [2014-01-16T07:25:23.393122 #14286] DEBUG -- : 14286 ccccccc
D, [2014-01-16T07:25:23.441076 #14286] DEBUG -- : 14286 -------
D, [2014-01-16T07:25:28.144026 #14287] DEBUG -- : 14287 ddddddd
D, [2014-01-16T07:25:28.153058 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:25:33.682118 #14286] DEBUG -- : 14286 eeeeeee
D, [2014-01-16T07:25:33.735474 #14286] DEBUG -- : 14286 fffffff
D, [2014-01-16T07:25:33.827446 #14286] DEBUG -- : 14286 -------
D, [2014-01-16T07:25:42.971976 #14287] DEBUG -- : 14287 ggggggg
D, [2014-01-16T07:25:42.986925 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:25:44.555526 #14286] DEBUG -- : 14286 hhhhhhh
D, [2014-01-16T07:25:44.606725 #14286] DEBUG -- : 14286 -------
D, [2014-01-16T07:25:53.106090 #14287] DEBUG -- : 14287 jjjjjjjj
D, [2014-01-16T07:25:53.118289 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:26:01.609948 #14286] DEBUG -- : 14286 kkkkkkkk
D, [2014-01-16T07:26:01.738742 #14286] DEBUG -- : 14286 -------
D, [2014-01-16T07:26:04.564231 #14287] DEBUG -- : 14287 llllllll
D, [2014-01-16T07:26:28.385778 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:26:34.210485 #14526] DEBUG -- : 14526 mmmmm
D, [2014-01-16T07:26:34.301180 #14526] DEBUG -- : 14526 -------
D, [2014-01-16T07:26:39.204945 #14287] DEBUG -- : 14287 nnnnn
D, [2014-01-16T07:26:39.224593 #14287] DEBUG -- : 14287 -------

こんな感じで、仮にプログラムがエラーでオチたりした場合でも、常に指定したプロセス数に起動しなおしてくれると助かります。

以上です。


2013年12月11日水曜日

AutoScalingってなんじゃ?(AutoScalingがAWSマネージメントコンソールで管理可能に!)

ついにAWSの管理コンソールからAutoScalingが管理可能になりました。

早速触ってみます。

EC2のコンソールの左ペインの最下部にAutoScaling(以下AS)の項目が追加されています。
選択してみると、左側に概要が表示されるので、「Create Auto Scaling Group」をクリックします。




Launch Configuration の作成



既存のLaunchConfiguration(以下LC)を使うか、新規にLCを作るかを聞かれるので、今回は新規LCを選びます。


すると、LC作成ウィザードに切り替わり、インスタンスの起動にまつわる設定が始まります。


AMI


インスタンスタイプ




詳細設定


ここで、LC名を入力します。
それ以外はインスタンス起動の詳細設定と同じです。




ストレージ





セキュリティグループ





確認画面






キーの選択




ここでLCで設定する鍵を選択して「Create launch configuration」をクリックすると、LCの作成は終了で、自動的にASの作成に移ります。



Auto Scaling Groupの作成



基本設定


AS作成画面では、先に新規作成したLCまたは既存から選択したLCがセットされ、AS名やサイズ、起動場所(VPCやゾーン)、バランサのヘルスチェックなどを入力します。




スケーリングポリシー


次にスケーリングポリシーを設定します。
アラームや増減の限界値や単位を設定します。



「Add new alarm」でその場でアラーム設定が可能です。




通知


通知の設定をします。ASのイベントとそれが発生した時の通知先を設定します。




確認画面


最後に確認画面で内容をチェックし、「Create auto scaling group」をクリックして設定を終えます。





Auto Scaling Groupの確認



設定の変更


一覧画面に作成したばかりのASが表示されます。
また、ASを選択すると、下部ペインの「Details」タブなどで詳細が確認でき、
「Edit」で設定の変更が可能です。

ここで、DesiredCapacityの変更もできるので、min=1, max=5, desired=1にして、1つインスタンスを起動してみます。




すると、「ScalingHistory」タブでスケーリングイベントの履歴が確認できます。
失敗イベントはその理由も記述されているので簡単なデバッグも行えます。




インスタンス一覧を見てみます。



正常に起動しているようです。


いままでASはコンソールからはまったく見えませんでしたが、これで視認性がよくなりました。
これからもコマンドライン等で設定を行うという人も、状態の確認などはコンソールを使うと便利かもしれません。


以上です。



2013年12月9日月曜日

CDPってなんじゃ?(Kinesisでstream chain)

この記事は「CDP Advent Calendar 2013」12/9用の記事です。

 前回、前々回でKinesisを触りました。

資料などみていく中で、ストリームの終端になりえるものに、Redshift, S3, EMR, DynamoDBなどの他に、別のKinesisストリームもありえるということを知りました。

処理の内容が単純、高速であったり、データ数が少ない場合には1つのConsumerで事足りると思いますが、あまりにも大量であったり、処理の幾つかに非常に時間の掛かるものがあったり、複合的な処理が必要な場合には、複数のストリームを使うと全体の効率が上がる場合があるかと思います。

これは、CDPのQueuing Chainパターンの派生的なものになるかと思います。
そこで、別のKinesisストリームに流すにはどういう場合が有効かを考えてみました。

Stream Chianパターン


・統計的な処理を連続して行う場合、Producerが投入したデータ単位と、1つ目の処理が終わったデータ単位が異なる場合があります。その場合も1つ目が終わったときに別のストリームを使います。



・処理全体の中で、負荷の高い部分と低い部分を分けて別に処理を行うことで、コストの最適化を行うことも考えられます。




・共通処理もあるが、データの種類によって個別の処理が必要という時も別のストリームを使える場合があります。




・おまけ:JettyをProducerにして、3つストリームのチェーンを使うと、ジェットストリームアタックになります。





最後のが言いたかっただけでした。
以上です。



2013年12月4日水曜日

Kinesisってなんじゃ?(Java実装編)

前回からの続きです。

このストリームをつかってイベント処理を行うアプリケーションを実装します。
Kinesisを扱うには、現時点でJavaのSDKとKinesisのクライアントライブラリ(KCL)が利用可能です。

今回のサンプルとなるシステムですが、以下のように定義してみました。
  • Producerはユーザーの出発地点(0, 0)からの到達位置(x, y)を日時ごとにJSONとしてストリームに入力していきます。
  • ConsumerAではストリームからデータを受け取り、ログとしてS3のバケットに保存していきます。
  • ConsumerBでは同じくストリームからデータを受け取り、ユーザーごとの総移動距離をDynamoDBにインクリメント保存していきます。

これを、限定公開用にKinesis対応されたJavaのSDKとKinesisのクライアントライブラリ(KCL)を使って実装してみます。SDKにはサンプルコードなどが付属しているため、それを参考に実装してみます。
また、KCLはシャードの管理のために裏側でConsumerごとにDynamoDBテーブルを使用します。

JDKの1.7とantがインストールされていることが前提です。


Producer


以下のツリー図の通り、SDKのサンプルコードの一部として他のサンプルと同じようにMemoKinesisというサンプルをつくりました。

/usr/local/src/aws-java-sdk-1.6.4/
├── lib
│   ├── aws-java-sdk-1.6.4.jar
│   ├── aws-java-sdk-1.6.4-javadoc.jar
│   ├── aws-java-sdk-1.6.4-sources.jar
│   ├── aws-java-sdk-flow-build-tools-1.6.4.jar
│   ├── commons-lang-2.6.jar
│   ├── joda-time-2.3-dist.tar.gz
│   ├── joda-time-2.3.jar
│   └── jsonic-1.3.0.jar
├── samples
│   └── MemoKinesis
│       ├── AwsCredentials.properties
│       ├── build.xml
│       ├── Hoge.java
│       └── MemorycraftKinesisProducer.java
└── third-party

配下のbuild.xmlは他サンプルと同様に、../../lib, ../../third-partyにクラスパスを通して、コンパイル→実行するようなターゲットになっているため、クラス名だけ変更してそのまま利用しています。
AwsCredentials.propertiesには自分のアカウントのキー情報を入力してあります。
また、このコードで必要なライブラリは../../libディレクトリに追加してあります(青字)。

また、コードは以下の通りです。

MemorycraftKinesisProducer.java

Hoge.java

Producerでは、testuser_[A-Z]の26人のユーザーIDと、日時、ランダムなx,y をJSON化してストリームに投入しつづけます。
AmazonKinesisClientを初期化し、PutRecordRequestを使ってputRecordします。
実行すると以下のように投入され続けていくことがわかります。
[root@ip-10-154-154-57 MemoKinesis]# ant
Buildfile: /usr/local/src/aws-java-sdk-1.6.4/samples/MemoKinesis/build.xml

run:
    [javac] /usr/local/src/aws-java-sdk-1.6.4/samples/MemoKinesis/build.xml:12: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /usr/local/src/aws-java-sdk-1.6.4/samples/MemoKinesis
    [javac] warning: Supported source version 'RELEASE_6' from annotation processor 'com.amazonaws.eclipse.simpleworkflow.asynchrony.annotationprocessor.AsynchronyDeciderAnnotationProcessor' less than -source '1.7'
    [javac] 1 warning
     [java] Dec 03, 2013 10:08:23 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:22","user_id":"testuser_F","x":"66.41701160878385","y":"85.85361518485006"}
     [java] Dec 03, 2013 10:08:23 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:23","user_id":"testuser_D","x":"64.19880893804586","y":"26.65513499028829"}
     [java] Dec 03, 2013 10:08:24 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:23","user_id":"testuser_T","x":"59.34696505060783","y":"85.54404394674596"}
     [java] Dec 03, 2013 10:08:24 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:24","user_id":"testuser_N","x":"76.26154448594934","y":"67.74843698818461"}
     [java] Dec 03, 2013 10:08:24 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:24","user_id":"testuser_Z","x":"29.457789127237753","y":"18.48254643961956"}
     [java] Dec 03, 2013 10:08:24 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:24","user_id":"testuser_Z","x":"9.91729666668798","y":"18.193714091252332"}
     [java] Dec 03, 2013 10:08:24 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:24","user_id":"testuser_M","x":"98.54843645906183","y":"83.25335740427954"}
     [java] Dec 03, 2013 10:08:24 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:24","user_id":"testuser_F","x":"22.2596852199308","y":"39.49631977033009"}
     [java] Dec 03, 2013 10:08:25 AM MemorycraftKinesisProducer main
     [java] INFO: {"datetime":"2013-12-03 10:08:24","user_id":"testuser_W","x":"35.34360225385589","y":"7.982969346289337"}
.......



Consumer A


次はConsumerです。これも同じように他のサンプルコードとほぼ同じ構成で実装しました。

/usr/local/src/aws-java-sdk-1.6.4/
├── lib
│   ├── aws-java-sdk-1.6.4.jar
│   ├── aws-java-sdk-1.6.4-javadoc.jar
│   ├── aws-java-sdk-1.6.4-sources.jar
│   ├── aws-java-sdk-flow-build-tools-1.6.4.jar
│   ├── commons-lang-2.6.jar
│   ├── jsonic-1.3.0.jar
│   └── KinesisClientLibrary.jar
├── samples
│   └── MemoKinesis
│       ├── AwsCredentials.properties
│       ├── build.xml
│       ├── ConfigKeys.java
│       ├── MemorycraftKinesisLoggingConsumer.java
│       ├── MemorycraftKinesisLoggingProcessorFactory.java
│       └── MemorycraftKinesisLoggingProcessor.java
└── third-party

Consumer Aのインスタンス群では、ストリームに流れているデータを抽出して、順次S3にログとして保存していきます。
ConsumerではKCLを使用します。

構成としては、MemorycraftKinesisLoggingConsumerからIRecordProcessorFactoryを実装したMemorycraftKinesisLoggingProcessorFactoryを初期化してワーカーとして実行します。
実際の処理はIRecordProcessorを実装したMemorycraftKinesisLoggingProcessorのprocessRecordsメソッド内部に記述します。


MemorycraftKinesisLoggingConsumer.java

MemorycraftKinesisLoggingProcessorFactory.java

MemorycraftKinesisLoggingProcessor.java

実行してみます。
[root@ip-10-118-97-158 MemoKinesis]# ant
Buildfile: /usr/local/src/aws-java-sdk-1.6.4/samples/MemoKinesis/build.xml

run:
    [javac] /usr/local/src/aws-java-sdk-1.6.4/samples/MemoKinesis/build.xml:12: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 4 source files to /usr/local/src/aws-java-sdk-1.6.4/samples/MemoKinesis
    [javac] warning: Supported source version 'RELEASE_6' from annotation processor 'com.amazonaws.eclipse.simpleworkflow.asynchrony.annotationprocessor.AsynchronyDeciderAnnotationProcessor' less than -source '1.7'
    [javac] 1 warning
..........
     [java] INFO: Successfully published 3 datums.
     [java] Dec 03, 2013 11:58:06 AM com.amazonaws.services.kinesis.metrics.impl.DefaultCWMetricsPublisher publishMetrics
     [java] INFO: Successfully published 18 datums.
     [java] Dec 03, 2013 11:58:14 AM com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker$WorkerLog info
     [java] INFO: Current stream shard assignments: shardId-000000000001, shardId-000000000000
     [java] Dec 03, 2013 11:58:14 AM com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker$WorkerLog info
     [java] INFO: Sleeping ...
     [java] Dec 03, 2013 11:58:16 AM com.amazonaws.services.kinesis.metrics.impl.DefaultCWMetricsPublisher publishMetrics
     [java] INFO: Successfully published 20 datums.
     [java] Dec 03, 2013 11:58:16 AM com.amazonaws.services.kinesis.metrics.impl.DefaultCWMetricsPublisher publishMetrics
     [java] INFO: Successfully published 3 datums.
     [java] Dec 03, 2013 11:58:18 AM MemorycraftKinesisLoggingProcessor process
     [java] INFO: process record [21269323576357670914947437401207537664]
     [java] Dec 03, 2013 11:58:18 AM MemorycraftKinesisLoggingProcessor process
     [java] INFO:  saved [json]={"datetime":"2013-12-03 08:41:05","user_id":"testuser_G","x":"54.504733903095726","y":"27.966324048617963"}
     [java] Dec 03, 2013 11:58:18 AM MemorycraftKinesisLoggingProcessor process
     [java] INFO: process record [21269323576357720993054772957520920576]
     [java] Dec 03, 2013 11:58:19 AM MemorycraftKinesisLoggingProcessor process
     [java] INFO:  saved [json]={"datetime":"2013-12-03 08:41:05","user_id":"testuser_W","x":"12.256118907591883","y":"63.004577908019634"}
     [java] Dec 03, 2013 11:58:19 AM MemorycraftKinesisLoggingProcessor process
     [java] INFO: process record [21269323576357794417499720660453949440]
     [java] Dec 03, 2013 11:58:19 AM MemorycraftKinesisLoggingProcessor process
     [java] INFO:  saved [json]={"datetime":"2013-12-03 08:41:05","user_id":"testuser_O","x":"69.81831906353719","y":"31.571006624423724"}
     [java] Dec 03, 2013 11:58:19 AM MemorycraftKinesisLoggingProcessor process
     [java] INFO: process record [21269323576357840331291814692712415232]
     [java] Dec 03, 2013 11:58:19 AM MemorycraftKinesisLoggingProcessor process
     [java] INFO:  saved [json]={"datetime":"2013-12-03 08:41:04","user_id":"testuser_F","x":"19.924814432111905","y":"41.65256488223227"}
..........


うまく拾えているようです。
S3のバケットを見てみます。

おお、次から次へとファイルが保存されていくのがわかります。
そのうちの一つをダウンロードして、中身を見てみます。
{"datetime":"2013-12-03 08:44:17","user_id":"testuser_H","x":"79.49199108301805","y":"2.4829017202529724"}
中身もうまく入っているようです。


Consumer B



次はConsumerBです。

/usr/local/src/aws-java-sdk-1.6.4/
├── lib
│   ├── aws-java-sdk-1.6.4.jar
│   ├── aws-java-sdk-1.6.4-javadoc.jar
│   ├── aws-java-sdk-1.6.4-sources.jar
│   ├── aws-java-sdk-flow-build-tools-1.6.4.jar
│   ├── commons-lang-2.6.jar
│   ├── jsonic-1.3.0.jar
│   └── KinesisClientLibrary.jar
├── samples
│   └── MemoKinesis
│       ├── AwsCredentials.properties
│       ├── build.xml
│       ├── ConfigKeys.java
│       ├── Hoge.java
│       ├── MemorycraftKinesisDistanceConsumer.java
│       ├── MemorycraftKinesisDistanceProcessorFactory.java
│       └── MemorycraftKinesisDistanceProcessor.java
└── third-party


Consumer Bのインスタンス群では、ユーザーIDをハッシュキーにしたDynamoDBのレコードにXとYから距離を出してインクリメントしていき総距離を加算更新します。

クラスとしてはMemorycraftKinesisDistanceProcessorを中心に実装します。

MemorycraftKinesisDistanceConsumer.java

MemorycraftKinesisDistanceProcessorFactory.java

MemorycraftKinesisDistanceProcessor.java

実行してみます。

[root@ip-10-60-155-21 MemoKinesis]# ant
Buildfile: /usr/local/src/aws-java-sdk-1.6.4/samples/MemoKinesis/build.xml

run:
    [javac] /usr/local/src/aws-java-sdk-1.6.4/samples/MemoKinesis/build.xml:12: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
     [java] Dec 03, 2013 3:22:17 PM MemorycraftKinesisDistanceConsumer configure
     [java] INFO: Using workerId: ip-10-60-155-21.ec2.internal:584216f1-8d4d-429c-ba99-8af365345e17
     [java] Dec 03, 2013 3:22:17 PM MemorycraftKinesisDistanceConsumer configure
.......
     [java] INFO: Successfully published 18 datums.
     [java] Dec 03, 2013 3:23:18 PM com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker$WorkerLog info
     [java] INFO: Current stream shard assignments: shardId-000000000001, shardId-000000000000
     [java] Dec 03, 2013 3:23:18 PM com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker$WorkerLog info
     [java] INFO: Sleeping ...
     [java] Dec 03, 2013 3:23:18 PM MemorycraftKinesisDistanceProcessor process
     [java] INFO: process record [21269323576357670914947437401207537664]
     [java] Dec 03, 2013 3:23:19 PM MemorycraftKinesisDistanceProcessor process
     [java] INFO:  saved [user_id:testuser_G, distance:61.260764757221075]
     [java] Dec 03, 2013 3:23:19 PM MemorycraftKinesisDistanceProcessor process
     [java] INFO: process record [21269323576357720993054772957520920576]
     [java] Dec 03, 2013 3:23:19 PM MemorycraftKinesisDistanceProcessor process
     [java] INFO:  saved [user_id:testuser_W, distance:64.18558473711015]
     [java] Dec 03, 2013 3:23:19 PM MemorycraftKinesisDistanceProcessor process
     [java] INFO: process record [21269323576357794417499720660453949440]
     [java] Dec 03, 2013 3:23:19 PM MemorycraftKinesisDistanceProcessor process
     [java] INFO:  saved [user_id:testuser_O, distance:76.62457919060493]
.....


それではDynamoDBを見てみます。
ちゃんとユーザーごとに集計されているようです。


続々加算されていきます。



チェックポイント



KinesisのコンシューマーでKCLを使うとコンシューマーごとにチェックポイントというマーカーを打つことができます。
IRecordProcessor.checkpointメソッド内で、checkpointer.checkpoint()を呼び出すと、ストリームのシーケンスのなかでどこまで読み込んだという記録が保存され、読み取りを中断したり障害が起こった後に、プロセスを再稼働すると、そのチェックポイントから読み取りが再開されます。
チェックポイントを呼び出すタイミングはユーザーに委ねられていて、今回のサンプルでは1分に設定しています。

   private static final long CHECKPOINT_INTERVAL_MILLIS = 60000L;
    public void processRecords(List records, IRecordProcessorCheckpointer checkpointer) {

        process(records);

        if (System.currentTimeMillis() > nextCheckpointTimeInMillis) {
            checkpoint(checkpointer);
            nextCheckpointTimeInMillis = System.currentTimeMillis() + CHECKPOINT_INTERVAL_MILLIS;
        }

    }


わかったこと


  • 定期的ではなく常にデータ処理を処理し続けることができる仕組みと、そのためのスケーラビリティを持っている。
  • ユーザーが書くコードは、最低限であればそんなに多くない。
  • バッチではタイムラグがありすぎる!という場合にはうってつけのサービス。
  • Consumer同士の処理順を気にしないでいい。処理順をつけたい場合は、そのConsumer内で行うか、出力先に別のストリームを指定しそちらで次の処理をするとか
  • DynamoDBと同様、ストリームのキャパシティの見積もりは必要です。でもシャード数を指定するだけなので変更自体は簡単
  • 周辺のインスタンス、特にConsumerはバッチと同様インスタンスの負荷をみてロールごとにAutoScalingGroupを作る必要あり
  • Consumerからデータの移動先となるDynamoDBやRedshiftその他のエンドポイントのキャパシティ管理も同様に注意が必要


以上です。

Kinesisってなんじゃ?(ストリーム作成編)

AWSの新サービスKinesisが限定プレビュー公開されています。
私のところでも見れるようになったので、触ってみました。

Kinesisとは


Kinesisは大量なデータのリアルタイムイベント処理をサポートするサービスです。
ユーザーは「ストリーム」を作り、そこにデータを流し、受け取り、処理を行います。

データを流す、受け取る、処理を行う、という部分はユーザーがプログラムで実装します。
Kinesisに接続するプログラムには大きく分けてProducerとConsumerという2つの立場があります。
  • Producerはストリームにデータを入力します。Producerは場合によってWEBまたはAPPサーバーのようなエンドポイントであったり、既存データのフェッチプログラムとして実装されます。
  • Consumerはストリームからデータを受け取り処理します。Consumerは処理内容ごとにAutoScalingグループなどによってクラスタ化されることが多くなります。

ストリームを流れるデータは順序付けされたシーケンスとして扱われ、「シャード」に分散されます。
また、Kinesisではシャードの単位でスループットが決定され、ユーザーは入出力の量に合わせてシャード数を設定できます。


ストリームの作成


それでは、まずストリームを作ってみます。
限定公開なので、コンソールのメニューには現れませんが、申請が通っている場合は、以下のURLでアクセスできます。

https://console.aws.amazon.com/kinesis/



「Create Stream」をクリックして、ストリームを作成します。
ストリーム名とストリーム数を入力します。
ストリーム数の目安がわからない場合は、DynamoDBと同じように、データサイズや書込回数、Consumer数を設定することで自動的に最適なシャード数を適用できます。




「Create」をクリックすると、作成中(CREATING)のストリームが一覧に表示されます。
Statusが「ACTIVE」になると利用可能です。



ストリーム名をクリックすると、ストリームのメトリクスが表示されます。
これをもとに、SDKなどでシャード数の変更などを行うことができます。



料金



  • シャード:1シャードあたり1時間0.015ドル
  • リクエスト:100万PUTで0.028ドル
  • データ転送(入力):無料 
  • データ転送(出力):EC2で処理する分には無料

これとは別に、実際の処理を行うEC2のインスタンス料金が掛かります。
ストリームの料金ではなく、接続するEC2の料金で回収するモデルのようです。


次回は、ストリームを使った実装をやってみます。
以上です。




2013年11月16日土曜日

re:Inventってなんじゃ?(CloudTrail)

re:Invent2013に来ています。
そこでCloudTrailの発表があったので触ってみました。

CloudTrailは、AWSのAPIコールの記録をS3にログとして保存するサービスです。
これによってセキュリティ分析や運用チェックなどを行うことが可能です。

AWSコンソールをみるとCoudTrailが追加されているので、開いてみます。


ログの保存先のS3バケットを指定して、必要であればその他のオプションも設定します。


Subscribeボタンを押すと、設定完了です。



しばらく、AWSの操作をしたあと、出力先に設定したS3バケットを確認します。
すると、以下のように、json形式のログファイルが圧縮された状態で日ごとに保存されるようになります。



このうちの一つをダウンロードして中身を見てみます。

{
    "Records": [
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeRouteTables", 
            "eventSource": "ec2.amazonaws.com", 
            "eventTime": "2013-11-15T18:08:00Z", 
            "eventVersion": "1.0", 
            "requestParameters": {
                "filterSet": {}, 
                "routeTableIdSet": {}
            }, 
            "responseElements": "<responseOmitted>", 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }, 
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeSubnets", 
            "eventSource": "ec2.amazonaws.com", 
            "eventTime": "2013-11-15T18:07:59Z", 
            "eventVersion": "1.0", 
            "requestParameters": {
                "filterSet": {}, 
                "subnetSet": {}
            }, 
            "responseElements": "<responseOmitted>", 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }, 
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeVpcs", 
            "eventSource": "ec2.amazonaws.com", 
            "eventTime": "2013-11-15T18:07:58Z", 
            "eventVersion": "1.0", 
            "requestParameters": {
                "filterSet": {}, 
                "vpcSet": {}
            }, 
            "responseElements": "<responseOmitted>", 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }, 
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeSecurityGroups", 
            "eventSource": "ec2.amazonaws.com", 
            "eventTime": "2013-11-15T18:08:03Z", 
            "eventVersion": "1.0", 
            "requestParameters": {
                "filterSet": {}, 
                "securityGroupIdSet": {}, 
                "securityGroupSet": {}
            }, 
            "responseElements": "<responseOmitted>", 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }, 
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeNetworkAcls", 
            "eventSource": "ec2.amazonaws.com", 
            "eventTime": "2013-11-15T18:08:01Z", 
            "eventVersion": "1.0", 
            "requestParameters": {
                "filterSet": {}, 
                "networkAclIdSet": {}
            }, 
            "responseElements": "<responseOmitted>", 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }, 
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeDBInstances", 
            "eventSource": "rds.amazonaws.com", 
            "eventTime": "2013-11-15T18:08:06Z", 
            "eventVersion": "1.0", 
            "requestParameters": null, 
            "responseElements": null, 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }, 
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeVolumes", 
            "eventSource": "ec2.amazonaws.com", 
            "eventTime": "2013-11-15T18:08:04Z", 
            "eventVersion": "1.0", 
            "requestParameters": {
                "filterSet": {}, 
                "volumeSet": {}
            }, 
            "responseElements": "<responseOmitted>", 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }, 
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeAddresses", 
            "eventSource": "ec2.amazonaws.com", 
            "eventTime": "2013-11-15T18:08:03Z", 
            "eventVersion": "1.0", 
            "requestParameters": {
                "allocationIdsSet": {}, 
                "filterSet": {}, 
                "publicIpsSet": {}
            }, 
            "responseElements": "<responseOmitted>", 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }, 
        {
            "awsRegion": "us-east-1", 
            "eventName": "DescribeInstances", 
            "eventSource": "ec2.amazonaws.com", 
            "eventTime": "2013-11-15T18:08:02Z", 
            "eventVersion": "1.0", 
            "requestParameters": {
                "filterSet": {}, 
                "instancesSet": {}
            }, 
            "responseElements": "<responseOmitted>", 
            "sourceIPAddress": "54.249.240.229", 
            "userAgent": "aws-sdk-php/1.6.2 PHP/5.4.20 curl/7.19.7 openssl/1.0.0-fips", 
            "userIdentity": {
                "accessKeyId": "xxxxxxxxxxxxxxxxxx", 
                "accountId": "821635308497", 
                "arn": "arn:aws:iam::821635308497:root", 
                "principalId": "821635308497", 
                "type": "Root"
            }
        }
    ]
}


このように呼び出したAPIの内容が表示されるため、jqやログ解析ツールなどと併用してAWSアカウントに対してどういった操作があったかを簡潔に知ることが可能になります。

以上です。

2013年9月26日木曜日

EBSってなんじゃ?(cryptsetup + S3 + IAM Roleでディスク暗号化鍵をS3で管理)

EBSの暗号化の方法のひとつとしてcryptsetupという技術があります。cryptsetupはパスフレーズで暗号化されたディスクにアクセス(マウント)しますが、今回は鍵ファイルを使用してアクセスする手順をまとめました。
また、鍵ファイルを同じインスタンス内に置かないためにS3から鍵ファイルを取得し、マウントした後に削除するようにします。

それでは手順を追ってみます。

まずcryptsetupで/dev/xvdfにアタッチされたEBSボリュームの暗号化を行い、マウントします。
# yum install -y cryptsetup
# yum install xfsprogs -y
# cryptsetup luksFormat -c aes -h sha256 /dev/xvdf
# cryptsetup luksOpen /dev/xvdf encrypted
# ls -l /dev/mapper/
# mkfs.xfs /dev/mapper/luks
# mkdir /mnt/vol
# mount -t xfs /dev/mapper/luks /mnt/vol
# mkdir /mnt/vol/data


次に鍵ファイルを作成し、cryptsetupに登録します
# dd if=/dev/urandom of=/root/encrypted_key bs=1 count=1024
# cryptsetup luksAddKey /dev/xvdf /root/encrypted_key


S3バケットを作成し、そこへ鍵を保管します




自動で暗号化+マウントするために起動スクリプトをつくり、S3から鍵ファイルを取得しマウントするようにします。終わったらAMIを作成します。
# cat /etc/init.d/cryptmount
-----------
#!/bin/sh
#
#
# chkconfig: 345 60 16

aws s3 get-object --region ap-northeast-1 --bucket luks-key --key xvdf_luks_key /boot/xvdf_luks_key
cryptsetup luksOpen /dev/xvdf luks --key-file /boot/xvdf_luks_key
mount -t xfs /dev/mapper/luks /mnt/vol
rm -rf /boot/xvdf_luks_key
-----------

# rm -rf /root/xvdf_luks_key



IAM Roleを作成し、S3へのアクセスを許可します



作成したAMIの起動時にIAM Roleを指定します




これで、鍵がない状態ではEBSをマウントすることができなくなりました。
以上です。

2013年5月28日火曜日

Fluentdってなんじゃ?(設定ファイルをリモートから読み込む)

fluentdのドキュメントに以下のような記載がありました。

Configuration File - (3) Include Directive
# absolute path
include /path/to/config.conf

# if using a relative path, the directive will use 
# the dirname of this config file to expand the path
include extra.conf

# glob match pattern
include config.d/*.conf

# http
include http://example.com/fluent.conf

最後の行、、、HTTPから設定ファイルを取得してインクルードできるみたいです。

ということで試してみました。

common.conf
<source>
  type tail
  format apache
  pos_file /var/log/td-agent/httpd-access.log.pos
  path /var/log/httpd/access_log
  tag apache.access
</source>

<match apache.access>
  type s3

  aws_key_id xxxxxxxxxxxxxxxxxxx 
  aws_sec_key yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
  s3_bucket hoge-bucket
  path logs/
  buffer_path /var/log/fluent/s3
  flush_interval 10s 
</match>

これをS3にアップロードしてWEBホスティングしてみます。


そして、EC2では以下のように設定します。

/etc/td-agent/td-agent.conf
include http://s3-ap-northeast-1.amazonaws.com/hoge-bucket/conf/fluentd/common.conf
# /etc/init.d/td-agent start


httpdのコンテンツにアクセスしてしばらくたつと、、、


無事出力されていました!

これの何がいいかというと、

  • 各サーバーに共通の設定ファイルなどを外部化しておき、一括変更をかけられる (再起動は必要ですが、定期的に再起動をかけるようにしておくという手もあります)
  • いっそ全設定を外出しして完全に外部で管理する

などが可能になります。

以上です。

2013年5月7日火曜日

Redshiftってなんじゃ?(BI編:JaspersoftでRedshift)

前回はpsqlでRedshiftを利用してみましたが、通常データウェアハウス(DWH)というのはBI(Buisiness Intelligence)ツールを利用することが多いようです。

エンジニアの観点からすると複雑なSQLを書くだけでいいかもしれませんが、経営者などの立場からするとBIツールなどを使って画面上でポチポチやって分析できることが重要なようです。

今回はそのBIツールの中で、Redshiftにいち早く対応しているJaspersoftという製品を使ってRedshiftに接続してみたいと思います。




起動とログイン



RedshiftとRDSに対応してあるバージョンのJaspersoftのAMIがマーケットプレイスにあるので、それを購入します。

Jaspersoft Reporting and Analytics for AWS
https://aws.amazon.com/marketplace/pp/B00B527JQ0





このAMIはインスタンスのランニングコスト以外にもソフトウェアの使用料金が時間単位で掛かります。
ここでは、RedshiftのあるUSのリージョンで起動します。




AWSコンソールのページが開き、インスタンス起動のウィザードが実行されます。




Redshiftと同じゾーンを選択します。
今回はm1.mediumのサイズで立ちあげます。




ここではルートボリュームを100GBにします。



また、セキュリティグループではSSHとHTTPをあけておきます。




起動させたあと、このインスタンスのPublicDNSまたはEIPに対してローカルのブラウザからアクセスしてみます。
すると、jasperサーバーの初期画面が表示されるので、「Login」をクリックします。



すると、ログイン画面が表示されます。



「ログインのお手伝いが必要ですか」というリンクをクリックすると、下図のように初期のID、パスワードが表示されます。ここではsuperuserでログインしてみます。



すると、新しいパスワードを要求されるので、好きなパスワードを設定して改めてログインします。



これでログインすることが出来ました。
これがJasperサーバーのホーム画面のようです。





データソースの登録



次に、データソースを作成します。
ここでいうデータソースとは、データがある場所をしめします。
データベースの場合やファイルの場合などがあり、ここではRedshiftをデータソースとして登録します。
グローバルヘッダの「作成」から「Data Source」を選択します。


 データソース作成画面では、タイプ欄からいくつかのデータソースタイプが選択でき、今回は「JDBC Data Source」を選択します。




ちなみに「AWS Data Source」でRedshiftを選択しても接続できます。






ドメインの作成



次にドメインを作成します。ドメインとはビューに渡すデータセットに当たります。
データソースからデータを選別してビューに渡すために整理した状態にします。

グローバルヘッダから「作成 > ドメイン」を選択します。

 ドメイン作成画面では、ドメイン名と作成したドメインの保存場所を適当に入力します。
また、データソースには先ほど作成したRedshiftのデータソースを選択します。
そして、ドメインデザイナのリンクをクリックします。


すると、ドメインデザイナが開き、データソースの「テーブル」タブが表示されます。
ここで、「>」ボタンなどで使用するテーブルを右側の枠に持っていきます。


次の「派生テーブル」タブで選択されたテーブルを対象に直接クエリ(SubQuery)などをかけられたり、



複数のテーブルを結合(Join)できたり、



フィルタ(Where)をかけられたり


などといったことができます。
つまりドメインというのはGUIでつくるSQL、つまりクエリビルダのようなものです。

最後の「表示」タブでは、このようにして作ったデータセットに対して、レポート表示時のラベルをつけれたりできます。




 そして「OK」を押すと、ドメインにこの設定が保存されます。
 ドメイン作成画面に戻り、「送信」を押すとこのドメインが作成されます。





アドホックビューの作成



次にアドホックビューを作成します。
アドホックビューは、レポート用の様々なタイプのビューで、グラフなどを作成できます。




アドホックビューでは最初に、入力ソースを選択します。
ここでは、さきほど作成したドメインを選択します。





 次に、ドメインに含まれるフィールドを選定します。
使用するフィールドを右側に移動し、下部のボタンから、テーブルやグラフなど表示タイプのボタンを押します。 今回は「グラフ」のボタンを押します。





すると、UIデザインの画面が開きます。
 ここで、左側の「フィールド」と「メジャー」から中央上部の「列」や「行」に適用する項目をドラッグします。この部分はGoogle Analyticsでカスタムレポートに指標やディメンションを追加するのに似ています。




 ここでは、列にprefecture_name, 行にcntをセットして、右側のデータラベルを右側にスライドします。
すると以下のようにグラフが自動で作成されます。
グラフのタイプを変更するには、グラフ左上の歯車アイコンをクリックして、変更します。





保存する場合は、中央ツールバーのディスクアイコンで保存します。








レポートの作成



 次に、レポートを作成します。
レポートは基本的に、アドホックビューを選択するだけです。





レポート作成画面でもグラフのタイプを変更することができます。



 ツールバーのディスクアイコンでレポートを保存します。






ダッシュボードの作成



最後はダッシュボードです。



ダッシュボードの作成画面では、複数のレポートを貼り付けたり、コントロールを貼り付けたりして帳票としての全体的な画面をつくります。




作成されたダッシュボードは以下のようになります。
このように、DBの知識がほとんどなくてもいろいろなデータの見た目をプリセットで整えて、手軽に更新、確認できるのがBIツールの役目のようです。





まとめ



Jaspersoftを使ってみた感覚としては、独特のコンポーネントにつけられた用語や意味を把握するのに少し戸惑いますが、慣れてしまうとそれなりに直感的に操作ができます。

ただ、異なるデータソースのデータ同士をJoinできるかと思ったのですが、やりかたがわかりませんでした。
その場合は、RedshiftにインポートしてRedshiftデータソースとして、ドメイン内でJoinしてしまえばよいかなと思います。


以上です。