Last active
June 17, 2021 23:51
-
-
Save hotta/21758f9b479bb271e7b663a98cb02205 to your computer and use it in GitHub Desktop.
Pgpool 通常稼働のため、Pgpool を定期的にポーリングしてDB接続を維持する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/php | |
<?php | |
// | |
// pg-persist.php | |
// pgpool ではクライアントからの接続がない場合は障害時でもフェイルオーバー | |
// しないため、DB接続を維持するため(だけ)のスクリプトを準備した。 | |
// cron から起動する場合はバックグラウンド起動とすること。 | |
// テスト側でのみ必要。 | |
// | |
// https://www.php.net/manual/ja/ref.pdo-pgsql.connection.php | |
// https://www.php.net/manual/ja/pdo.connections.php | |
// | |
declare(ticks = 1); // シグナルハンドラ利用時に必要 | |
class MyClass { | |
const HOST = "pgpool-vip"; | |
const PORT = "9999"; | |
const DBNAME = "postgres"; | |
const DBUSER = "vagrant"; | |
const DBPASS = ""; | |
const INTERVAL = 10; // 単位:秒 | |
const MAILTO = "mhotta@example.com"; // メール通知先 | |
const SQL = "SELECT COUNT(*) FROM pg_user"; // 値を1つだけ返す SQL を指定する | |
private $dbh = null; | |
private $PIDFILE = null; | |
private $in_cron = false; | |
// ------------------- | |
// 初期化 | |
// ------------------- | |
public function __construct() { | |
if (! isset($_SERVER['TERM']) && ! isset($_SERVER['VSCODE_AGENT_FOLDER'])) { | |
$this->in_cron = true; | |
} | |
$PIDDIR = getenv("HOME") . "/.pg-persist"; | |
$this->PIDFILE = "$PIDDIR/pg-persist.pid"; | |
if (! is_dir($PIDDIR)) { | |
mkdir($PIDDIR); | |
} | |
if (file_exists($this->PIDFILE)) { | |
$pid = file_get_contents($this->PIDFILE); // PID 読み込み | |
if (! $this->in_cron) { | |
printf("Another process seems to be running: pid = %s\n", $pid); | |
} | |
exit(0); | |
} | |
file_put_contents($this->PIDFILE, getmypid()); | |
pcntl_signal(SIGTERM, [ $this, "sig_handler"] ); | |
pcntl_signal(SIGINT, [ $this, "sig_handler"] ); | |
} // __construct() | |
// ------------------- | |
// シグナルハンドラ | |
// ------------------- | |
public function sig_handler($signo) { | |
switch ($signo) { | |
case SIGTERM: | |
case SIGINT: | |
unlink($this->PIDFILE); // PID ファイル削除 | |
exit(0); | |
} | |
} | |
// ------------------- | |
// メール送信&終了 | |
// ------------------- | |
private function sendmail($msg = "") { | |
if (! $this->in_cron) { | |
printf("%s\n", $msg); | |
} else { | |
mail(self::MAILTO, "pg-persist.php", $msg); | |
} | |
exit(-1); | |
} // sendmail() | |
// ------------------- | |
// DB接続 | |
// ------------------- | |
private function connect() { | |
$dsn = sprintf("pgsql:host=%s;port=%s;dbname=%s", | |
self::HOST, self::PORT, self::DBNAME); | |
try { | |
$this->dbh = new PDO($dsn, self::DBUSER, self::DBPASS, [ | |
PDO::ATTR_PERSISTENT => true // 持続的接続 | |
]); | |
} catch (PDOException $e) { | |
// print_r($e); | |
unlink($this->PIDFILE); // PID ファイル削除 | |
$msg = $e->errorInfo[2]; | |
$this->sendmail($msg); | |
} | |
} // connect() | |
// ------------------- | |
// DBポーリング | |
// ------------------- | |
private function poll() { | |
if (! $this->dbh) { // pgpoolから切断された | |
$this->connect(); | |
} | |
try { | |
foreach ($this->dbh->query(self::SQL) as $row) { | |
if (! $this->in_cron) { | |
print_r($row['0']); | |
} | |
} | |
} catch (PDOException $e) { | |
unlink($PIDFILE); // PID ファイル削除 | |
$this->sendmail("Could not exec to PDO"); | |
} | |
} // poll() | |
// ------------------- | |
// メインループ | |
// ------------------- | |
public function run() { | |
while (1) { | |
$this->poll(); | |
sleep(self::INTERVAL); | |
} | |
} // run() | |
} // class MyClass | |
$x = new MyClass(); | |
$x->run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment