さあその先へ OpenLDAP パフォーマンスチューニング 2010/02/26 日本 LDAP ユーザ会 1
はじめに OpenLDAP は 他のオープンソースソフトウェアと同様に わずかなマシンリソースでも動作させることができるディレクトリサーバです OpenLDAP は わずかなチューニングを施すことで 飛躍的に性能を向上させられる可能性を秘めたソフトウェアです 本セッションでは OpenLDAP サーバのチューニングの勘所をご紹介します 2
目次 試験環境 チューニング DB_CONFIG と Berkeley DB バッファ設定 検索処理フローと インデックス ログファイルと syslogd エントリキャッシュ ID リストキャッシュ スレッド数 もう一歩 その先へ 3
試験環境 4
試験環境 サーバ機 CPU:2.53GHz Quad Core 2 メモリ :12G ディスク :146GB SAS 10rpm 4 ディスクコントローラ :512M キャッシュ 負荷サーバ OS:CentOS 5.4 x86_64 JVM:Sun 64bit 1.6.0_18 検証ツール : slamd-2.0.0 OpenLDAP サーバ OS:CentOS 5.4 x86_64 Berkeley DB:4.7.25 OpenLDAP: 2.4.19 OpenLDAP 2.4.19 (+ Berkeley DB 4.7.25) は 本資料作成時点本資料作成時点でのでの最新最新の安定版安定版リリースリリースですです 5
slamd からの負荷内容 LDAP プロトコルでの様々な試験が可能なツール 検証に用いた負荷の内容 Bind( 認証 ) 処理 1 : Search( 検索 ) 処理 3 の割合 LDAP Mixed Load 1 万のエントリを対象 検証時のセッション数 100 セッション (10 クライアント 10 スレッド ) 6
OpenLDAP サーバの初期設定 特別なオプションなしでインストール 試験中に ログファイルを参照してエラーがないかを確認できる状態 syslogd へ stats ログを送付し 記録 試験中に ldapsearch にて slapd の動作状況を確認できる状態 monitor データベースを利用 7
DB_CONFIG を知っておこう! 8
DB_CONFIG 利用の意味 ざっくり Berkeley DB をチューニング Berkeley DB への参照処理性能の向上 set_cachesize ディレクティブ Berkeley DB への更新処理性能の向上 set_lg_bsize ディレクティブ サンプルファイルをコピーするだけ 9
set_cachesize ディレクティブ Berkeley DB が共有メモリとして利用する バッファプールのサイズ 目標は *.bdb の合計サイズより大きく slapd Berkeley DB dn2id.bdb xx.bdb id2entry.bdb yy.bdb db.003 10
set_lg_bsize ディレクティブ Berkeley DB がログバッファとして利用する データ変更処理 メモリ領域のサイズ 大きな更新では 大きなサイズで性能が向上 2M Berkeley DB db.004 log.n 11
Berkeley DB バッファプール で その先へ! 12
OS ファイルシステムキャッシュ Berkeley DB 側で OpenLDAP のデータをキャッシュしきれなくても OS のファイルシステムキャッシュでキャッシュすることもできる OS のキャッシュがあるため Berkeley DB 側のバッファプールのチューニング効果は見えにくいことが多い dn2id.bdb ファイルシステムキャッシュ id2entry.bdb db.003 13
Berkeley DB バッファプール OS のファイルシステムキャッシュを利用できない場合 Berkeley DB バッファプールが性能に影響 バッファプールへのページ読込み頻度が性能に影響 バッファプールのサイズは set_cachesize で調整可能 dn2id.bdb id2entry.bdb db.003 14
バッファプールの利用価値 Linux では OS 提供のファイルシステムキャッシュは 余剰メモリが割り当てられる OS が 他のプロセスにも利用するキャッシュ OpenLDAP 側での制御ではない OpenLDAP にとって 自分で管理できる Berkeley DB のバッファプールは 信頼しやすい 2 重バッファを行わないために わざわざ O_DIRECT フラグを用いるという考え方も しっかりとした サイジングが必要 O_DIRECT フラグは Linux カーネル 2.4.10 以降で利用可能利用可能ですです OpenLDAPのバックエンドバックエンドとなる Berkeley DB での利用利用にはには OpenLDAP コミュニティからのからのパッチパッチと コンパイルオプションコンパイルオプションの変更変更が必要必要ですです 15
set_cachesize ディレクティブ デフォルトは 256KBytes 最小は 20KBytes DB_CONFIG では 256MBytes を設定 500MBytes 未満は 自動的に設定値 +25% 003.db は +25% で 320MBytes に ざっくり見積りは OpenLDAP データ領域で # du -c -h *.bdb 16
Berkeley DB バッファプールの効果 OSキャッシュが利用できない状況にする目的で あえてO_DIRECTで.bdbファイルをオープン O_DIRECT と set_cachesize=256mb ココを 100% O_DIRECT と set_cachesize=256kb 15% バッファプール不足不足で 今回 秒間処理量秒間処理量が わずか 15% までに減少 結果は 今回今回の検証環境検証環境でのでの値ですです 性能劣化性能劣化のインパクトインパクトは Berkeley DB バッファプールへのへのページページ読み込み処理処理の発生頻度発生頻度にもにも関係関係しますします 17
安心を バッファプールで安心 DB_CONFIG set_cachesize Berkeley DB のバッファプールを活用しよう! 18
Berkeley DB ログバッファ で その先へ! 19
slapadd でのデータロード速度 DB_CONFIG で ログバッファを調整 DB_CONFIG を適用 set_lg_bsize=2m 198.0KB/sec デフォルト状態 set_lg_bsize=32k およそ 3.36 倍更新性能 up 58.9KB /sec 結果は 今回今回の検証環境検証環境でのでの値ですです 性能改善性能改善のインパクトインパクトは ディスク IO 性能にもにも依存依存しますします 20
更新性能 up! ログバッファで更新性能 DB_CONFIG set_lg_bsize Berkeley DB のログバッファを活用しよう! 21
検索の仕組み を知っておこう! 22
ディレクトリ情報ツリーの検索 ldapsearch -x -b dc=my-domain,dc=com -s sub 検索を開始開始するするベース ディレクトリ情報ツリー : DIT (Directory Information tree) エントリ 識別名 : DN (Distinguished Name) 検索スコープ 0 : base ( 検索ベースのみ ) 1 : one ( 検索ベース以下 1 レベル ) 2 : sub ( 検索ベース以下全て ) 3 : children ( 検索ベースを除き以下全て ) のどれかを指定 や 属性 : (Attribute) を持つ dn:uid=xx,ou=yy,dc=zz cn:xx uid:xx sn:xx ObjectClass: ObjectClass: 23
back-bdb での エントリの扱い Berkeley DB は Key/Value ストレージ リレーショナル DB ではない OpenLDAP の各エントリに一意の ID を付与 dn:uid=xx,ou= xx, dc=zzz が欲しい dn dn2id.bdb ID ID id2entry.bdb slapd entry 24
back-bdb での エントリ検索 最初に 検索ベーストップの ID を取得 続いて 検索ベーストップのエントリを取得 繰り返し 同じ要領で検索スコープ内のDN と エントリを取得 ldapsearch -x -b ou=xx,dc=yy -s sub * dn ID dn2id.bdb 検索ベーストップから スコープ内のエントリ分繰り返し client entries slapd ID entry id2entry.bdb ou=xx,dc=yy 25
インデックス で その先へ! 26
フィルタを付けてのエントリ検索 検索条件にフィルタを利用し 検索対象と ldapsearch -x -b ou=xx,dc=yy -s sub uid=test1000 なる件数を減らしたいが ( ここでは uid=test1000 を指定 ) フィルタと比較する情報は id2entry.bdb に格納されている為 やっぱり何度も DB アクセスしないと 回答が返せない dn ID dn2id.bdb 検索ベーストップから スコープ内のエントリ分繰り返し ou=xx,dc=yy entries ID client slapd entry id2entry.bdb 27
インデックスファイル インデックスキー - ID をマップ 与えられた検索フィルタから 必要エントリのみへのアクセスを可能にする情報 dn2id.bdb は DN - ID をマップ id2entry.bdb は ID - エントリ をマップ dn2id.bdb id2entry.bdb xx.bdb 28
インデックスを利用した検索 インデックスファイルを利用して ピンポイ ントで必要なエントリを読む為の ID を取得 bdb_key_read() ID または IDのリスト xx.bdb dn2id.bdb slapd bdb_id2entry() エントリ id2entry.bdb 必要な回数回数だけにだけに限り データベースへアクセス db.003 Berkeley DB 29
30 インデックスを利用しない検索 ピンポイントの DB アクセスができず 延々とエントリを取得し続けなければならない db.003 xx.bdb Berkeley DB slapd id2entry.bdb dn2id.bdb bdb_dn2id() ID bdb_id2entry() エントリエントリエントリエントリ検索検索検索検索ベースベースベースベース 検索検索検索検索スコープスコープスコープスコープの範囲範囲範囲範囲で延々データベースデータベースデータベースデータベースへのへのへのへのアクセスアクセスアクセスアクセスを繰り返えすえすえすえす
31 OS から見る インデックス効果 インデックス情報を利用できない場合は slapd は 無駄に働きすぎてしまう 頑張って働いても 結果は良くない 0% 20% 40% 60% 80% 100% 0% 20% 40% 60% 80% 100% インデックスインデックスインデックスインデックスなしでのなしでのなしでのなしでの仕事量仕事量仕事量仕事量インデックスインデックスインデックスインデックス利用時利用時利用時利用時の仕事量仕事量仕事量仕事量試験時間試験時間試験時間試験時間試験時間試験時間試験時間試験時間 idle sys usr idle sys usr iowa
index ディレクティブの設定 slapd syslog に送られたログを参照することで 設定するべきインデックスを確認できる # view servers/slapd/back-bdb/filterindex.c [ 略 ] slapd.conf とかに loglevel 0 が指定されない限り loglevel 0 の場合場合は 出力出力されませんされません if ( rc == LDAP_INAPPROPRIATE_MATCHING ) { } Debug( LDAP_DEBUG_ANY, return 0; フィルタが指定されているのに 利用できなかったら "<= bdb_equality_candidates: (%s) not indexed n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); この属性に このタイプのインデックスを使いたかったとログに出すから 32
index ディレクティブの設定 syslogに送られたログを参照することで 設定するべきインデックスを確認できる # tail -f /var/log/ldap.log [ 略 ] slapd date time HOST slapd[pid]: <= bdb_equality_candidates: (uid) not indexed [ 略 ] uid 属性に eq インデックスが欲しい date time HOST slapd[pid]: <= bdb_substring_candidates: (uid) not indexed [ 略 ] date time HOST slapd[pid]: <= bdb_approx_candidates: (uid) not indexed [ 略 ] uid 属性に sub インデックスが欲しい uid 属性に approx インデックスが欲しい 33
index ディレクティブの設定 同じ内容が頻繁にログ出力される場合は 特に効果が期待できる slapd slapd.conf include database bdb suffix dc=my-domain,dc=com [ 略 ] index uid eq database bdb suffix dc=example,dc=com [ 略 ] グローバルセクションバックエンド DB #1 バックエンド DB #2 34
slapindex でのインデックス作成 slapindex でのインデックス作成手順 1. OpenLDAPサーバの停止 2. slapd.confの index を更新 3. slapindexを実行 # slapindex -b dc=my-domain,dc=com -v indexing id=00000001 indexing id=00000002 indexing id=00000003 indexing id=00000004 [ 略 ] 属性名.bdb cn.bdb ou.bdb xx.bdb yy.bdb 35
インデックスの効果 インデックス検索で 6.7 倍の性能改善 インデックスを作成 1906.5 回 / 秒 DB_CONFIG 適用のみ 282.917 回 / 秒 結果は 今回今回の検証環境検証環境でのでの値ですです 性能改善性能改善のインパクトインパクトは 検索対象検索対象となるとなるエントリエントリ数にもにも依存依存しますします 36
6.7 倍 UP! インデックスで 6.7 倍インデックスを活用しよう! 37
ログファイル を知っておこう! 38
OpenLDAP のログファイル 今回の対象 ディレクティブ 役割 loglevel syslog に記録するログ 出力する内容 ( 出力量 ) を調整できる logfile loglevel で指定した内容を syslog に加え 指定するファイルへも重複して出力させる overlay accesslog OpenLDAP への操作ログを バックエンドデータベースへ蓄積する overlay auditlog 全ての変更情報を 指定するファイルに記録する DB_CONFIG ファイル set_lg_max Berkeley DB のトランザクションログファイル 39
ログレベルの検討 loglevel に指定する値 Level Level Level 説明 (10 進数 ) (16 進数 ) ( 文字列 ) -1 any enable all debugging 0 0x0 no debugging 1 0x1 trace trace function calls 2 0x2 packet debug packet handling 4 0x4 args heavy trace debugging (function args) 8 0x8 conns connection management 16 0x10 BER print out packets sent and received 32 0x20 filter search filter processing 40
ログレベルの検討 loglevel に指定する値 Level Level Level 説明 (10 進数 ) (16 進数 ) ( 文字列 ) 64 0x40 config configuration file processing 128 0x80 ACL access control list processing 256 0x100 stats stats log connections/operations/results 512 0x200 stats2 stats log entries sent 1024 0x400 shell print communication with shell backends 2048 0x800 parse entry parsing 16384 0x4000 sync LDAPSync replication 32768 0x8000 none only messages that get logged whatever log level is set 41
syslogd で その先へ! 42
OS から見る slapd の仕事ぶり インデックス作成後も slapd は頑張ってる しかし CPU 利用率のiowaitの割合からは ディスクIOを待っている時間も長いことがわかる 検索処理でも 管理者の為に ログを出しています 100% 80% インデックス利用時利用時の仕事量 60% 40% iowaが 6~7% 程度で推移 slapd ディスク IO は コンピュータの処理の中で最も遅い処理 20% 0% 試験時間 idle iowa sys usr 43
syslog の非同期書き込み syslogdがデータの書込み後に ディスクへのフラッシュ (fsync) 処理を行わない 時間がかかるfsyncをスキップし性能を稼ぐ 電源断時には データを失う可能性がある slapd syslogd LOCAL4 writev() fsync() ldap.log 44
syslog 非同期書き込みの設定 OpenLDAP は デフォルトで LOCAL4 ファシリティを用いてログメッセージを送付 syslog 側で LOCAL4 ファシリティログを受け取り非同期で書込む設定 - が必要 # vi /etc/syslog.conf [ 略 ] local4.* -/var/log/ldap.log [ 略 ] syslog 再起動 45
syslog 非同期書き込みの効果 インデックス + 非同期 IO 20515.255 回 / 秒 インデックスを作成 1906.5 回 / 秒 DB_CONFIG 適用のみ 282.917 回 / 秒 結果は 今回今回の検証環境検証環境でのでの値ですです 性能改善性能改善のインパクトインパクトは ディスク IO 性能 ログログ出力量出力量にもにも依存依存しますします 46
10 倍 UP! 非同期 IO で 10 倍 syslogdの非同期書き込みを検討しよう! 47
エントリキャッシュ を知っておこう! 48
back-bdb での エントリ検索 最初に 検索ベーストップの ID を取得 続いて 検索ベーストップのエントリを取得 繰り返し 同じ要領で検索スコープ内のDN と エントリを取得 ldapsearch -x -b ou=xx,dc=yy -s sub * dn ID dn2id.bdb 検索ベーストップから スコープ内のエントリ分繰り返し client entries slapd ID entry id2entry.bdb ou=xx,dc=yy 49
エントリデータのキャッシュ クライアントに回答する前に decode が必要 2~6 までの処理の繰り返し ldapsearch -x -b ou=xx,dc=yy -s sub * 1 2dn 3ID dn2id.bdb 検索ベーストップから スコープ内のエントリ分繰り返し client 7entries slapd 4ID 5entry id2entry.bdb ou=xx,dc=yy エントリキャッシュ 6decode ( ) ( ) Berkely DBに格納されていた形式から クライアントへ転送できる形式への変換処理を 各エントリ毎に行う 50
DB_CONFIG set_cachesize DB_CONFIG に設定するキャッシュは Berkeley DB が利用するバッファサイズ Berkeley DB による ディスクからのキャッシュ slapd dn2id.bdb xx.bdb id2entry.bdb yy.bdb set_cachesize で指定するサイズ Berkeley DB db.003 51
エントリキャッシュ で その先へ! 52
エントリキャッシュ 一度 Berkeley DB から取得 デコードした エントリを OpenLDAP 側でキャッシュ 2 回目以降 slapd はエントリキャッシュを利用して DB アクセス デコード処理を省略 エントリキャッシュ 初回きり id2entry.bdb slapd db.003 AVL ツリー構造 B ツリー構造 53
cachesize ディレクティブ バックエンドに Berkerey DB を利用している 場合に 利用可能なディレクティブ Berkeley DB から取得済み デコード済みエントリを slapd 側でキャッシュする最大数を指定 bdb_id2entry() エントリ id2entry.bdb slapd エントリキャッシュ entry_decode() db.003 Berkeley DB 54
cachesize ディレクティブ デフォルトは 1000 ベストは エントリ数と同じ数だけ設定 エントリキャッシュ id2entry.bdb 1:1 Berkeley DB slapd 55
ID リストキャッシュ を知っておこう! 56
インデックスを利用した検索 インデックスファイルを利用して ピンポイ ントで必要なエントリを読む為の ID を取得 bdb_key_read() ID または IDのリスト xx.bdb dn2id.bdb slapd bdb_id2entry() エントリ id2entry.bdb 必要な回数回数だけにだけに絞り データベースへアクセス db.003 Berkeley DB 57
キーでヒットした ID のキャッシュ インデックスファイルから取得した ID を OpenLDAP 側でキャッシュすることが可能 bdb_key_read() ID ID リスト ID リストキャッシュ xx.bdb dn2id.bdb slapd bdb_id2entry() エントリ 2 回目以降の ID 取得のデータベースアクセスを省略 db.003 id2entry.bdb Berkeley DB 58
ID リストキャッシュ で その先へ! 59
ID リストキャッシュ バックエンドに Berkerey DB を利用している 場合に設定可能 IDL(ID List) キャッシュに格納する ID の最大数を指定するディレクティブ slapd bdb_idl_cache_get() IDL キャッシュ bdb_idl_cache_put() ( 初回きり ) xx.bdb (2 回目以降 ) AVL ツリー構造 db.003 B ツリー構造 60
idlcachesize ディレクティブ デフォルトは 0 IDL キャッシュは使わない BDB を利用している場合の設定目安 Back-bdb は 1 エントリと同数 Back-bdb は 1 エントリにつき 1 ID の関係 HDB を利用している場合の設定目安 Back-hdb は ID を多く使う為 エントリ数の 3 倍 61
OpenLDAP 側でのキャッシュ効果 インデックス + 非同期 IO + キャッシュ 22472.208 回 / 秒 インデックス + 非同期 IO 20515.255 回 / 秒 インデックス作成 1906.5 回 / 秒 DB_CONFIG 適用のみ 282.917 回 / 秒 結果は 今回今回の検証環境検証環境でのでの値ですです 性能改善性能改善のインパクトインパクトは 参照系処理参照系処理 更新系処理更新系処理の割合割合にもにも依存依存しますします 62
10% UP! キャッシュで 10% OpenLDAP 側でのキャッシュ技術を活用しよう! 63
スレッド処理 を知っておこう! 64
OpenLDAP が生成するスレッド OpenLDAP は マルチスレッドで動作 slapd は リスナーと ワーカーの 2 タイプの スレッドを生成する リスナースレッド 1 ワーカースレッド n slapd (n) 65
スレッドが生成されるタイミング slapd 起動時 slapd プロセスは リスナースレッドを生成 LDAP クライアントからのアクセス時 リスナーに加え 必要なワーカーをプール開始 66
concurrency ディレクティブ スレッドライブラリに 目標とする並行度数を指定 pthread_setconcurrency() を利用 システムリソース消費の抑制などを目的として アプリケーション側からスレッドの並行度数を絞ることが可能 デフォルトは設定なし スレッドライブラリへの並行度数の制限なし Gnu C library 67
tool-threads ディレクティブ slapd を ツールモードにて実行する場合の最大スレッド数を指定する デフォルト値は 1 設定値は システムの持つ CPU の総数以下に slapd -T a や slapadd など slapadd のほか slapcat slapindex slaptest slapacl など slapd slapadd シンボリックリンクよりツールモードで実行 68
ワーカースレッド で その先へ! 69
threads ディレクティブ ワーカースレッドの最大数 (n) を設定する slapd プロセスは 最大 n+1 のスレッドを生成 リスナースレッド 1 ワーカーとなるスレッド n slapd (n) 70
threads ディレクティブ (2) デフォルトは 16 2 未満では OpenLDAP サーバの起動不可 デフォルト値の 2 倍 (16*2=32) より大きい設定では 起動時に警告メッセージ 33 以上が 常に良くないというわけではない 設定可能な最大値は 1024 ( 最大 1024) 71
threads ディレクティブの設定 OpenLDAP コミュニティからの 設定目安 参照系の処理が多い場合 ハードウェアのCPUコア数 4 または 8 最大でも 16 程度 更新系の処理が多い場合 16 よりも もっと多く (16 以上 ) 72
threads ディレクティブの設定 (2) 処理内容や環境によって 適正値は異なる デフォルト値のスタートも間違いではない まずは コミュニティの情報を信じても良い 可能であれば 実機での確認を! 73
スレッド数を調整した効果 今回インデックス + 非同期 IO + キャッシュインデックス + 非同期 IO 26075.061 回 / 秒 22472.208 回 / 秒 20515.255 回 / 秒 インデックス作成 DB_CONFIG 適用のみ 1906.5 回 / 秒 282.917 回 / 秒 結果は 今回今回の検証環境検証環境でのでの値ですです 性能改善性能改善のインパクトインパクトは 参照系処理参照系処理 更新系処理更新系処理の割合割合や CPUの特長特長にもにも依存依存しますします 74
16% UP! スレッド数で 16% 状況に応じワーカースレッド数を調整しよう! 75
もう一歩一歩 そのその先へ 76
様々な要因で 性能は変化 サイジングを! サービス要件の把握 サイジング 性能検証 ( ベンチマーク ) 1. システムのサービス要件の把握 2. ハード ミドルウェア特性を考慮したサイジング 3. できる限り本番環境に近い環境での確認 77
ご清聴清聴 ありがとうございました 78