読者です 読者をやめる 読者になる 読者になる

記憶永続化用のメモブログ

脳内に揮発性記憶領域しかないことに気づいたので作成

gradle + jmockitでjava.lang.IllegalStateExceptionって出たので対応

jmockitを使っていて gradle test とかやったら以下のエラーが出た。

java.lang.IllegalStateException: JMockit wasn't properly initialized; check that jmockit.jar precedes junit.jar in the classpath (if using JUnit; if not, check the documentation)

どうやらclasspathjunitのjarより前にjmockitのjarの方が通ってる必要があるらしく、普通に書いてたら順番がいけてなくてダメだった。

で、以下のように対応したら大丈夫だった


Jmockit + gradle test

Elasticsearchで色々やったことをメモ

大量のデータをElasticsearchで扱ったときに色々と起きた問題の対処をメモ(雑)

Elasticsearch v1.0.1
Amazon EC2
JDK 1.7.0_21

問題

データ量が多くなってから検索系のクエリを投げるとElasticsearchが停止する
indexを日付別に切っているが、結構な日数分を集計するクエリを投げるとOOMになってしまった。

原因(多分)

kibanaのクエリが結構エグい

色々なグラフを1画面に乗せておくと1回のリロードで大量のクエリがElasticsearchに投げられていた。
根本解決にはならないけど、kibanaの1画面に乗せる画面数を減らした

フィールドキャッシュの上限が無制限だった

設定ファイルで指定してあげないとキャッシュがひたすら溜まって行く模様だった。
indices.fielddata.cache.expire
indices.fielddata.cache.size
を設定してあげた。
あとシャード数を増やしてサーバ台数も増設して1台あたりの負荷を分散させた。

CPUリソースが足りない

びっくりするくらい検索にCPUを使っていたので、EC2インスタンスタイプをCPU上げた。
ただ最終的には設計から見直して検索によく使う部分を入れるindexを作って、そのindexに登録されるデータ量を減らしたら劇的にCPUを使わずに検索出来るようになった。
大量のデータが存在するindexに検索にかけないように設計しなきゃダメ。


まとめ中

td-agent -> Elasticsearchで困ったことをメモ

td-agentでリトライ上限を超えてタイムアウトで失敗したキューが消える

td-agentからElasticsearchにログを流し込んでたら、処理しきれなくてリトライ回数を超えて失敗してたキューをロストしてた。
以下のログがtd-agentのログに出てました。

2014-05-20 06:07:11 +0000 [error]: throwing away old logs.

たぶんElasticsearchにbulk APIで流し込むところのタイムアウトでこけてるので、以下の対応を考えた。

ログのロストをしないようにする

td-agentの設定にsecondaryディレクティブを設定して、リトライ上限を超えて失敗したキュー(チャンク)をファイルで保存しておいて、後でまとめて再実行する
ログを消失させたくない話 - OTメモ帳
上記のサイトを参考にさせてもらったらばっちりでした。ありがとうございます。

Elasticsearchのbulk APIを叩く際に、replication = asyncにする

td-agentのプラグイン
https://github.com/uken/fluent-plugin-elasticsearch/blob/master/lib/fluent/plugin/out_elasticsearch.rb:fluent-plugin-elasticsearchをカスタマイズ使っているのだけれども、bulk APIを叩くところにreplication : "async"ってパラメータを渡して、レプリケーションを非同期で行うようにしてレスポンスを速く返るようにする。

def send(data)
    client.bulk body: data replication: "async"
end

元ネタは
Index API

さて効果は出るだろうか。

Freemarkerって遅いの?

なんか現行のシステムがString#formatでタグ作ってたから、テンプレートエンジン使うと遅いのかなって思って簡単な調査。


FreeMarkerTest
※ 上記コードは1000000回ループ。

10回ループ

試行回数 Freemarker String#format()
1 90962000 (0) 60003000 (0)
2 98667000 (0) 37471000 (0)
3 92529000 (0) 33368000 (0)
4 106556000 (0) 33661000 (0)
5 89869000 (0) 35237000 (0)
平均 95716600 (0) 39948000 (0)

ナノ秒(括弧内の数値はYoungGCの処理時間(秒))

10回のループだと平均で3倍弱速かった。
ただし、各Runner#run()の開始から終わりまでSystem.nanoTime()の差分を計ったら

ループ回数 Freemarker String#format()
1 95704000 35038000
2 315000 546000
3 269000 504000
4 280000 383000
5 272000 387000
6 262000 412000
7 248000 383000
8 302000 396000
9 265000 401000
10 246000 373000

だったので、ループ開始時の初回のみ大きく差が出ていてそれ以外は大きく差が出ていなかったので速度自体はそんなに変わらないっぽい。

1000000回

試行回数 Freemarker String#format()
1 13621484000 (0.095908) 14490797000 (0.112314)
2 13510582000 (0.106299) 13599284000 (0.103076)
3 13726206000 (0.065058) 13826649000 (0.106106)
4 13704940000 (0.077895) 13838695000 (0.091303)
5 13746025000 (0.110715) 13656157000 (0.090931)
平均 13661847400 (0.091175) 13882316400 (0.100746)

ナノ秒(括弧内の数値はYoungGCの処理時間(秒))

結果、そんなに変わらない。

AWSでElasticSearch & AutoScalingを使ってみたのでメモ

インスタンスを作成ElasticSearchをインストール

wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.90.5.noarch.rpm

sudo rpm -ivh ./elasticsearch-0.90.5.noarch.rpm

sudo tar -xvf jdk-7u51-linux-x64.tar

sudo mv jdk1.7.0_51 /usr/local/

sudo alternatives --install /usr/bin/java java /usr/local/jdk1.7.0_51/bin/java 200

# JDK7の方を選択
sudo alternatives --config java

java -version

cd /usr/share/elasticsearch/

sudo bin/plugin --install elasticsearch/elasticsearch-cloud-aws/1.16.0
sudo bin/plugin --install royrusso/elasticsearch-HQ
sudo bin/plugin --install mobz/elasticsearch-head
sudo bin/plugin --install lukas-vlcek/bigdesk

sudo vim /etc/elasticsearch/elasticsearch.yml

sudo service elasticsearch start

cat /var/log/elasticsearch/elasticsearch.log

sudo service elasticsearch stop
  • /etc/elasticsearch/elasticsearch.ymlに書いたこと


cluster.name: elasticsearch

discovery.zen.ping.multicast.enabled: false

cloud.aws.region: ap-northeast-1
cloud:
aws:
access_key: XXXXXXXX
secret_key: XXXXXXXXXXXXXXXXXXXXXXXXXXX

discovery:
type: ec2

ec2:
tag:
hoge-tag-key: hoge-tag-value

AMIを作成する

AutoScalingをするのに使います
AWSのコンソールから作成する -> AMI IDをメモる

Subnetを作成する

AutoScalingのときにIPの範囲を絞るために使います
AWSのコンソールから作成する -> Subnet IDをメモる

Load Balancerを作成する

AWSのコンソールから作成する -> Load Balancer Nameをメモる

Security Groupを作成する

AutoScalingの時に自動でElasticSearch用サーバに付与するのに使います
AWSのコンソールから作成する -> Inboundで9200-9400ポートを開ければよさげ(もしかしたらもっと狭くてもいいかも) -> Group IDをメモる

AutoScalingの設定をする

AutoScalingToolのインストール(適当なサーバとかローカルの端末とかにインストール)

wget http://ec2-downloads.s3.amazonaws.com/AutoScaling-2011-01-01.zip
unzip AutoScaling-2011-01-01.zip
mv AutoScaling-1.0.61.4 /usr/local/
cd /usr/local/
ln -s AutoScaling-1.0.61.4 autoscaling
export PATH=$PATH:/usr/local/autoscaling/bin

AutoScalingConfigの登録

# imageId = AMI ID , accessKeyとsecretKeyは操作権限のあるIAMのを書く
as-create-launch-config hoge-config \
--image-id ami-XXXXXXXXX \
--instance-type t1.micro \
--key hoge-internal \
-I ${accessKey} \
-S ${secretKey} \
--region ap-northeast-1

AutoScalingGroupの登録

# vpc-zone-identifierはsubnetId,load-balancersはLoad Balancer Name
# タグはElasticSearchのAWS設定でタグフィルターで使用する
as-create-auto-scaling-group hoge-group \
--launch-configuration hoge-config \
--availability-zones ap-northeast-1a \
--group sg-XXXXXXX,   \
--tag "k=hoge-tag-key, v=hoge-tag-value, p=true" \
--min-size 1 --max-size 10 \
--load-balancers ${loadBalancerName} \
--vpc-zone-identifier subnet-XXXXXXX \
-I ${accessKey} \
-S ${secretKey} \
--region ap-northeast-1

AWSでMySQL MHAを導入したときのメモ

AWSドシロートがやってみたのでメモ (まだ記述途中)

構成

サーバ IP
監視サーバ 10.0.10.1
マスターDB 10.0.10.11
待機用スレーブDB 10.0.10.10
参照用スレーブDB 10.0.1.10

インストール


Mysql Master HAをソースからインストールするレシピ

MHA Masterの設定
vim /etc/mastermha/mysql-mha.cnf
※ Gist参照

VIP用ENIの作成
コンソールからENIを作成して、プライベートアドレスにVIPとして使うIPを付けてる。
作成したらNetwork Interface IDをメモる(VIP付け替えスクリプトで使用する)
とりあえずコンソールから現在稼働中のマスタDBサーバにVIP用のENIをAttachしてあげる
当然、アプリケーションからマスタへの接続はVIPで接続するように修正する

AWS CLI Tool用ユーザの作成
コンソールからIAMにユーザを作って以下の権限を追加してあげる。
※ 既に存在するならそのユーザを使えばいい

{
"Statement": [
{
"Action": [
"ec2:DescribeInstances",
"ec2:DetachNetworkInterface",
"ec2:AttachNetworkInterface",
"ec2:DescribeNetworkInterfaceAttribute"
],
"Effect": "Allow",
"Resource": "*"
}
]
}

AWSAccessKeyIdとAWSSecretKeyをメモして/opt/aws/credentials.txtに記述する。
※/opt/aws/credential-file-path.templateをコピーして作るとよい
/opt/aws/credentials.txtは/etc/profile.d/aws-apitools-common.shの中で$AWS_CREDENTIAL_FILEという変数にexportされてた(最初はコメントアウトされている)
※ 別exportしなくても直接このファイルを読み込んでもいいけどテンプレートがあったので使ってみた

各ノード間にノンパス設定

サーバ 使用するユーザ
監視サーバ root
マスターDB mysql
待機用スレーブDB mysql
参照用スレーブDB mysql

MHA Managerを起動する

nohup /usr/local/bin/masterha_manager --conf=/etc/mastermha/mysql-mha.cnf > /usr/local/masterha/masterha_manager.log &

/usr/local/masterha/masterha_manager.logにエラーが出ていなければok

エラー出たとこ

  • 現マスターとマスター候補の2台構成のとき両方ともread_only=0 ?

[error][/usr/share/perl5/vendor_perl/MHA/ServerManager.pm, ln732] Multi-master configuration is detected, but two or more masters are either writable (read-only is not set) or dead! Check configurations for details. Master configurations are as below:

現マスターとマスター候補の2台構成のとき両方ともread_only=0だと怒られるので、マスター候補の方は
SET GLOBAL read_only = 1;
でread_onlyに設定しておく。

read_onlyの確認方法

mysql> SELECT @@read_only;

  • Log/Dispatch.pmがインストールされてない?

Can't locate Log/Dispatch.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/local/share/perl5/MHA/MasterMonitor.pm line 28.
BEGIN failed--compilation aborted at /usr/local/share/perl5/MHA/MasterMonitor.pm line 28.
Compilation failed in require at /usr/local/bin/masterha_manager line 26.
BEGIN failed--compilation aborted at /usr/local/bin/masterha_manager line 26.

$ sudo cpan
cpan[1]> install CPAN
cpan[2]> install Module::Build
cpan[3]> quit
$ sudo cpan
cpan[1]> install Log::Dispatch
cpan[2]> install Log::Dispatch::FileRotate
cpan[3]> quit
  • テストしてる間に接続エラー出しすぎてマネージャーホストが拒否された!?

ue Mar 11 21:13:56 2014 - [error][/usr/local/share/perl5/MHA/ServerManager.pm, ln255] Got MySQL error when connecting 10.0.1.10(10.0.1.10:3306) :1129:Host '10.0.10.1' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts', but this is not mysql crash. Check MySQL server settings.
at /usr/local/share/perl5/MHA/ServerManager.pm line 251
Tue Mar 11 21:13:56 2014 - [error][/usr/local/share/perl5/MHA/ServerManager.pm, ln263] Got fatal error, stopping operations
Tue Mar 11 21:13:56 2014 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln386] Error happend on checking configurations. at /usr/local/share/perl5/MHA/MasterMonitor.pm line 300
Tue Mar 11 21:13:56 2014 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln482] Error happened on monitoring servers.
Tue Mar 11 21:13:56 2014 - [info] Got exit code 1 (Not master dead).

ログにある通り各MySQLサーバで

$ mysqladmin  -uroot flush-hosts