2012.01.26

fluentdのtailプラグインを使ってログを収集してみる


MongoDBのReplica SetsをUbuntuで試してみる | shinodogg.comで立てた
MongoDBにApacheのログを突っ込みたいわけなんですが、
何かとFluent(https://github.com/fluent/fluentd)がアツそうなので試してみます。
 
↓こちらのブログを参考にさせていただきました。
イベントログ収集ツール fluent を試しに使ってみる | 文字
 
■ fluentdのインストール
 
RubyGemsを使ったインストールをしてみます。
諸事情で自分のUbuntuはまっさらな状態になったので、Ruby入れて、RubyGems入れてから、

# apt-get install ruby1.8
# apt-get install rubygems

gem用にプロキシの設定を入れてやって

# vi ~/.gemrc
http_proxy: http://サーバー:ポート

gemでfluent入れようとしたら、、

# gem install fluentd
ERROR:  Could not find a valid gem 'fluentd' (>= 0) in any repository

またまたまた、、っていう。
 
アレやコレやしてたらmarshal data too shortとか言われて
なんだかなぁって思ってたら、そもそもRuby1.9じゃなきゃアレだとかみたいなのを目にしたので、
Ruby系はガッツリpurgeして↓を参考に、Ruby1.9.3のRubyGems1.8.11でやる事にしました。
[Debian(squeeze)][Ruby][fluent]Debian に fluent をインストール | 日記的な

# ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]
# gem -v
1.8.11

 
ようやく以下のようにインストールが完了しました。
んま、いろいろと依存してるんですねーって感じで。

# gem install fluentd
Fetching: msgpack-0.4.6.gem (100%)
Building native extensions.  This could take a while...
Fetching: json-1.6.5.gem (100%)
Building native extensions.  This could take a while...
Fetching: yajl-ruby-1.0.0.gem (100%)
Building native extensions.  This could take a while...
Fetching: iobuffer-1.0.0.gem (100%)
Building native extensions.  This could take a while...
Fetching: cool.io-1.1.0.gem (100%)
Building native extensions.  This could take a while...
Fetching: http_parser.rb-0.5.3.gem (100%)
Building native extensions.  This could take a while...
Fetching: fluentd-0.10.9.gem (100%)
Successfully installed msgpack-0.4.6
Successfully installed json-1.6.5
Successfully installed yajl-ruby-1.0.0
Successfully installed iobuffer-1.0.0
Successfully installed cool.io-1.1.0
Successfully installed http_parser.rb-0.5.3
Successfully installed fluentd-0.10.9
7 gems installed
Installing ri documentation for msgpack-0.4.6...
Installing ri documentation for json-1.6.5...
Installing ri documentation for yajl-ruby-1.0.0...
Installing ri documentation for iobuffer-1.0.0...
Installing ri documentation for cool.io-1.1.0...
Installing ri documentation for http_parser.rb-0.5.3...
Installing ri documentation for fluentd-0.10.9...
Installing RDoc documentation for msgpack-0.4.6...
Installing RDoc documentation for json-1.6.5...
Installing RDoc documentation for yajl-ruby-1.0.0...
Installing RDoc documentation for iobuffer-1.0.0...
Installing RDoc documentation for cool.io-1.1.0...
Installing RDoc documentation for http_parser.rb-0.5.3...
Installing RDoc documentation for fluentd-0.10.9...

 
fluentdがインストールできてきたところで、
何も考えずに叩いてやると↓のようになりました。んま、ダメポって感じっぽいですねw

# fluentd
2012-01-25 15:28:14 +0900: starting fluentd-0.10.9
2012-01-25 15:28:14 +0900: reading config file path="/etc/fluent/fluent.conf"
2012-01-25 15:28:14 +0900: unexpected error error="No such file or directory - /etc/fluent/fluent.conf"
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:228:in `read'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:228:in `read_config'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:77:in `block in start'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:170:in `call'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:170:in `main_process'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:145:in `block in supervise'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:144:in `fork'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:144:in `supervise'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/supervisor.rb:76:in `start'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/lib/fluent/command/fluentd.rb:128:in `<top (required)>'
  2012-01-25 15:28:14 +0900: /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
  2012-01-25 15:28:14 +0900: /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
  2012-01-25 15:28:14 +0900: /var/lib/gems/1.9.1/gems/fluentd-0.10.9/bin/fluentd:6:in `<top (required)>'
  2012-01-25 15:28:14 +0900: /usr/local/bin/fluentd:19:in `load'
  2012-01-25 15:28:14 +0900: /usr/local/bin/fluentd:19:in `<main>'
2012-01-25 15:28:14 +0900: process finished code=256
2012-01-25 15:28:14 +0900: process died within 1 second. exit.

 
中身を見ていくと、/etc/fluent/fluent.conf というファイルが無くて怒られているようです。
どうも fluentd –setup ディレクトリ って感じで、fluentのホームディレクトリ的なのが
ホゲホゲされそうなので↓のように叩いてみました。

# fluentd --setup /usr/local/fluent
Installed /usr/local/fluent/fluent.conf.
# ls -l | grep fluent
drwxr-xr-x 3 root root     4096 2012-01-25 15:31 fluent

 
fluent.confを開いてみると、結構ブワーっとイロイロ書いてありますが、
sourceが入力で、matchが出力って事みたいです。

# cat fluent.conf 

## built-in TCP input
## $ echo <json> | fluent-cat <tag>
<source>
  type forward
</source>

## built-in UNIX socket input
#<source>
#  type unix
#</source>

# HTTP input
# http://localhost:8888/<tag>?json=<json>
<source>
  type http
  port 8888
</source>

## File input
## read apache logs with tag=apache.access

 
 
■ ログ収集用の環境設定
 
同じホスト内になってしまうのであれですが、
2つのプロセスからログを集めてくることにしました。
 
せっかくRubyでアレやコレやしてみたのでSinatraを使ってみることにします。

# gem install sinatra
Fetching: rack-1.4.1.gem (100%)
Fetching: rack-protection-1.2.0.gem (100%)
Fetching: tilt-1.3.3.gem (100%)
Fetching: sinatra-1.3.2.gem (100%)
Successfully installed rack-1.4.1
Successfully installed rack-protection-1.2.0
Successfully installed tilt-1.3.3
Successfully installed sinatra-1.3.2
4 gems installed
Installing ri documentation for rack-1.4.1...
Installing ri documentation for rack-protection-1.2.0...
Installing ri documentation for tilt-1.3.3...
Installing ri documentation for sinatra-1.3.2...
Installing RDoc documentation for rack-1.4.1...
Installing RDoc documentation for rack-protection-1.2.0...
Installing RDoc documentation for tilt-1.3.3...
Installing RDoc documentation for sinatra-1.3.2...

 
・1つめのアプリ(app01.rb)。 # 何のへんてつもないw

# cat app01.rb
require 'sinatra'
require 'logger'
logger = Logger.new('sinatra01.log')

get '/' do
  logger.info "log from 01"
  'Hello app01'
end

 
・2つめのアプリ(app02.rb)。#上のコピペw

# cat app02.rb
require 'sinatra'
require 'logger'
logger = Logger.new('sinatra02.log')

get '/' do
  logger.info "log from 02"
  'Hello app02'
end

 
起動します。ポートは4567と4568にしてみました。

# ruby -rubygems app01.rb -p 4567
[2012-01-26 11:25:30] INFO  WEBrick 1.3.1
[2012-01-26 11:25:30] INFO  ruby 1.9.3 (2011-10-30) [x86_64-linux]
== Sinatra/1.3.2 has taken the stage on 4567 for development with backup from WEBrick
[2012-01-26 11:25:30] INFO  WEBrick::HTTPServer#start: pid=4135 port=4567
# ruby -rubygems app02.rb -p 4568
[2012-01-26 12:20:31] INFO  WEBrick 1.3.1
[2012-01-26 12:20:31] INFO  ruby 1.9.3 (2011-10-30) [x86_64-linux]
== Sinatra/1.3.2 has taken the stage on 4568 for development with backup from WEBrick
[2012-01-26 12:20:31] INFO  WEBrick::HTTPServer#start: pid=5838 port=4568

 
上記のプロセスたちから吐かれるsinatra01.logとsinatra02.logをリモート的に集めて、
一つのログファイルに出力したいです、と。
ってことで、以下3つの設定ファイルを用意してfluentを起動します。
 
・app01.rbのログをtailで持ってくる
(pos_fileっていうのはFluentがどこまでファイル読んだか記録しておく用途)

$ cat sinatra01.conf
<source>
  type tail
  format /^(?<SeverityID>[^ ]), \[(?<time>[^ ]*) (?<pid>[^ ]*)\]  (?<SeverityLabel>[^ ]*) -- : (?<message>.*)$/
  time_format %Y-%m-%dT%H:%M:%S
  path /usr/local/sinatra_test/sinatra01.log
  tag sinatra
  pos_file /usr/local/fluent/tmp/sinatra01.log.pos
</source>

<match sinatra>
  type tcp
  host localhost
</match>

 
・app02.rbのログをtailで持ってくる

$ cat sinatra02.conf
<source>
  type tail
  format /^(?<SeverityID>[^ ]), \[(?<time>[^ ]*) (?<pid>[^ ]*)\]  (?<SeverityLabel>[^ ]*) -- : (?<message>.*)$/
  time_format %Y-%m-%dT%H:%M:%S
  path /usr/local/sinatra_test/sinatra02.log
  tag sinatra
  pos_file /usr/local/fluent/tmp/sinatra02.log.pos
</source>

<match sinatra>
  type tcp
  host localhost
</match>

 
・上記で集めたログを一ヶ所に吐き出す

$ cat log.conf
<source>
  type tcp
</source>

<match sinatra>
  type file
  path /usr/local/fluent/sinatra.log
</match>

 
※ tailのインプット(sourceタグ)の設定にちょっと手間取りました。
Fluentは↓のようにapacheのaccess_logとsyslogをformatに指定することが出来るのですが、
http://fluentd.org/doc/plugin.html#tail
Sinatraでloggerで吐いたログは自分でレイアウトをFluentに教えてあげる必要があります。
#そうするとFluentがよしなにJSONにしてくれるわけです。
 
やり方的には、
・formatのところをログレイアウトに沿って正規表現で指定して、
・日付データ(timeで指定したとこ)はformat_timeのところで指定する
感じになります。
 
日付データに関して、Sinatraからloggerで吐いたログは
↓のようになっていて、

2012-01-25T19:47:57.799700

こいつは、fluentのparser.rbで↓のように扱われるようなのですが、

time = Time.strptime(value, @time_format).to_i

そうした場合に、マイクロ秒を%6Nとかで指定すると↓のように怒られてしまいます。

irb(main):030:0> Time.strptime('2001-02-03T04:05:06.799324', '%Y-%m-%dT%H:%M:%S.%6N')
ArgumentError: invalid strptime format - `%Y-%m-%dT%H:%M:%S.%6N'

 
ってことで@yssk22がプラグイン書いてくれるそうなのですがw
そんなに困ってないので、とりあえず秒まで指定おくか的な感じにしています。
 
ってことで、それぞれの設定ファイルを指定してFluentのプロセスを起動させます。
 
・app01.rb向け

/usr/local/fluent# fluentd -c sinatra01.conf
2012-01-26 12:57:30 +0900: starting fluentd-0.10.9
2012-01-26 12:57:30 +0900: reading config file path="sinatra01.conf"
2012-01-26 12:57:30 +0900: adding source type="tail"
2012-01-26 12:57:30 +0900: adding match pattern="sinatra" type="tcp"

 
・app02.rb向け

/usr/local/fluent# fluentd -c sinatra02.conf
2012-01-26 12:57:34 +0900: starting fluentd-0.10.9
2012-01-26 12:57:34 +0900: reading config file path="sinatra02.conf"
2012-01-26 12:57:34 +0900: adding source type="tail"
2012-01-26 12:57:34 +0900: adding match pattern="sinatra" type="tcp"

 
・ログを一ヶ所に吐き出すヤツ

# fluentd -c log.conf
2012-01-26 12:57:36 +0900: starting fluentd-0.10.9
2012-01-26 12:57:36 +0900: reading config file path="log.conf"
2012-01-26 12:57:36 +0900: adding source type="tcp"
2012-01-26 12:57:36 +0900: adding match pattern="sinatra" type="file"
2012-01-26 12:57:36 +0900: listening fluent socket on 0.0.0.0:24224

 
 
■ ログ収集できるか確認
 
ログがちゃんと集まるか確認してみます。
 
Sinatraアプリのhttp://localhost:4567/とhttp://localhost:4568/をズカズカ叩いた後に、
上記のlog.confで指定した /usr/local/fluent/sinatra.log にアクセスすると、
sinatra.log.20120126.b4b765625c2912236 っていうファイルが出来ていて、
開いてみると↓のようにイイ感じです。

$ cat sinatra.log.20120126.b4b765625c2912236
2012-01-26T13:00:32+09:00	sinatra	{"SeverityID":"I","pid":"#4135","SeverityLabel":"INFO","message":"log from 01"}
2012-01-26T13:00:34+09:00	sinatra	{"SeverityID":"I","pid":"#5838","SeverityLabel":"INFO","message":"log from 02"}
2012-01-26T13:00:36+09:00	sinatra	{"SeverityID":"I","pid":"#5838","SeverityLabel":"INFO","message":"log from 02"}
2012-01-26T13:00:40+09:00	sinatra	{"SeverityID":"I","pid":"#4135","SeverityLabel":"INFO","message":"log from 01"}
2012-01-26T13:01:19+09:00	sinatra	{"SeverityID":"I","pid":"#4135","SeverityLabel":"INFO","message":"log from 01"}
2012-01-26T13:01:22+09:00	sinatra	{"SeverityID":"I","pid":"#4135","SeverityLabel":"INFO","message":"log from 01"}
2012-01-26T13:00:38+09:00	sinatra	{"SeverityID":"I","pid":"#5838","SeverityLabel":"INFO","message":"log from 02"}
2012-01-26T13:01:21+09:00	sinatra	{"SeverityID":"I","pid":"#5838","SeverityLabel":"INFO","message":"log from 02"}

 

ってことで、scpとかしないで一ヶ所にログを集めることが出来そうです。
 
あとは、pos_fileを指定してもログファイルがローテーションした時にinode番号が変わってー
とかってなった時は、プロセスが落ちたりすると、どないしよ?みたいになりそうで、
その辺のリカバリとか考えなきゃなーって気がする今日この頃です。
 
次は、こいつをMongoDBに突っ込んでGoogle Web Tool Kitとか使って、
イカしたグラフ的なUIとかでキャッキャしたいなー
 

入門 ウェブ分析論~アクセス解析を成果につなげるための新・基礎知識~
小川 卓
ソフトバンククリエイティブ
売り上げランキング: 139321

2012.01.25

MongoDBでUnclean shutdownの際にmongod.lockを消す


昨日何も考えず、VirtualBox上のUbuntu(ゲスト)でMongoDB動かしたまま、
ホストのWindowsをシャットダウンして帰ったわけなんですが、
今朝起動したところ↓のようなエラーが出て起動できませんでした。

# /usr/local/mongodb/bin/mongod --replSet replica --port 27017 --dbpath /data/replica1 --rest --nojournal
Wed Jan 25 10:01:36 [initandlisten] MongoDB starting : pid=2131 port=27017 dbpath=/data/replica1 64-bit host=ubnt
Wed Jan 25 10:01:36 [initandlisten] db version v2.0.2, pdfile version 4.5
Wed Jan 25 10:01:36 [initandlisten] git version: 514b122d308928517f5841888ceaa4246a7f18e3
Wed Jan 25 10:01:36 [initandlisten] build info: Linux bs-linux64.10gen.cc 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41
Wed Jan 25 10:01:36 [initandlisten] options: { dbpath: "/data/replica1", nojournal: true, port: 27017, replSet: "replica", rest: true }
**************
Unclean shutdown detected.
Please visit http://dochub.mongodb.org/core/repair for recovery instructions.
*************
Wed Jan 25 10:01:36 [initandlisten] exception in initAndListen: 12596 old lock file, terminating
Wed Jan 25 10:01:36 dbexit:
Wed Jan 25 10:01:36 [initandlisten] shutdown: going to close listening sockets...
Wed Jan 25 10:01:36 [initandlisten] shutdown: going to flush diaglog...
Wed Jan 25 10:01:36 [initandlisten] shutdown: going to close sockets...
Wed Jan 25 10:01:36 [initandlisten] shutdown: waiting for fs preallocator...
Wed Jan 25 10:01:36 [initandlisten] shutdown: closing all files...
Wed Jan 25 10:01:36 [initandlisten] closeAllFiles() finished
Wed Jan 25 10:01:36 dbexit: really exiting now

 
MongoDBのドキュメントのページのDurability and Repairの章をみると、
コマンドラインで mongod –repair するか、
mongoシェルで db.repairDatabase(); ってするかみたいです。
 
mongod –repairしてみると↓のようにクリアされたようです。

# ./mongod --repair
Wed Jan 25 10:47:50 [initandlisten] MongoDB starting : pid=2801 port=27017 dbpath=/data/db/ 64-bit host=ubnt
Wed Jan 25 10:47:50 [initandlisten] db version v2.0.2, pdfile version 4.5
Wed Jan 25 10:47:50 [initandlisten] git version: 514b122d308928517f5841888ceaa4246a7f18e3
Wed Jan 25 10:47:50 [initandlisten] build info: Linux bs-linux64.10gen.cc 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41
Wed Jan 25 10:47:50 [initandlisten] options: { repair: true }
略
Wed Jan 25 10:48:00 [initandlisten] closeAllFiles() finished
Wed Jan 25 10:48:00 [initandlisten] journalCleanup...
Wed Jan 25 10:48:00 [initandlisten] removeJournalFiles
Wed Jan 25 10:48:00 [initandlisten] shutdown: removing fs lock...
Wed Jan 25 10:48:00 dbexit: really exiting now

 
で、起動しようとしたら、それでも同じエラーが出てるがや。。。

Wed Jan 25 10:52:57 [initandlisten] exception in initAndListen: 12596 old lock file, terminating

 
↓によると、mongod.lockっていうデータディレクトリ直下にあるロック用の
ファイルを消してやらないとダメみたいです。
[MongoDB]MongoDBの新機能:ジャーナリングについて詳しく| @doryokujin ブログ:勉強会はうちに帰っても勉強会
ということで。

# rm /data/replica1/mongod.lock
# rm /data/replica2/mongod.lock
# rm /data/replica3/mongod.lock

 
一応、もう一発mongod –repairカマしてから、
それぞれ↓で起動してめでたしめでたし。

/usr/local/mongodb/bin/mongod --replSet replica --port 27017 --dbpath /data/replica1 --rest --nojournal
/usr/local/mongodb/bin/mongod --replSet replica --port 27018 --dbpath /data/replica2 --rest --nojournal
/usr/local/mongodb/bin/mongod --replSet replica --port 27019 --dbpath /data/replica3 --rest --nojournal

 
クエリ的にも昨日入れたデータが取れて

/usr/local/mongodb/bin# ./mongo localhost:27018
MongoDB shell version: 2.0.2
connecting to: localhost:27018/test
SECONDARY> rs.slaveOk();
SECONDARY> db.posts.find( { "comments.author" : "jim" } )
{ "_id" : ObjectId("4f1e79261c0db27b00f1954c"), "author" : "joe", "created" : ISODate("2009-03-27T15:00:00Z"), "title" : "Yet another blog post", "text" : "Here is the text...", "tags" : [ "example", "joe" ], "comments" : [ 	{ 	"author" : "jim", 	"comment" : "I disagree" }, 	{ 	"author" : "nancy", 	"comment" : "Good post" } ] }

 
画面的にもOKです。

 

Scaling MongoDB
Scaling MongoDB
posted with amazlet at 12.01.25
Kristina Chodorow
Oreilly & Associates Inc
売り上げランキング: 53297

2012.01.24

MongoDBのReplica SetsをUbuntuで試してみる


ログ溜め込んで解析する基盤としてMongoDBイイんじゃない?ってのは前からよく聞く話でしたが、
こないだのMongoTokyo2012(秀逸なまとめ)みてたら、みんなやってんだなぁと。
以前WindowsでSpringDataからいじった事はあったのですが、(MongoDBをSpring Dataからホゲホゲしてみる | shinodogg.com)
運用考えた構成で試してみようかな的な感じで。
 
■ MongoDBのインストールと動作確認
 
Webサイト(http://www.mongodb.org/downloads)からLinux 64-bitのURLをコピって
wgetでバイナリをダウンロード

# cd /usr/local/src
# export http_proxy=ごにょごにょ
# wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.0.2.tgz
略

Saving to: `mongodb-linux-x86_64-2.0.2.tgz'

100%[======================================>] 38,350,811  6.81M/s   in 5.2s    

2012-01-24 10:18:08 (7.10 MB/s) - `mongodb-linux-x86_64-2.0.2.tgz' saved [38350811/38350811]

 
解凍すると↓こんな感じ。ダンプとかリストアとかtopとか、ほうほうって感じですね。

# tar xvf mongodb-linux-x86_64-2.0.2.tgz
mongodb-linux-x86_64-2.0.2/
mongodb-linux-x86_64-2.0.2/THIRD-PARTY-NOTICES
mongodb-linux-x86_64-2.0.2/GNU-AGPL-3.0
mongodb-linux-x86_64-2.0.2/README
mongodb-linux-x86_64-2.0.2/bin/
mongodb-linux-x86_64-2.0.2/bin/mongo
mongodb-linux-x86_64-2.0.2/bin/mongotop
mongodb-linux-x86_64-2.0.2/bin/mongos
mongodb-linux-x86_64-2.0.2/bin/mongodump
mongodb-linux-x86_64-2.0.2/bin/mongostat
mongodb-linux-x86_64-2.0.2/bin/mongofiles
mongodb-linux-x86_64-2.0.2/bin/mongoimport
mongodb-linux-x86_64-2.0.2/bin/mongosniff
mongodb-linux-x86_64-2.0.2/bin/mongorestore
mongodb-linux-x86_64-2.0.2/bin/mongod
mongodb-linux-x86_64-2.0.2/bin/bsondump
mongodb-linux-x86_64-2.0.2/bin/mongoexport

てか、configureとかmakeとか要らんのねーって。この辺も楽チンなとこでしょうか。
 
/usr/local/mongodbって感じにしておきたいので、ディレクトリ移動して
シンボリックリンク貼っておきやす。

# mv mongodb-linux-x86_64-2.0.2 /usr/local
# cd /usr/local
# ln -s mongodb-linux-x86_64-2.0.2 mongodb
# ls -l | grep mongodb
lrwxrwxrwx 1 root root   26 2012-01-24 10:24 mongodb -> mongodb-linux-x86_64-2.0.2
drwxr-xr-x 3 root root 4096 2011-12-15 06:26 mongodb-linux-x86_64-2.0.2

 
調子に乗ってそのまま起動したらなんか怒られました。
所定のディレクトリがねぇだろうがゴルァって話みたいです。

# /usr/local/mongodb/bin/mongod
/usr/local/mongodb/bin/mongod --help for help and startup options
Tue Jan 24 10:28:42 [initandlisten] MongoDB starting : pid=3275 port=27017 dbpath=/data/db/ 64-bit host=VirtualBoxUbuntu
Tue Jan 24 10:28:42 [initandlisten] db version v2.0.2, pdfile version 4.5
Tue Jan 24 10:28:42 [initandlisten] git version: 514b122d308928517f5841888ceaa4246a7f18e3
Tue Jan 24 10:28:42 [initandlisten] build info: Linux bs-linux64.10gen.cc 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41
Tue Jan 24 10:28:42 [initandlisten] options: {}
Tue Jan 24 10:28:42 [initandlisten] exception in initAndListen: 10296 dbpath (/data/db/) does not exist, terminating
Tue Jan 24 10:28:42 dbexit:
Tue Jan 24 10:28:42 [initandlisten] shutdown: going to close listening sockets...
Tue Jan 24 10:28:42 [initandlisten] shutdown: going to flush diaglog...
Tue Jan 24 10:28:42 [initandlisten] shutdown: going to close sockets...
Tue Jan 24 10:28:42 [initandlisten] shutdown: waiting for fs preallocator...
Tue Jan 24 10:28:42 [initandlisten] shutdown: lock for final commit...
Tue Jan 24 10:28:42 [initandlisten] shutdown: final commit...
Tue Jan 24 10:28:42 [initandlisten] shutdown: closing all files...
Tue Jan 24 10:28:42 [initandlisten] closeAllFiles() finished
Tue Jan 24 10:28:42 dbexit: really exiting now
# echo $?
100

 
データを格納しておくようのディレクトリが必要なのねって事で作って叩きます。

# mkdir -p /data/db
# /usr/local/mongodb/bin/mongod
/usr/local/mongodb/bin/mongod --help for help and startup options
Tue Jan 24 10:30:37 [initandlisten] MongoDB starting : pid=3281 port=27017 dbpath=/data/db/ 64-bit host=ほげほげ
Tue Jan 24 10:30:37 [initandlisten] db version v2.0.2, pdfile version 4.5
Tue Jan 24 10:30:37 [initandlisten] git version: 514b122d308928517f5841888ceaa4246a7f18e3
Tue Jan 24 10:30:37 [initandlisten] build info: Linux bs-linux64.10gen.cc 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41
Tue Jan 24 10:30:37 [initandlisten] options: {}
Tue Jan 24 10:30:38 [initandlisten] journal dir=/data/db/journal
Tue Jan 24 10:30:38 [initandlisten] recover : no journal files present, no recovery needed
Tue Jan 24 10:30:38 [initandlisten] preallocateIsFaster=true 14.9
Tue Jan 24 10:30:39 [initandlisten] preallocateIsFaster=true 15.24
Tue Jan 24 10:30:41 [initandlisten] preallocateIsFaster=true 15.32
Tue Jan 24 10:30:41 [initandlisten] preallocateIsFaster check took 3.469 secs
Tue Jan 24 10:30:41 [initandlisten] preallocating a journal file /data/db/journal/prealloc.0
		503316480/1073741824	46%
		954204160/1073741824	88%
Tue Jan 24 10:30:50 [initandlisten] preallocating a journal file /data/db/journal/prealloc.1
		377487360/1073741824	35%
		597688320/1073741824	55%
Tue Jan 24 10:30:59 [initandlisten] File I/O errno:2 No such file or directory
preallocating a journal file /data/db/journal/prealloc.2
Tue Jan 24 10:30:59 [initandlisten] File I/O errno:2 No such file or directory
waiting for connections on port 27017
Tue Jan 24 10:30:59 [websvr] admin web console waiting for connections on port 28017

 
それっぽく上がったみたいなのでバックグラウンドにしておきます。
# /etc/init.dがどうのとか、そういうのは置いておいて。。

^Z
zsh: suspended  /usr/local/mongodb/bin/mongod
# bg
[1]  + continued  /usr/local/mongodb/bin/mongod

 
データを入れたり出したりしてみます。
MongoDBのシェルはbin/mongoなので↓のようにシェルを起動します。

# ./mongo
MongoDB shell version: 2.0.2
connecting to: test
Tue Jan 24 11:44:06 [initandlisten] connection accepted from 127.0.0.1:52563 #1
>

 
↓を参考にしてドキュメントをインサートしようとしたら、、

http://www.mongodb.org/pages/viewpage.action?pageId=7209154

diskの残りがねーよ、と。。

Tue Jan 24 12:32:15 [FileAllocator]     will try again in 10 seconds
Tue Jan 24 12:32:25 [FileAllocator] allocating new datafile /data/db/test.ns, filling with zeroes...
Tue Jan 24 12:32:25 [FileAllocator] creating directory /data/db/_tmp
Tue Jan 24 12:32:25 [FileAllocator] error failed to allocate new file: /data/db/test.ns size: 16777216 errno:28 No space left on device

 
またまた、とか思ってみてみたら↓そんなに食うんですかいっていう…

/data/db/journal# ls -l
total 1754916
-rw------- 1 root root 1073741824 2012-01-24 10:30 j._0
-rw------- 1 root root  721301504 2012-01-24 10:30 prealloc.1
-rw------- 1 root root    1888256 2012-01-24 10:30 prealloc.2
/data/db/journal# du -skh
1.7G	.

 
とりあえずjounal配下を全部消して、

/data/db/journal# rm -r *
/data/db/journal# ls -l
total 0

プロセスkillして、、

# kill 3281
VirtualBoxUbuntu# Tue Jan 24 12:35:05 got kill or ctrl c or hup signal 15 (Terminated), will terminate after current cmd ends
Tue Jan 24 12:35:05 [interruptThread] now exiting
Tue Jan 24 12:35:05 dbexit:
Tue Jan 24 12:35:05 [interruptThread] shutdown: going to close listening sockets...
Tue Jan 24 12:35:05 [interruptThread] closing listening socket: 6
Tue Jan 24 12:35:05 [interruptThread] closing listening socket: 7
略
Tue Jan 24 12:35:05 [interruptThread] journalCleanup...
Tue Jan 24 12:35:05 [interruptThread] removeJournalFiles
Tue Jan 24 12:35:05 [interruptThread] shutdown: removing fs lock...
Tue Jan 24 12:35:05 dbexit: really exiting now

[1]  + exit 12    /usr/local/mongodb/bin/mongod

 
ジャーナル無しで上げ直します

# /usr/local/mongodb/bin/mongod --nojournal
Tue Jan 24 12:37:59 [initandlisten] MongoDB starting : pid=3580 port=27017 dbpath=/data/db/ 64-bit host=VirtualBoxUbuntu
Tue Jan 24 12:37:59 [initandlisten] db version v2.0.2, pdfile version 4.5
Tue Jan 24 12:37:59 [initandlisten] git version: 514b122d308928517f5841888ceaa4246a7f18e3
Tue Jan 24 12:37:59 [initandlisten] build info: Linux bs-linux64.10gen.cc 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41
Tue Jan 24 12:37:59 [initandlisten] options: { nojournal: true }

 
気を取り直して、ドキュメントを突っ込んでみます。

/usr/local/mongodb/bin# ./mongo
MongoDB shell version: 2.0.2
connecting to: test
> doc = { author: 'joe',
...   created : new Date('03/28/2009'),
...   title : 'Yet another blog post',
...   text : 'Here is the text...',
...   tags : [ 'example', 'joe' ],
...   comments : [ { author: 'jim', comment: 'I disagree' },
...                { author: 'nancy', comment: 'Good post' }
...   ]
... }
{
	"author" : "joe",
	"created" : ISODate("2009-03-27T15:00:00Z"),
	"title" : "Yet another blog post",
	"text" : "Here is the text...",
	"tags" : [
		"example",
		"joe"
	],
	"comments" : [
		{
			"author" : "jim",
			"comment" : "I disagree"
		},
		{
			"author" : "nancy",
			"comment" : "Good post"
		}
	]
}
> db.posts.insert(doc);

 
コメントのauthorを指定して検索も出来ました。

> db.posts.find( { "comments.author" : "jim" } )
{ "_id" : ObjectId("4f1e27f47d7053b05fb67e39"), "author" : "joe", "created" : ISODate("2009-03-27T15:00:00Z"), "title" : "Yet another blog post", "text" : "Here is the text...", "tags" : [ "example", "joe" ], "comments" : [ 	{ 	"author" : "jim", 	"comment" : "I disagree" }, 	{ 	"author" : "nancy", 	"comment" : "Good post" } ] }

 
 
■ Replica Setsで冗長性を確保する
 
Shardingとかもあれですが、とりあえず冗長性確保したいのと、
Master/Slaveじゃなくて自動フェールオーバーな仕掛けを持った
Replica Setsってのがあるので、ソレを試してみたいな、と。
 
↓の記事がとてもよくまとまっていて分かりやすかったので参考にさせていただきました。
MongoDBのReplica Setsについての概要 | ryopekoの日記
 
それぞれのデータ用のディレクトリ作ります。

mkdir -p /data/replica1
mkdir -p /data/replica2
mkdir -p /data/replica3

 
それぞれをnojournalで立ち上げます。restオプションはブラウザで確認できるようにする
オプションらしいです。
今回はそれぞれがどんなログ出すのか後からみてみたいので、
コンソールのタブを3つ立ち上げてそれぞれでやってみます。

タブ1:
/usr/local/mongodb/bin/mongod \
--replSet replica --port 27017 --dbpath /data/replica1 --rest --nojournal

タブ2:
/usr/local/mongodb/bin/mongod \
--replSet replica --port 27018 --dbpath /data/replica2 --rest --nojournal

タブ3:
/usr/local/mongodb/bin/mongod \
--replSet replica --port 27019 --dbpath /data/replica3 --rest --nojournal

 
どこのノードでも↓のように設定がちゃんとされてないんじゃね?系のログが出ています。

Tue Jan 24 13:48:16 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Tue Jan 24 13:48:16 [rsStart] replSet info you may need to run replSetInitiate -- rs.initiate() in the shell -- if that is not already done
Tue Jan 24 13:48:26 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)

 
↓にアクセスするとHadoop並みのイカした画面が出てきます。
localhost:28017 localhost:28018 localhost:28019

 
続いてレプリカの設定を入れます。

/usr/local/mongodb/bin# ./mongo localhost:27017
MongoDB shell version: 2.0.2
connecting to: localhost:27017/test
> conf = {_id: 'replica', members: [
...    {_id: 0, host: 'localhost:27017'},
...    {_id: 1, host: 'localhost:27018'},
...    {_id: 2, host: 'localhost:27019'}]
... }
{
	"_id" : "replica",
	"members" : [
		{
			"_id" : 0,
			"host" : "localhost:27017"
		},
		{
			"_id" : 1,
			"host" : "localhost:27018"
		},
		{
			"_id" : 2,
			"host" : "localhost:27019"
		}
	]
}
> rs.initiate(conf)
{
	"info" : "Config now saved locally.  Should come online in about a minute.",
	"ok" : 1
}

 
ステータスを見てみるとまだStartup的な。

> rs.status()
{
	"set" : "replica",
	"date" : ISODate("2012-01-24T09:20:22Z"),
	"myState" : 2,
	"members" : [
		{
			"_id" : 0,
			"name" : "localhost:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"optime" : {
				"t" : 1327396814000,
				"i" : 1
			},
			"optimeDate" : ISODate("2012-01-24T09:20:14Z"),
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "localhost:27018",
			"health" : 1,
			"state" : 5,
			"stateStr" : "STARTUP2",
			"uptime" : 8,
			"optime" : {
				"t" : 0,
				"i" : 0
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2012-01-24T09:20:22Z"),
			"pingMs" : 18677460,
			"errmsg" : "initial sync need a member to be primary or secondary to do our initial sync"
		},
		{
			"_id" : 2,
			"name" : "localhost:27019",
			"health" : 1,
			"state" : 5,
			"stateStr" : "STARTUP2",
			"uptime" : 8,
			"optime" : {
				"t" : 0,
				"i" : 0
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2012-01-24T09:20:22Z"),
			"pingMs" : 18661632,
			"errmsg" : "initial sync need a member to be primary or secondary to do our initial sync"
		}
	],
	"ok" : 1
}
SECONDARY>

 
もう一回叩いてやると、狙った感じになっています。

SECONDARY> rs.status()
{
	"set" : "replica",
	"date" : ISODate("2012-01-24T09:22:16Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "localhost:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"optime" : {
				"t" : 1327396814000,
				"i" : 1
			},
			"optimeDate" : ISODate("2012-01-24T09:20:14Z"),
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "localhost:27018",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 122,
			"optime" : {
				"t" : 1327396814000,
				"i" : 1
			},
			"optimeDate" : ISODate("2012-01-24T09:20:14Z"),
			"lastHeartbeat" : ISODate("2012-01-24T09:22:14Z"),
			"pingMs" : 68
		},
		{
			"_id" : 2,
			"name" : "localhost:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 122,
			"optime" : {
				"t" : 1327396814000,
				"i" : 1
			},
			"optimeDate" : ISODate("2012-01-24T09:20:14Z"),
			"lastHeartbeat" : ISODate("2012-01-24T09:22:14Z"),
			"pingMs" : 68
		}
	],
	"ok" : 1
}
PRIMARY>

 
プライマリにデータを入れて、

PRIMARY> doc = { author: 'joe',
...   created : new Date('03/28/2009'),
...   title : 'Yet another blog post',
...   text : 'Here is the text...',
...   tags : [ 'example', 'joe' ],
...   comments : [ { author: 'jim', comment: 'I disagree' },
...                { author: 'nancy', comment: 'Good post' }
...   ]
... }
{
	"author" : "joe",
	"created" : ISODate("2009-03-27T15:00:00Z"),
	"title" : "Yet another blog post",
	"text" : "Here is the text...",
	"tags" : [
		"example",
		"joe"
	],
	"comments" : [
		{
			"author" : "jim",
			"comment" : "I disagree"
		},
		{
			"author" : "nancy",
			"comment" : "Good post"
		}
	]
}
PRIMARY> db.posts.insert(doc);

 
セカンダリからデータを取得してみます。slaveOkってのをやってやらないと
error: { “$err” : “not master and slaveok=false”, “code” : 13435 }
って出て、データが取得できませんでした。

SECONDARY> rs.slaveOk();
not master and slaveok=false
SECONDARY> db.posts.find( { "comments.author" : "jim" } )
{ "_id" : ObjectId("4f1e79261c0db27b00f1954c"), "author" : "joe", "created" : ISODate("2009-03-27T15:00:00Z"), "title" : "Yet another blog post", "text" : "Here is the text...", "tags" : [ "example", "joe" ], "comments" : [ 	{ 	"author" : "jim", 	"comment" : "I disagree" }, 	{ 	"author" : "nancy", 	"comment" : "Good post" } ] }

 
ちなみにrsはhelpのメソッドもあって↓こんな感じに使うんだぜ的な

SECONDARY> rs.help();
	rs.status()                     { replSetGetStatus : 1 } checks repl set status
	rs.initiate()                   { replSetInitiate : null } initiates set with default settings
	rs.initiate(cfg)                { replSetInitiate : cfg } initiates set with configuration cfg
	rs.conf()                       get the current configuration object from local.system.replset
	rs.reconfig(cfg)                updates the configuration of a running replica set with cfg (disconnects)
	rs.add(hostportstr)             add a new member to the set with default attributes (disconnects)
	rs.add(membercfgobj)            add a new member to the set with extra attributes (disconnects)
	rs.addArb(hostportstr)          add a new member which is arbiterOnly:true (disconnects)
	rs.stepDown([secs])             step down as primary (momentarily) (disconnects)
	rs.freeze(secs)                 make a node ineligible to become primary for the time specified
	rs.remove(hostportstr)          remove a host from the replica set (disconnects)
	rs.slaveOk()                    shorthand for db.getMongo().setSlaveOk()

	db.isMaster()                   check who is primary

	reconfiguration helpers disconnect from the database so the shell will display
	an error, even if the command succeeds.
	see also http://<mongod_host>:28017/_replSet for additional diagnostic info

 
↓Web画面から見てもフムフムって感じになっています。

 
これでプライマリ(27017)落としてセカンダリ(27018か27019)がプライマリになればOKです。
さっそくやってみると、、
 
・27017のログ

Tue Jan 24 19:02:36 [interruptThread] closeAllFiles() finished
Tue Jan 24 19:02:36 [interruptThread] shutdown: removing fs lock...
Tue Jan 24 19:02:36 dbexit: really exiting now

 
・27018のログ

Tue Jan 24 19:02:36 [rsSync] replSet syncThread: 10278 dbclient error communicating with server: localhost:27017
Tue Jan 24 19:02:37 [rsHealthPoll] DBClientCursor::init call() failed
Tue Jan 24 19:02:37 [rsHealthPoll] replSet info localhost:27017 is down (or slow to respond): DBClientBase::findN: transport error: localhost:27017 query: { replSetHeartbeat: "replica", v: 1, pv: 1, checkEmpty: false, from: "localhost:27018" }
Tue Jan 24 19:02:37 [rsHealthPoll] replSet member localhost:27017 is now in state DOWN
Tue Jan 24 19:02:37 [rsMgr] replSet info electSelf 1
Tue Jan 24 19:02:37 [rsMgr] replSet PRIMARY

 
・27019のログ

Tue Jan 24 19:02:36 [rsHealthPoll] replSet info localhost:27017 is down (or slow to respond): DBClientBase::findN: transport error: localhost:27017 query: { replSetHeartbeat: "replica", v: 1, pv: 1, checkEmpty: false, from: "localhost:27019" }
Tue Jan 24 19:02:36 [rsHealthPoll] replSet member localhost:27017 is now in state DOWN
Tue Jan 24 19:02:36 [rsMgr] not electing self, localhost:27018 would veto
Tue Jan 24 19:02:37 [conn172] replSet info voting yea for localhost:27018 (1)
Tue Jan 24 19:02:38 [rsHealthPoll] replSet member localhost:27018 is now in state PRIMARY

 
画面からみても↓のように狙った通り。お利口さんです。

 
27018(プライマリ)にデータを入れて、27019(セカンダリ)からデータを取得してみます。

# ./mongo localhost:27018
MongoDB shell version: 2.0.2
connecting to: localhost:27018/test
PRIMARY> db.things.save({"name":"Shinohara","age":"32"});

↓無事取れました。

# ./mongo localhost:27019
MongoDB shell version: 2.0.2
connecting to: localhost:27019/test
SECONDARY> db.things.find();
error: { "$err" : "not master and slaveok=false", "code" : 13435 }
SECONDARY> rs.slaveOk();
not master and slaveok=false
SECONDARY> db.things.find();
{ "_id" : ObjectId("4f1e837e59ff27bd08cf3187"), "name" : "Shinohara", "age" : "32" }

 
最後は落とした27017を戻してやって画面から確認したら
セカンダリとしてちゃんと戻ってくれました↓

  

確かにお手軽な感じなんだなぁってのは実際に手を動かしてみるとよくわかりますね。
 

NoSQLデータベースファーストガイド
佐々木 達也
秀和システム
売り上げランキング: 182936

2012.01.23

ザ・ラストバンカー 西川善文回顧録


ザ・ラストバンカー 西川善文回顧録
西川 善文
講談社
売り上げランキング: 714

ザ・ラストバンカーを読みました。
 
コレは激アツ。
自分の中では一年に数冊出会えるかくらいグッときた本。
 
いろんな歪みのあった激動の日本経済のド真ん中を、
自分の信念曲げずに使命感を持って駆け抜けた苦労人の回顧録。
 
この本は、表紙の写真の表情も何とも言えない凄みがあるし、
“逃げたらあかん!”とか、”不良債権と寝た男”とか、帯も煽りまくりなわけ
なんですが、中身はもっと俄然アツいぜって感じで。
 
自分は銀行員でも何でもないですが、もしそうだったら、
“日本の銀行員ナメんなよ”くらいな感じで奮い立っちゃうのかもなぁとか。
 
自分は2012年1月現在で、32歳なのですが、自分が生まれる前の、
高度経済成長って順風満帆だったのか的な印象だったのですが、
んまぁ、それはそれでイロイロあったのねぇと。
学校で習った社会の授業よりも、こっちの方が俄然グイグイ引き込まれる感じでした。
 
金融とか、一般庶民からすると割りとベールに包まれたようなところでも、
ゴールドマン・サックスからの融資の話とか、”結局は人と人”みたいなところが
随所に溢れてて、それでイイんだよなーと、スッキリしました。
 
郵政の件は志半ばで無念っていうか、チクショー!ふざけんな!!って感じですが、
物事を進めていく上で、ズル賢い政治力とか、そういう能力とかそういう側近的な人が
いるとか、そういうのも大事なんだろうなとか思ったりして。
 
にしても、責任感とか主体性とか、絶対に逃げない姿勢とか、ハンパない。
私利私欲云々もアレだけど、あんまり小さい事ばっか言ってないで、
微力ながらも、自分ももうちょっと頑張らないとイカンなぁと。
そんな風に思わせてくれる一冊でした。
 
いやー、この本は巡りあえてよかった。ほんとに。

2012.01.22

ソーシャルコマース ~業界キーマン12人が語る、ソーシャルメディア時代のショッピングと企業戦略~


ソーシャルコマース ~業界キーマン12人が語る、ソーシャルメディア時代のショッピングと企業戦略~
桜丘製作所株式会社 イケダハヤト 三橋ゆか里 川田智明
マイナビ
売り上げランキング: 21494

ソーシャルコマースを読みました。
 
IT業界で働いてても、たまにはこういう本読まないと、
実は業界全体がどういう風に動いていってるのか分からなかったりします。
 
“海外展開するならFacebook”
もうコレなんですね。Facobookは友達とのコミュニケーションにしか使ってないけど、
例えば、ハーレー(バイク)のカスタムやってるBAD LANDさん。
“日本のハーレーのカスタムは世界一って言われてる”
それを海外に向けて〜って考えたら、Facebookなんだ、と。
 
他にも興味深い事例とか沢山乗ってて、Yahoo!さんの、
“メールはたくさん打て、巻き物のような長いページを作れ、
ポイントをどんどんつけろ、というアプローチは通用しなくなる”
コレなんかグサっとくるところだったりします。
 
また、サンフランシスコでお世話になった@SocialGregの会社のCEOのブランドンさんが、
Javaの勉強会で毎回高度な技術を紹介してくれた、
スマホ決済のSquareのインタビューに答えてたり、
自分の会社に同じタイミングで入社した役員の人のアツいインタビューとか、
読み応え満載でした。
 
Facebookの広告ってとてもシンプルで使いやすいシステムで、
#って、実際に自分で広告運用してないから分からないのですが、
#前に英会話習ってた先生からMixiに広告出したいけどFBみたいに簡単にできないの?
#って聞かれて見て、ちょっとイジってみたら使いやすさにビックリ。
それを使って、サクっと広めて、今じゃ何万人もの人がファンになってて、
なんか記事上げればすぐ1000いいね以上いくとか。うぉーって感じです。
 
Facebook上だけで完結する決済の仕掛けもあるわけで、
海外考えると、課題は送料とか輸送系。この辺どうなってくのかねってところで。。
 
んま、こういう本読んで、ただ、へー、そーなんだーって思ってても仕方ないので、
エンジニアとしてどうこの潮流と絡んでくのか?ってのは自分で戦略立てなきゃ
いけないなぁと思ったりするわけです。

2012.01.18

JenkinsをLinuxにインストールした時のメモ


Linux(ディストリビューションすら分からずw)にJenkinsをインストールした時のメモ
 
■ Java(JDK7)インストール
諸事情で特定の場所に入れる必要があったので。

wget http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-x64.tar.gz
tar xvf jdk-7-linux-x64.tar.gz

ちなみに↓なので

$ env | grep SHELL
SHELL=/bin/bash

↓こんな設定いれてwgetしましたよ、と。

$ cat ~/.bashrc | grep proxy
export http_proxy=hogehoge.co.jp:9999

 
■ Jenkinsのホームページ(http://jenkins-ci.org/)からwarファイルをダウンロード
↓こんな感じで。

wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war

 
■ Tomcatをインストール

wget http://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-7/v7.0.23/bin/apache-tomcat-7.0.23.tar.gz
tar xvf apache-tomcat-7.0.23.tar.gz
ln -s apache-tomcat-7.0.23 tomcat
cd tomcat/bin
./startup.sh

で http://ホストとかIPとか:8080 で↓みたいな画面が出ればOK

 
■ webappsディレクトリにjenkins.warを配置して再起動

cp jenkins.war TOMCAT_HOME/webapps/
cd TOMCAT_HOME/bin
./shutdown.sh
./startup.sh

http://ホストとかIPとか:8080/jenkins にアクセスすると
↓こんなんがちゃんと出てくればインストール成功です。

 
■ UTF-8がどうのこうの
↓のようになんか言われるので、

↓のようにserver.xmlのConnectorの設定にUTF-8の記述を足します。
 
んで、”Jenkinsの管理”からJAVA_HOMEの場所を
JDKってところに↑で入れたパスを指定していれてやります、と。
 
■ Mavenのインストール
コレも普通に落としてきて解凍するだけだけど、

wget http://www.apache.org/dist//maven/binaries/apache-maven-3.0.3-bin.tar.gz
tar xvf apache-maven-3.0.3-bin.tar.gz
ln -s apache-maven-3.0.3 maven

プロキシ使う時は、Mavenをインストールしたところのconfディレクトリにある
settings.xmlで↓のように。

  
Jenkinsでsetting.xmlは、プロジェクトの設定(リポジトリのURLとか登録する画面)で、
ビルドのところにある”高度な設定”ボタンで指定できます。

 
■ Jenkinsのプロキシ
Jenkinsでプロキシの設定をするのに-DオプションでJVMに引数渡すのかと思ったら、
Jenkinsの管理⇒プラグインの管理⇒高度な設定 で↓のように出来るんですね。

 

途中MongoDB Tokyo 2012で職場いなかったのですが、
↓やっとこさ黄色まできましたって感じw

 
これでインフラ的なところは整ったのであとは
画面からイロイロ設定したり、pom.xmlでアレやコレやしたりして、
ガツガツCIしていきます。
 
↓買おうか悩み中な今日この頃です。ほんとこの手のはPDFで買いたい…

Jenkins実践入門 ~ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)
佐藤 聖規 和田 貴久 河村 雅人 米沢 弘樹 山岸 啓
技術評論社
売り上げランキング: 4447

2012.01.15

ゆるく考えよう – ちきりん


ゆるく考えよう 人生を100倍ラクにする思考法
ちきりん
イースト・プレス
売り上げランキング: 885

ゆるく考えよう 人生を100倍ラクにする思考法を読みました。
 
Chikirinの日記(http://d.hatena.ne.jp/Chikirin/)はいつも楽しみに読んでるわけなんですが、
まとまった感じでドップリちきりんワールドに浸りたかったので書籍を購入しました。
 
悪いこと言わないから一回読んでみたらイイんじゃないかな?って感じで。
 
なんか知らないけど、普段からやたらアクセクしてたり、悲観的だったり、
仕事とかに自意識過剰っていうか、そういう風になりたくないなぁって
ぼんやり思ってたりするわけなんですが、この本読むと、それでイイじゃんって
背中をポンって押してもらえたような感じで。
 
ただ、どうせなら、いろんなトコいって、いろんなモノみて、感じてって事を
したいんですが、最近では、ブルーカラーとかホワイトカラーの他に
ゴールドカラーって人たちが出てきた、と。
別にこれはちきりんが定義したアレじゃないんでしょうけど、
“中国の田舎生まれで、清華大学(中国の理系トップ大学)の工学部で博士号をとり、
その後ハーバード大学で経済学の博士号をとって国際機関で働き、
今は米系の投資銀行で働く傍ら、 中国政府のアドバイザーもやっている”
みたいな、生活圏がハンパなく広い人の事をゴールドカラーって言うらしいです。
いわゆる勝ち組的みたいなそんな感じなんですかね。
 
んま、自分は学歴とかそういうモノより、現場でエンジニアやりながら
自分を成長させたいタイプなのですが、移動距離が長い感じなのはアツいな
って常日頃から思ってて、それが上手いことゴールドカラー的な感じになったら
オイシイかなとか思ったりしました。
サンフランシスコもナイスなとこだったし。他にもたくさんいろんなトコみてみたい。
 
にしても、分を知るとか、日本ってイイじゃないとか、
そーだよねーって思える事のオンパレードで、最後は楽観的に〜なんていう
これまたナイスな〆め方だなって感じで、サクっと読めちゃう割に、
自分のこれからの人生において、少なからず影響を与えてくれそうな本でした。
 
にしても、この語り口が何とも言えないやねー。
俺もやり方は違えど、こんくらい説得力のある文章書けるようになりてー。
 
ちなみに↓新しい本出てるんですね。こっちもチェックしてみようと思います。

自分のアタマで考えよう
ちきりん
ダイヤモンド社
売り上げランキング: 64

 
そんじゃーね。

2012.01.06

Spring3.1の宣言的キャッシングを試してみる


SpringSourceの記事を読んでたら、Spring 3.1で
“A declarative, annotation-driven caching model”とか書いてあって、
比較的大量なアクセスを受け付けるアプリを作る事が多いので、ちょっとチェックしてみたいな、と。
 
って事でさっそくやってみます。
 
■ pom.xmlをSpring3.1に書き換える

<org.springframework-version>3.0.6.RELEASE</org.springframework-version>
<org.springframework-version>3.1.0.RELEASE</org.springframework-version>

 
 
■ てか、そもそもどういうテクノロジ?
SpringSourceのブログのSPRING 3.1 M1: CACHE ABSTRACTIONを読むと、
↓みたいな感じで仕掛けておくと、 

@Cacheable("books")
public Book findBook(ISBN isbn) {...}

キャッシュの中に、そのisbn番号のBookオブジェクトが見つかったら、
メソッドの実行をスキップして、returnしますよ、と。
 
引数が複数ある場合はあーでこーでみたいなテクニックがあるようですが、この際なので省略しますw
 
んで、中身はっていうと、サクっと使えるのは
1. encache(http://ehcache.org/)っていうQuartz(ジョブスケ)とかもやってるTerracottaのアレと、
2. JavaのConcurrentHashMapを使ったシンプルな感じのヤツらしいです。(Not Distributed)
 
Gemfireがウンたらカンたらって書いてあったけど、具体的な事は書いてなかったす。。
JPAの2nd-level cacheとの違いはーとかも書いてあったけど、それ使った事にゃい…
 
 
■ Springの定義ファイル的には
↓のような名前空間があって、

xmlns:cache="http://www.springframework.org/schema/cache"

↓こんな感じでアノテーションでイケるように仕掛けて、

<cache:annotation-driven />

↓cacheManagerの定義入れておくとOK、、のはずが、、

<!-- generic cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
  <property name="caches">
    <set>
      <bean class="org.springframework.cache.concurrent.ConcurrentCacheFactoryBean" p:name="default"/>
      <bean class="org.springframework.cache.concurrent.ConcurrentCacheFactoryBean" p:name="books"/>
    </set>
  </property>
</bean>

org.springframework.cache.concurrent.ConcurrentCacheFactoryBean
って書いてあったから、bean定義そうしたら、そんなクラスないとか言われて、
正しくはConcurrent”Map”CacheFactoryBeanだそうで。。知らんがな…w
 
 
■ 動かしてみる
Controllerのコードの中に↓のようなログを仕込んで

@RequestMapping(value = "/hoge/search/{id}", method = RequestMethod.GET)
public String searchById(@PathVariable int id, Locale locale, Model model) {
	★ logger.info("Controller: hoge Search By ID"); ★
	hoge hoge = hogeDao.findById(id);
	String hogeJsonStr = JSON.encode(hoge);
	model.addAttribute("hogeJson", hogeJsonStr );
	return "hoge";
}

Daoのコードの中に↓のようなログを仕込んで

@Cacheable("hoge")
public hoge findById(int hogeId) {
	★ logger.info("Dao: hoge Find By ID"); ★
	RowMapper mapper = new BeanPropertyRowMapper(hoge.class);
	return this.template.query(SELECT_BY_ID, mapper, hogeId).get(0);
}

動かそうと思ったら、、、

org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
	at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67)

トホホ…。だりぃ。。。
 
ってことで↓をpom.xmlに突っ込んでやって、、

 
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

 
動かしたら、、、@Cachableが効いてるのでログ的には最初の一回しかDaoのメソッドは呼ばれませんよ、と。

INFO : com.shinodogg.HogeController - Controller: hoge Search By ID
INFO : com.shinodogg.dao.HogeDao - Dao: hoge Find By ID
INFO : com.shinodogg.HogeController - Controller: hoge Search By ID
INFO : com.shinodogg.HogeController - Controller: hoge Search By ID
INFO : com.shinodogg.HogeController - Controller: hoge Search By ID
INFO : com.shinodogg.HogeController - Controller: hoge Search By ID

 
 
キャッシュのクリアとか、Expireどうすんだ?とか、JVMのメモリどんだけ食うんだ?とか、
考えなきゃいけないことはイロイロありそうですが、
永続化のところは何かとボトルネックになりがちなので、
こういうのでちょっとでも裏を楽させてあげるのは良いことかなぁと。
 

SpringによるWebアプリケーションスーパーサンプル 第2版
株式会社クロノス 阪田 浩一
ソフトバンククリエイティブ
売り上げランキング: 24403

2012.01.05

Gitでchmodをシカトする場合(git config core.filemode false)


git clone http://hogehoge.co.jp/git/hoge って感じでリポジトリをクローンしてきて、
git branch oreore って感じでブランチ作って
git checkout oreore って感じでブランチにきてから、
諸事情により chmod -R 777 hoge してから、あれやこれやしてコミットしたら、
fileのmodeが変わりましたよーー的なログがドヤーーっと出てしまったりして。
そこはよしなにシカトして欲しい場合は、

 
git config core.filemode false

 
こんな風にするんだそうで。
そうすると、

 
git config --local -l | grep filemode
core.filemode=false

ってな感じでメデタシメデタシ。
 

入門git
入門git
posted with amazlet at 12.01.05
Travis Swicegood
オーム社
売り上げランキング: 5822

2011.12.26

Javaのkeytoolを使ってオレオレ証明書の壁を突破する


Eclipseのプラグインからオレオレ証明書なURLにアクセスしようとすると何か↓こんなの出てる、、っていう。

Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)

 
そのプラグインのソース書き換えるってわけにもいかんので、
ローカルのJavaでシカッティングしてやろうと。
 
ググって一番上に出てきた javaでhttps通信 | 来栖川電算 によると、
javaのkeytoolを使って証明書を追加すればイイっぽい。
 
FireFoxでそのURLにアクセスすると、『接続の安全性を確認できません』とかいうモノモノしいページが出て、
例外を追加ボタンを押すと、証明書が表示出来て、詳細タブを押すと証明書がエクスポート出来ます。
エクスポートするときに種類を『X.509 証明書(PEM)』とかいうので引っこ抜きます。
でもって、引っこ抜いたファイルをJavaのkeytoolを使ってインポートします。 

C:\Program Files\Java\jdk1.6.0_24\bin>keytool -import -file エクスポートしたファイル -keystore "C:\Program Files\Java\jdk1.6.0_24\jre\lib\security\cacerts"
キーストアのパスワードを入力してください:
新規パスワードを再入力してください:

こいつ(cacerts)のデフォルトのパスワードは”changeit”なんだそうです。

この証明書を信頼しますか? [no]:  yes
証明書がキーストアに追加されました。

って感じでアクセスしてやると、SSLのエラーは回避出来たみたいです。
#そのかわり、また違うエラーが出てるんでてますが、、汗
#そっちはまた別途。
  

Effective Java 第2版 (The Java Series)
Joshua Bloch
ピアソンエデュケーション
売り上げランキング: 6062

Next »