ソケット通信でサーバーの状況を監視する | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

PHP内からあのサービスに接続したいけど、その前に正常に動いているか確認したいってときに、ソケット通信で相手先のサービスの稼動状況を確認できたりします。



PHPでソケット通信してサービスの稼動状況をチェックするサンプル


PHPでソケット通信するためには、ソケット関数fsockopen関数 を利用します。


<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if (@socket_connect($socket, "192.168.0.100", 80)) {
    echo "接続できました";
} else {
    echo socket_strerror(socket_last_error());
}

<?php

$socket = @fsockopen("192.168.0.100", 23, $errno, $errstr, 10);

if ($socket === FALSE) {
    echo $errno . $errstr;
} else {
    echo "接続できました";
}

これはサーバーや特定のポート(例えばHTTPとか)が応答するかどうかのチェックなので、厳密なその上で利用したいサービスやAPI等が正常に応答するかというチェックではありません。

例えば、最初のHTTPのサービスが動いているかどうかは、ポートからの応答があるというのはわかりますが、実際にリクエストを投げてみればHTTPステータスコード500(Internal Server Error)が返ってくる場合もあり、厳密なチェックではありません。


ただ、PINGを飛ばして応答を見るといった簡易的な死活チェックには使えます。

実際に応答が無かった場合などは、


111Connection refused
113No route to host

のような、エラーコードとメッセージを受け取ることもできます。



socket_connect()のタイムアウトの問題


socket_connect() を使った場合で、例えば指定したIPのサーバーがダウンしていたり経路が存在しなかった場合に、激しくタイムアウトまで待たされるという現象が出たりします。

どうもsocket_connect()にはコネクション確立時のタイムアウトが設定できないっぽいです。


socket_set_option()stream_set_timeout() など設定できそうな関数があるんですが、コネクション時のタイムアウトは設定できないっぽい。(そもそもstream_set_timeout()はストリームに対する操作のため、socket_connect()のリソースには適用できない)


PEARのNet_Socketを使っても同様の問題(内部的にはsocket_connect()を使っているので当たり前ですが)が出ますし、オプションも見当たらないのでfsockopen()を使った方が無難なのかな、と思ったりします。


$socket = @fsockopen("192.168.0.100", 23, $errno, $errstr, 10);

のように、第5引数でコネクション時のタイムアウト(上記の場合は10秒)を設定できますし。