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)
どうやらclasspathがjunitのjarより前にjmockitのjarの方が通ってる必要があるらしく、普通に書いてたら順番がいけてなくてダメだった。
で、以下のように対応したら大丈夫だった
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: elasticsearchdiscovery.zen.ping.multicast.enabled: false
cloud.aws.region: ap-northeast-1
cloud:
aws:
access_key: XXXXXXXX
secret_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXdiscovery:
type: ec2
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