はやさがたりない。

へっぽこぷろぐらまのメモログ

serverlessで一つのfunctionをrunする方法

公式ドキュメントには

sls function run myModule/myFunctions#functionOne

って書いてあるけど実際にそれでやっても

Serverless: Select a function to run: 
    myFunctions
  >   functionOne
      functionTwo

ってなっちゃうのでもやもやしてた。

こう書いたら選択しなくてもテストできるのですな。

sls function run -n functionOne

serverless さわってみた

所感

serverless (旧名JAWS)の使い勝手を調べてみた。
結果としては割といい感じ。
serverlessならansibleとかもいらなくなる!
AWSのリソースもserverlessの中のCloudFormationでOKだぜ!!みたいな。。?
まだまだドキュメントは少ないけど、もうちょっと勉強していこうと思う。。

手順

初期セットアップ

※Node 4系以上が必要

$ sudo npm install serverless -g
$ mkdir ~/.aws
$ vi ~/.aws/credentials
--
[default]
aws_access_key_id=<<アクセスキー>>
aws_secret_access_key=<<シークレットアクセスキー>>
--
$ vi ~/.aws/config
--
[default]
region = ap-northeast-1
--

作ってみる

$ serverless project create
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                          serverless.com, v.0.0.12
`-------'
Serverless: Enter a project name:  (serverlessN1A2rULrx) akira-test
Serverless: Enter a project domain (used for serverless regional bucket names):  (myapp.com) akira-test.com
Serverless: Enter an email to use for AWS alarms:  (me@myapp.com) 
Serverless: Select a region for your project: 
    us-east-1
    us-west-2
    eu-west-1
  > ap-northeast-1
Serverless: Select an AWS profile for your project: 
  > default
Serverless: Creating a project region bucket on S3: serverless.apnortheast1.akira-test.com...  
Serverless: Creating CloudFormation Stack for your new project (~5 mins)...  
Serverless: Successfully created project: akira-test  
  • 作られたもの
    • S3 
    • IAM Group
    • IAM Role
  • ディレクトリ構成
-rw-r--r--  1 arika  staff   11 12 13 21:38 README.md
-rw-r--r--  1 arika  staff  136 12 13 21:38 admin.env
drwxr-xr-x  4 arika  staff  136 12 13 21:38 back
drwxr-xr-x  3 arika  staff  102 12 13 21:38 cloudformation
drwxr-xr-x  2 arika  staff   68 12 13 21:38 plugins
-rw-r--r--  1 arika  staff  495 12 13 21:41 s-project.json

CloudFormationでIAMあたりを作っているっぽ。S3は別。
CloudFormationのテンプレートが自動生成されて、そこにIAMのロールやらの定義が書かれている。
んで、おそらくここにAWS elsaticsearchの設定とかを書いておいてserverless resources deployってやるとデプロイされる、とかができるための仕組みだと思う。
AWSのリソースの管理もできるということですね。素晴らしい。

モジュールとかファンクションとかを作る

$ serverless module create -m greetings -f hello
Serverless: Successfully created hello function.  
Serverless: Installing "serverless-helpers" for this module via NPM...  
serverless-helpers-js@0.0.3 node_modules/serverless-helpers-js
└── dotenv@1.2.0
Serverless: Successfully created new serverless module "greetings" with its first function "hello"  

$ ls -l back/modules/greetings/
total 16
drwxr-xr-x  5 arika  staff  170 12 13 21:49 hello
drwxr-xr-x  3 arika  staff  102 12 13 21:49 lib
drwxr-xr-x  3 arika  staff  102 12 13 21:49 node_modules
drwxr-xr-x  2 arika  staff   68 12 13 21:49 package
-rw-r--r--  1 arika  staff  359 12 13 21:49 package.json
-rw-r--r--  1 arika  staff  277 12 13 21:49 s-module.json

backっていうディレクトリの下にhelloっていうのができて、
そこのhandler.jsってやつがメイン処理っぽい。。。?

back/modules/greetings/hello/handler.js
'use strict';

/**
 * Serverless Module: Lambda Handler
 * - Your lambda functions should be a thin wrapper around your own separate
 * modules, to keep your code testable, reusable and AWS independent
 * - 'serverless-helpers-js' module is required for Serverless ENV var support.  Hopefully, AWS will add ENV support to Lambda soon :)
 */

// Require Serverless ENV vars
var ServerlessHelpers = require('serverless-helpers-js').loadEnv();

// Require Logic
var lib = require('../lib');

// Lambda Handler
module.exports.handler = function(event, context) {

  lib.respond(event, function(error, response) {
    return context.done(error, response);
  });
};

...いや、こっちか?でもlibの下にメイン処理があるもんか?
おそらくhandlerはいじらずここだけ意識していじればいいぜって感じか?

back/modules/greetings/lib/index.js
/**
 * Lib
 */

module.exports.respond = function(event, cb) {

  var response = {
    message: "Your Serverless function ran successfully!"
  };

  return cb(null, response);
};

lambdaへのデプロイ

$ serverless function deploy
Serverless: Deploying functions in "development" to the following regions: ap-northeast-1  
Serverless: Successfully deployed functions in "development" to the following regions: ap-northeast-1  

api gatewayへのデプロイ

$ serverless endpoint deploy
Serverless: Deploying endpoints in "development" to the following regions: ap-northeast-1  
Serverless: Successfully deployed endpoints in "development" to the following regions:  
Serverless: ap-northeast-1 ------------------------  
Serverless:   GET - https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/development/greetings/hello  

ローカルでのテスト

ローカルでのテストも簡単にできるのは素晴らしい。

$ serverless function run
Serverless: Running GreetingsHello...  
Serverless: -----------------  
Serverless: Success! - This Response Was Returned:  
Serverless: {"message":"Your Serverless function ran successfully!"}  

リンク集

http://docs.serverless.com/v0/docs
http://qiita.com/mokemokechicken/items/f81c886053f7d81a655d

elasticsearch勉強会

elasticsearch勉強会

percolatorのユースケース

  • アラート
    インデックスが特定のクエリにマッチしたら教えてくれ。

  • 広告出稿する場合
    ユーザがサイト検索する
    アパートを検索して結果を表示するが
    新しいマッチする物件が出たら知りたい
    どのメールに通知すればいいのかみたいなのを取得して通知することができる

  • 分類
    ニュースサイトやブログがあってカテゴリわされている
    カテゴリは検索として表現できる
    ニュースに地域などの属性があれば東京のニュース一覧とかできる
    どの記事がどの地域に属するかというのを設定するにはどうしたら良いか
    percolation queryを使えばどの記事がどの地域に属するかということを簡単に設定できる。
    記事をかいてpercolationを使えばその記事のカテゴリを得られる

  • groclassificationについて
    例えば緯度経度を使って検索することもできるけど検索はめんどい
    percolationを使ってこのお地域はどの地域内にあるみたいなことも。

  • 言語の検出にも使える
    日本語は簡単だけどラテン語なんかは難しい
    特定の言語固有の単語などもあるのでこの言語にしかない単語をpercolationクエリとして
    設定しておけば言語判別できる

  • percolatorにはメタデータを設定できる
    いつそのクエリが保存されたのかなどなど
    課金している人にのみ通知したい場合、課金しているかという情報もメタデータになる
    そのメタデータによって通知の頻度を変えるとかもできる

  • ハイライトをできる
    特定のトピックについて通知をしてもらいたい場合
    トピックをpercolatorとして保存しておいて結果をハイライトできる

これが reverse search

esとRDBMSを検索するのはどう違うか

単にマッチするかどうかだけでなく、関連性も検出できる

TF-IDF
TF term frequency : 単語の出現頻度、頻度により関連性を調べられる。
IDF : どれくらいドキュメント内でレアかどうか
例えばisとかtheとか検索してもほぼ全部のドキュメントに出てくるので
あんまり関連性の重要性には寄与しない。

luceneはTF-IDF以外にもフィールドの長さを加味する
東京の本で東京について検索した場合たくさんヒットするけど
その中のタイトルでヒットすれば関連性が高いと言える

function scoreという機能を使えばドキュメント自体に
格納されていない情報も検索のタイミングでスコア算出につかうことができる
映画を検索した場合、映画のレビュー情報も算出できる。

レビューの星の数だけでソートしないほうがいいですね?
それだけでランクが決まってしまうので。
でも少しだけ順序に入れると良い。。

ホテルを検索する例
grand hotelというホテルを検索
指定した地点から1km以内がいいと指定した場合、1km以内であれば完全にマッチとするけど
そこから離れていても検査くっかに入れる
バルコニーが欲しいと指定した場合、バルコニーがなくても検索結果に入れる
でもバルコニーがあればより検索結果の上位に出すようにする
populartyというフィールド(レビュー)もランクに加味する
さらに幾分ランダムも入れる。つど発見があるように。
これらのウェイトはチューニング可能。
esは単語の頻度だけではなくいろんな情報を持っている。

aggregationについて

facetsともいう。
githubの検索結果の左側のようなやつ。
検索結果の中から検出したものでオーバービュートなる(どの言語がどれくらいあるかとか)
esを使うことで多次元の情報を見ることができる。
グラフ化するだけならRDBMSでもでk里う。

  • レコメンデーション
    音楽について、特定のアーティストをlikeしているかどうか。
    誰がどのアーティストをlikeしているのかという情報を格納する。
    レコメンドする方法としてアーティストを検索して
    さらにアーティストをlikeしている人を算出。
    でも人気は必ずしも寒冷生徒はなりません。
    termsでaggregateする代わりにsignificant term というものを使う。
    これはaggregationの一種で単に人気があるということだけでなく、
    特定のグループ内で突出しているものを調べられる。
    アーティストを、誰が、likeしているのかという情報持っているし、
    転値インデックスもあるので検出できる。
    バンドをlikeした人数と、その検索termでlikeした人数を比較すれば
    突出したものを検知することができる。

  • sampler aggregation es2.0の新機能
    例えば1ユーザにつき1ドキュメントだけ、とかできる。
    1ユーザが何百ドキュメントを持っている場合効率的。
    自分と同じものをよりたくさんlikeしている人は近い傾向を持っているとわかる。
    誰もが好きなバンドをlikeしているというのはあまり参考にならないが
    レアなバンドであれば大変好みが近いと言える(TF-IDFの応用)
    sampler aggregationを使えばより効率的に、すばやくレコメンデーションできる。

  • wikipediaの記事をグラフ化した場合、各記事同士がたくさんリンクしている。
    共通のコネクションが大事。
    たくさん調べればスーパーノード(共通してリンクしているノード、記事)がわかる
    でも、人名が人物とリンクしているという情報なんかは意味があまりない。

    カンファレンスで、どのwebサイトによく行きますか?と聞いたら
    githubとかstackoverflowと答えが出るでしょう。
    googleではなく、これがカンファレンス特有の答えです。

    人間が、世の中をどういう風に見ているのかと同じ考え方。
    データを期間で区切って調べる(週とか時間とかで)
    signficant term を調べたら何が得られるか?例えばハッシュタグで。
    その日で他の人に比べてたくさん使われているハッシュタグがわかる。
    トレンドがわかる。
    情報は力です。

    esを使えばよりたくさんの情報が得られる。

next stack

  • elasticsearch

    • task management api
    • reindex api
  • logstash (event hub的な)

    • clustering
    • persistent
  • kibana

    • custom app / plugins
  • Beats (fluentd agent的な)

    • packetbeat
    • filebeat
    • topbeat
  • commercial plugins

    • pdf reporting
    • orchestration / automation

Amazon SQSのテストでelasticMQを使おうとしてちょっとハマった話

最近はもっぱら AWS を使ったサービスの開発をしている。
あいかわらず、サーバサイド(Java)の開発+ちょっとインフラも。

さてさて、今回は Amazon SQS を使うことになった。
SQS周りの単体テストをしょうということで elasticMQ っていう子を使うことになりました。

adamw/elasticmq · GitHub

今回はそのelasticMQの使い方でちょっとハマっている話。

elasticMQはAmazonSQS互換のインターフェースを持っている子で起動の仕方は大きく2種類ある。
Readmeにも書いてあるけども

  • プロセスとして起動する方法
    java -jar elasticmq-server-0.8.8.jar

  • JUnitとかのテスト内で起動する方法

val server = SQSRestServerBuilder.start()
// ... use ...
server.stopAndWait()

ローカル環境で開発するときにはプロセスとして起動しながらサーブレット起動して動作確認したり。
JUnitでの単体テストのときはテスト内で起動したり。そんな感じで使ってる。

で、CI環境では(ちょっとテストがいけていないっていうのもあるけども)
プロセスが起動してあることが前提で動くAPIのRESTテストと
テスト内で起動して動作確認をする単体テスト両方が動く。

この時にテストの中でキューのメッセージを消しているはずなのに消せない!って問題が起きた。
というかそもそもキューがない!って言われる。

流れはこんな感じ。
maven testを流すと下の流れでテストが動く。

  1. RESTのテスト
    1. APIのテストを実施(この中でプロセスElasticMQにメッセージを発行)
  2. 単体テスト
    1. テスト内でElasticMQ起動
    2. ElasticMQに接続してキューを削除(しているつもりだった)
    3. テストで起動したElasticMQにメッセージを発行
    4. メッッセージの確認(APIテストのメッセージが残ってる!!)

ちゃんとした原因は、まだわかっていないんだけども

$ netstat -an | grep 9324

tcp46      0      0  *.9324                 *.*                    LISTEN     <---- プロセスで起動したElasticMQ
tcp4       0      0  127.0.0.1.9324         *.*                    LISTEN     <----テスト内で起動したElasticMQ

このように起動したプロセスが同じポート使って別ヤツもので動くっぽい。
ポートってぶつかってたらダメなやつだと思っていたけども
「tcp46」と「tcp4」だったら別ヤツでうごけるの?
それともアドレスが「*」と「127.0.0.1」 だから?<--多分こっち (ここわかってないのでインフラ先生に教えを乞おう)

キューへのアクセッサーはシングルトンなので接続状態とかテストをどうやって実行するかも関係してて

  1. RESTのテスト
    1. APIのテストを実施(この中でプロセスElasticMQにメッセージを発行)
      (ここで「*.9324」へのコネクションを確立している)
  2. 単体テスト
    1. テスト内でElasticMQ起動
    2. ElasticMQに接続してキューを削除(しているつもりだった)
      (ここは「127.0.0.1.9324」へ接続、消しているつもりになっていた)
    3. テストで起動したElasticMQにメッセージを発行
      (こっちは「*.9324」に接続している)
    4. メッセージの確認(APIテストのメッセージが残ってる!!)
      (こっちは「*.9324」に接続している)

ということで失敗してしまっていた様子。

今回の対処方法は2つ?

1つ目

  • プロセス起動側の設定ファイルを指定する(elasticMQのReadme 参照)
    bind-hostname = "127.0.0.1"
  • テスト内の起動時にすでにプロセス側が起動していたら(java.lang.RuntimeException: Binding failed.例外が発生したら)スルーする。

2つ目

  • テスト内の起動時にインターフェースを「"0.0.0.0"」で設定して、 すでにプロセス側が起動していたら(java.lang.RuntimeException: Binding failed.例外が発生したら)スルーする。
SQSRestServerBuilder.withInterface("0.0.0.0").start();

1つ目のやり方だと他の人にも影響がでてしまうので2つ目のやり方で試してみようと思う。

Amazon Linux で yum update したら Ansible が動かなくなった

今日Amazon Linux 上でAnsibleを実行したら

--

ImportError: No module named yum

--

とか言われて動かなくなった。

 

つい先日まで動いていたのに、なんでやねんとおもいつつ調べてみたら
どうやら Amazon Linux 2015.03 がリリースされていて色々と変わっていたらしい。
(何でこんなタイムリーなんだ…と思いつつ)

Amazon Linux AMI 2015.03 Release Notes

今回問題になったのが 「Python 2.7 by default」となったこと。
Ansible で yum update を実行しているのだけど
それでpythonのバージョンが上がっていた。

 

バージョンが上がっても普通に動いてくれればいいんだけど、
python2.6側が動かなくなっているみたいで
Ansibleの実行対象サーバ側で

--

> python
> import yum

--

とするだけでもエラーとなった。

 

この事象を回避するには、Ansibleの実行対象サーバ側で

sudo alternatives --set python /usr/bin/python2.7

としてあげれば動くようになった。

 

Ansible側で

--

ansible_python_interpreter="/usr/bin/python2.7"

--

とやっても動きました。


しかしどうも、なんだかなぁという感覚なので
今回は yum updateでアップデートしないようにした。

 

/etc/yum.conf の

---

releasever=latest 

---

---

releasever=2014.09

---

 

のようにしてあげれば、リポジトリ先を指定することができて
pythonが上がらないようにできる。

もうちょっと様子見てからどうするか考える。

 

イテレーションについて考える

最近うちの上司がイテレーションをなくしたいということを言っているので、
なくすことによってどんなメリットがあるのか、
そもそもなんでイテレーションが存在するのかについて考えてみることにする。

イテレーション

うちは2週間でイテレーションを区切っている。BtoBtoC。
最初に計画を立てて、物を作り、最終テストをしてリリースする。という流れ。

イテレーションとはつまり期限を決めることか?
違う、イテレーション=反復という意味らしい。

イテレーションがあることによるメリット

顧客と開発者、両方の目線で考えて見る。

顧客からの視点

  • ある程度、いつまでにできるかわかる
    これはどうだ?そもそも、今のうちのやり方がおかしいからこういう発想になるのではないか?

  • 計画、レビューのみ参加するってことができる
    がっつり入り込めない忙しい人には嬉しいのかもしれない。
    でもこれもちがう、ダメだと思う。

開発者の視点から

  • 開発リズムができる
    計画を全員で立てればなんとなく全体の状況が把握できる。終わったーっていう達成感とか。
    あとは、この日までにここまでやらなきゃいけないという気持ちにさせてくれる。

  • 進捗を管理できる
    もう完全に何のためだかわからなくなってきた。

イテレーションがないことによるメリット

顧客からの視点

  • できたものがすぐに提供できる
    イテレーションで区切ると最後のタイミングで一斉にリリースってなるけど、それがなくなる感じ。

開発者の視点から

  • 期限に間に合わせようと品質を犠牲にしなくなる
    やはりなんとか間に合わせようとしてしまうことはある。

  • 物を作る、以外の付加価値作業ができる ここまでにこれ終わらせなきゃ、ってならないと
    なんかこの作業いつもめんどくさいから自動化するかって発想になりそう。
    自分が作ったものの使われ方とか気になって、ログ解析とかしそう。
    いや、ちゃんと顧客にその価値を伝えてやらせて貰えばいいんだけど、

  • 進捗を管理しなくていい
    ちょっと言い過ぎかもしれないけど。
    でもさぼるやつでそう。俺みたいな。

現状を踏まえての結論

今のままではイテレーションをなくすことはできないんだと思う。
「相手にこの機能をここまでに出します」って約束しちゃってるから、
そうするとイテレーションなりなんなりで進捗の管理をせざるを得ない。

でも、イテレーションがある意味があまりない、かな。
「不完全」な状態でも一旦見せて、フィードバックを受けて成長させるということができていないから。
最初から特定の機能をどーんと作って、それで終わり。というものが多い。
ちょこっとはフィードバック受けているだろうけども、なんか違う気がする。
ただ2週間ごとにやることを決めているだけな感、それじゃそんなに意味なくない?

ぬあああああ、結論、「進捗管理」のためのイテレーションになっているのでなくすことはできない思います。

なくすためにはお客さん、さらにはその先の先まで思想の共有をして納得してもらって
もっと透明性のある情報共有を行なっていく必要がある。

とは言ってみたが

個人的になくすことは賛成。
進捗管理なんて、エンドユーザからしたら何の意味もない。
大型リリースとかならともかく、細かい改善やバグフィックスは許可なんて得ないでどんどん出していけばいい。 もっと意味のあることに時間を費やすべき。
自由にやらせた方がいいものができるんじゃない?(→これは妄想かもしれぬ) そのためにいろんな仕組みが必要になると思うけど、自分がこっちのほうがいいと思った以上それに向けて頑張る。