apache mod_dbd にて mysql に接続

mod でつなぐ mysql。ということで、mysql に接続するモジュールを作って、先般インストールした apache で動かしてみる。

ワークディレクトリにて、以下のコマンドを実行し、テンプレを作る。

$ apxs2 -n dbd_test -g

mod_dbd_test.cを以下のような感じに修正した。q4m のキューテーブルにデータを突っ込むことを想定したテストプログラムだ。

#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
#include "apr_lib.h"
#include "apr_strings.h"
#include "apr_dbd.h"
#include "mod_dbd.h"


/* The sample content handler */
static int dbd_test_handler(request_rec *r)
{
  if (strcmp(r->handler, "dbd_test")) {
    return DECLINED;
  }
  r->content_type = "text/html";
    
  if (r->header_only)
    return OK;
  
  ap_rputs("<html><head><title>The sample page from mod_dbd_test.c</title><head><body>\n", r);

  ap_dbd_t *dbd = ap_dbd_acquire(r);
  apr_dbd_results_t *res = NULL;
  apr_dbd_row_t *row = NULL;
  
  if(dbd == NULL) {
    ap_rputs("Failed to aqcuire DBD handler in mod_dbd_test.c<br/>\n", r);
    return OK;
  }
  ap_rputs("DBD connection acquired in mod_dbd_test.c<br/>\n", r);
  
  if(dbd->driver == NULL) {
    ap_rputs("DBD driver is NULL in mod_dbd_test.c<br/>\n", r);
    return OK;
  }
  ap_rprintf(r, "DBD connection driver name is %s<br/>\n", apr_dbd_name(dbd->driver));

  const char *statement = "INSERT into q4m_t values('');";
  int rv = 0;
  int nrows;

  rv = apr_dbd_query(dbd->driver, dbd->handle, &nrows, statement);

  ap_rputs("</body></html>", r);

  return OK;
}

static void dbd_test_register_hooks(apr_pool_t *p)
{
  ap_hook_handler(dbd_test_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA dbd_test_module = {
  STANDARD20_MODULE_STUFF, 
  NULL,                  /* create per-dir    config structures */
  NULL,                  /* merge  per-dir    config structures */
  NULL,                  /* create per-server config structures */
  NULL,                  /* merge  per-server config structures */
  NULL,                  /* table of config file commands       */
  dbd_test_register_hooks  /* register hooks                      */
};

んで、以下のコマンドでインストール。

# apxs2 -i -a -c mod_dbd_test.c

/usr/local/apache2/conf/httpd.conf に以下を追加。

LoadModule dbd_test_module /usr/lib/apache2/modules/mod_dbd_test.so
<location /dbd_test>
SetHandler dbd_test
</Location>

DBDriver mysql
DBDParams host=localhost,user=root,pass=mysql,dbname=test,sock=/tmp/mysql.sock
DBDPersist ON
DBDKeep 500
DBDMax 500
DBDMin 200
DBDExptime 600

apache を再起動

# /usr/local/apache2/bin/apachectl restart

http://(サーバ機へのURL)/dbd_test
にて接続。あっさり繋がる。

mysql に接続し、

mysql> select count(*) from q4m_t;
+----------+
| count(*) |
+----------+
|   528858 | 
+----------+
1 row in set (0.00 sec)

実行するたびにキューにデータが挿入されていくのを確認。これはあまりはまるところが無くあっさり動いた。

負荷テスト。

$ httperf --server=localhost --uri=/dbd_test --num-conns=30000 --num-calls=1 --rate=500
httperf --client=0/1 --server=localhost --port=80 --uri=/dbd_test --rate=500 --send-buffer=4096 --recv-buffer=16384 --num-conns=30000 --num-calls=1
httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
httperf: connection failed with unexpected error 99
Maximum connect burst length: 16

Total: connections 29569 requests 29365 replies 29365 test-duration 62.209 s

Connection rate: 475.3 conn/s (2.1 ms/conn, <=1022 concurrent connections)
Connection time [ms]: min 0.5 avg 185.1 max 6203.2 median 12.5 stddev 614.7
Connection time [ms]: connect 91.2
Connection length [replies/conn]: 1.000

Request rate: 472.0 req/s (2.1 ms/req)
Request size [B]: 68.0

Reply rate [replies/s]: min 299.0 avg 487.3 max 615.1 stddev 77.5 (12 samples)
Reply time [ms]: response 93.9 transfer 0.0
Reply size [B]: header 138.0 content 182.0 footer 0.0 (total 320.0)
Reply status: 1xx=0 2xx=29365 3xx=0 4xx=0 5xx=0

CPU time [s]: user 11.12 system 47.98 (user 17.9% system 77.1% total 95.0%)
Net I/O: 179.0 KB/s (1.5*10^6 bps)

Errors: total 635 client-timo 0 socket-timo 0 connrefused 0 connreset 0
Errors: fd-unavail 431 addrunavail 0 ftab-full 0 other 204

--rate をいじりながら何度か実行してみたが、今の設定では、500tps くらいしか出ないみたい。多分プールの設定をちゃんとしたらもうちょいいい数字が出るのじゃないかなあ・・・。(と期待)*1


てか、「httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
httperf」この辺が先決か・・・。*2

*1:siege で計測したら、1000 tps くらいまでは出た

*2:apache じゃなくて、httperf が吐いてるのか?