開発元サイトより抜粋
$ wget http://pgfoundry.org/frs/download.php/225/pgpool-2.5.2.tar.gz $ tar xvfz pgpool-2.5.2.tar.gz $ cd pgpool-2.5.2 $ ./configure $ make $ su # make install
以下にインストールされました。
/usr/local/bin/pgpool /usr/local/etc/pgpool.conf.sample
インストール先を変更するには、以下のように指定する。
configure --prefix=path
$ wget http://pgfoundry.org/frs/download.php/500/pgpool-2.6-5.i686.rpm # rpm -ivh pgpool-2.6-5.i686.rpm
# service pgpool start
# service pgpool stop
# service pgpool restart
# vi /etc/rc.d/init.d/pgpool
# chmod 755 /etc/rc.d/init.d/pgpool # chkconfig --add pgpool # chkconfig pgpool on
$ cd /usr/local/src/postgresql-7.3.4/src/test/regress $ make all $ ./pg_regress --schedule=parallel_schedule --port=9999
Playing with benchmarking
Here is a brief explanation how to play with benchmarking using pgbench/PHP/ab.
Initialize the pgbench database.
$ su - postgres $ createdb test $ pgbench -i test $ pgbench test
<?php ini_set("track_errors", "1"); define_syslog_variables(); $con = pg_connect("dbname=test user=postgres port=9999"); if ($con == FALSE) { syslog(LOG_ERR, "could not connect $php_errormsg"); trigger_error("Could not connect to DB", E_USER_ERROR); exit(1); } $aid = rand(1,10000); pg_query($con, "SELECT * FROM accounts WHERE aid = $aid"); pg_close($con); ?>
run ab.
$ /usr/local/apache/bin/ab -c 100 -n 1000 "http://localhost/bench.php"
pgpoolはpg_hba.conf設定ファイルには影響されない。TCP/IPによるネットワーク接続を受け付ける設定にすると、基本的に無条件でアクセスを許可してしまう。
よって、pgpoolで使用するポートをiptablesでローカルIPからのみアクセス許可しておく。
例:
# iptables -A INPUT -s 192.168.0.0/24 -p tcp --dport 5433 -j ACCEPT # iptables -A INPUT -p tcp --dport 5433 -j DROP # service iptables save # service iptables restart
RedHat系ならば
# vi /etc/sysconfig/iptables -A Firewall-1-INPUT -s 192.168.0.0/24 -p tcp -m state --state NEW -m tcp --dport 5433 -j ACCEPT -A Firewall-1-INPUT -p tcp --dport 5433 -j DROP # service iptables restart
pg_poolに接続後、「show pool_status;」コマンドで行う。
以下のような構成の場合。
「pgpool.conf.sample」を「pgpool.conf」にコピーして、設定を行う。
項目名 | デフォルト | 説明 |
num_init_children | 32 | preforkするpgpoolのサーバプロセスの数 |
max_pool | 4 | 最大コネクション数。[ユーザ名:データベー ス名]のペアの種類の数だけをmax_poolに指定すると良い |
# cp /usr/local/etc/pgpool.conf.sample /usr/local/etc/pgpool.conf # vi /usr/local/etc/pgpool.conf/usr/local/etc/pgpool.conf(デフォルトから変更点のみ記述)
listen_addresses = '*' port = 5433 backend_host_name = 'example.com' backend_port = 5432 secondary_backend_host_name = 'b.example.com' secondary_backend_port = 5432 replication_mode = true health_check_period = 30 health_check_user = 'postgres'
# su - # service pgpool stop # service postgresql stop
# su - # service postgresql stop
$ su - postgres $ cd /var/lib/pgsql $ rsync -avz -e ssh example.com:/var/lib/pgsql/data .
# su - # service postgresql start
# su - # service postgresql start # service pgpool start
$ su - postgres $ psql -h example.com -U apache -p 5432 scott $ psql -h b.example.com -U apache -p 5432 scott $ psql -h b.example.com -U apache -p 5433 scott
insert into DEPT values(50,'dept1','loc1'); INSERT 3218347 1OKのようだ。
select * from DEPT where deptno = 50; deptno | dname | loc --------+-------+------ 50 | dept1 | loc1正常に追加できたのを確認。
$ psql -h example.com -U apache -p 5432 scott select * from DEPT where deptno = 50; $ psql -h b.example.com -U apache -p 5432 scott select * from DEPT where deptno = 50;正常に追加されている。
※DB名「php_session」でセッション専用DBを定義している場合
# su - # vi /etc/php.ini
session.save_handler = pgsql extension=session_pgsql.so session_pgsql.db="host=localhost user=apache password=パスワード dbname=php_session port=5433"
# service httpd restart
一時的にセカンダリを止めてみる。
# service postgresql stop
レコードを追加してみる。
$ psql -h b.example.com -U apache -p 5433 scott insert into DEPT values(60,'dept2','loc2'); INSERT 3218354 1
追加成功。
現在の状態を確認
$ show pool_status; replication_mode | 1 | non 0 if operating in replication mode current_backend_host_name | example.com| current master host name current_backend_port | 5432 | current master port # replication_enabled | 0 | non 0 if actually operating in replication mode
マスタのみ稼働状態になっている事がわかる。
「replication_mode=1」で、「replication_enabled=0」なので「縮退運転中」とわかる。
# service pgpool stop # service postgresql stop
# service postgresql stop
$ su - postgres $ cd /var/lib/pgsql $ rsync -avz -e ssh example.com:/var/lib/pgsql/data .
# su - # service postgresql start
# su - # service postgresql start # service pgpool start
$ su - postgres scott=> show pool_status; replication_enabled | 1 | non 0 if actually operating in replication mode「replication_enabled=1」となり、レプリケーションモードで復旧した。
Memo/PHP/PEAR/session_pgsqlと併用すると、高負荷時に切断されなくなり
コネクションを使い果たし、新規接続ができなくなるようだ。
その場合、pgpoolとhttpdを再起動しなければいけない。
よって、session_pgsqlが使用する「php_session」DBをpgpool経由で接続せずに、直接DBに接続すれば良い。 ただし、障害発生時には、同期を取る必要があり、その時に片方のセッションデータが消失する。
/usr/local/bin/pgpool -d -f /usr/local/etc/pgpool.conf -n 2>&1 | logger -t pgpool -p local0.info
「replication_stop_on_mismatch = true」だと、不意に縮退モードに入ってしまう。
おそらくだが、insert時にCURRENT_TIMESTAMPを使うと内部時計の微妙な誤差が記録され、それを含む行をSELECTする時に不一致と見なされてしまうのではないか。
以下のように、毎時に時刻合わせをしても発生した。
20 0 * * * (/usr/sbin/ntpdate ntp.ring.gr.jp ; /sbin/hwclock --systohc) > /dev/null 2>&1
「now」や「CURRENT_TIMESTAMP」等時刻関数は頻繁に使うので、このオプションはfalseの方がよさそうである。
以下のように、ロードバランシングモード=trueの場合、片方のDBにのみselect文を発行する事で速度向上を図っている。
/usr/local/etc/pgpool.conf
load_balance_mode=true
しかし、シーケンス文はselectで更新されるため、マスタとセカンダリの間に不整合が生じる。
× select nextval('シーケンス名'); × select setval('シーケンス名', 更新値);
よって、シーケンスを使う場合は、load_balance_modeは使えない。
pgpool公式サイトより引用:
たとえば乱数やトランザクションID,OID,SERIAL,シーケンス,CURRENT_TIMETSTAMP
OK | ab -n 100 -c 100 http://b.example.com/~vod/pg_test.php |
NG | ab -n 1000 -c 100 http://b.example.com/~vod/pg_test.php |
<?php $conn = pg_connect ("host=localhost dbname=scott user=apache password=apache123 port=5433"); if (!$conn) { echo "エラーが発生しました。\n"; exit; } $result = pg_exec ($conn, "select * from EMP where JOB = 'SALESMAN'"); if (!$result) { echo "エラーが発生しました。\n"; exit; } echo "row count:" . pg_num_rows($result) . "\n"; ?>
JMeterやabでのテスト中に接続できなくなる。
再現性あり。
pg_pconnect()もコネクションプーリングを行うので、やはり2重に使うのは良くないのかもしれない。
pg_query(): Query failed: kind mismatch between backendsserver closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request.
SELECT時にマスタとセカンダリの結果が違うと発生します。
違ったら、強制的に縮退モードに入るオプションもあります。
(デフォルトはそのクエリが失敗するのみ)
# vi /usr/local/etc/pgpool.conf replication_stop_on_mismatch = true
デメリットの項目にもあるが、コネクションがプールされる事によって、切断されなくなる。
よって、「create temp table」や「create temp sequence」等の一時表が削除されなくなる。
明示的に「drop table」や「drop sequence」を行わないと、「既にテーブルは存在します。」等のエラーが出る事になる。
概ね問題なし。劇的な性能向上はないが、速度低下もない。
テスト対象ページではPCのスペック不足でCPU負荷がネックとなり、コネクションプーリングの速度効果は確認できなかった。
pgpoolのオーバーヘッドは僅かなようなので、問題ないレベルだった。
注意点として、pgpool+pg_pconnect()だと、途中でpgpoolに接続できなくなった。
よって、利用する際にはpgpool+pg_connect()が良いと思われる。
RedHat ES3はPostgreSQL-7.3.xなので負荷分散(SELECT文のみ)の効果は得られない。
7.4にバージョンアップした際は試してみると良いかもしれない。
CPU | VIA Eden (600MHz) EBGA |
---|---|
FSB | 133MHz |
MEM | 256MB |
HDD | 40GB |
OS | Red Hat Linux release 9 (Shrike) |
---|---|
httpd | httpd-2.0.40-21.11 |
php | PHP 4.3.3 (cgi) |
PostgreSQL | 7.3.4 port=5432 |
pgpool | 2.5.2 port=5433 |
session_pgsql | 0.6.1 |
OS | Fedora Core release 1 (Yarrow) |
---|---|
PostgreSQL | 7.3.4 port=5432 |
スレッド数 | Ramp-Up(秒) | ループ回数 |
10 | 5 | 10 |
偏差(ミリ秒) | 遅延時間オフセット定数(ミリ秒) |
2000 | 5000 |
1秒あたりのリクエスト処理数 | グラフ | |
pg_connect()のみ | 1.3 | File not found: "normal_pg_connect.png" at page "Memo/PostgreSQL/pgpool"[添付] |
pg_pconnect()のみ | 1.5 | File not found: "normal_pg_pconnect.png" at page "Memo/PostgreSQL/pgpool"[添付] |
pgpool+pg_connect() | 1.5 | File not found: "pgpool_pg_connect.png" at page "Memo/PostgreSQL/pgpool"[添付] |
pgpool+pg_pconnect() | 測定不能 pgpoolを再起動しても、96%で停止。 | File not found: "pgpool_pg_pconnect_ng.png" at page "Memo/PostgreSQL/pgpool"[添付] |