著者は、Apache Software FoundationをWrite for DOnationsプログラムの一環として寄付の対象に選びました。
はじめに
A hit counter is an application that records and indicates the number of visits your web page has received. The counter starts from 1 and is incremented once every time a web page is visited.
訪問を追跡するために、ヒットカウンターアプリケーションにはデータベースの形式が必要です。MySQLなどのディスクベースのデータベース管理システムが機能する場合がありますが、インメモリデータベースは速度、パフォーマンス、スケーラビリティ、シンプリシティ、および使いやすさの面で優れています。これがRedisサーバーの役割です。RedisはデータをコンピューターのRAMに保存し、入出力操作ごとにディスクにアクセスする必要がありません。これによりスループットが大幅に向上します。
サイトの訪問を追跡するには、Redisハッシュマップが必要です。これはキーと値のペアを実装するデータ構造です。ハッシュマップは、キーを値にマッピングするハッシュテーブルを提供します。ユーザーがWebページを訪問すると、公開IPアドレスまたはユーザー名(認証済みユーザーの場合)に基づいてキーを作成し、その後、彼らの合計訪問回数を1の値に初期化します。その後、ユーザーがWebページを再訪問するたびに、IPアドレス/ユーザー名に基づいてRedisハッシュマップから彼らの合計訪問回数を確認し、値を増やします。
このガイドでは、Ubuntu 20.04サーバー上でRedisとPHPを使用してウェブサイトのヒットカウンターを設定します。このガイドのPHPスクリプトは、訪問者の公開IPアドレスを使用して彼らの訪問を追跡します。
前提条件
このガイドに従うには、以下の準備が整っていることを確認してください:
-
Ubuntu 20.04サーバーが、Ubuntu 20.04での初期サーバーセットアップガイドに従って構成されています。
-
sudo
権限を持つ非rootユーザーが必要です。非rootのsudoユーザーを設定するには、Ubuntu 20.04で新しいSudo有効ユーザーを作成する方法[クイックスタート]ガイドに従ってください。 - ApacheとPHP。これらをセットアップするには、Ubuntu 20.04にLinux、Apache、MySQL、PHP(LAMP)スタックをインストールする方法チュートリアルを使用してください。このガイドをテストするにはMySQLデータベースや仮想ホストが不要なので、ステップ2 — MySQLのインストールとステップ4 — ウェブサイトのための仮想ホストの作成をスキップしてください。
-
Redis サーバー。Redis サーバーをインストールしてセキュリティを確保する方法は、Ubuntu 20.04 に Redis をインストールしてセキュリティを確保する方法 [クイックスタート]チュートリアルを参照してください。
ステップ 1 — PHP Redis 拡張機能のインストール
このステップでは、PHP が Redis サーバーと通信できるようにする Redis 拡張機能をインストールします。また、ウェブ訪問を追跡するために Redis ハッシュマップを実装したテストウェブページも作成します。
Redis 拡張機能をインストールする前に、Ubuntu パッケージ情報のインデックスを更新してください。
次に、次のコマンドを実行してphp-redis
をインストールします。この拡張機能は、Redisサーバーのキー値ストアと通信するためのAPIを提供します:
新しい拡張機能を読み込むためにApacheを再起動します:
これで、Redisサーバーと通信するPHP拡張機能をインストールしました。次に、Apache Webサーバーのルートディレクトリにtest.php
ウェブページを作成します。これは、訪問者がブラウザでウェブサイトを訪問したときにリクエストされるサンプルファイルです。裏側では、test.php
ページファイルがRedisサーバーを使用してページの訪問を追跡するhit_counter.php
スクリプトを読み込みます。
実際のシナリオでは、ウェブサイトには数十から数百のウェブページがある可能性があります。このガイドでは、デモンストレーション目的で単一のウェブページを設定します。
ターミナルウィンドウで、nano
を使用してWebサーバーのルートディレクトリ/var/www/html/
に新しいtest.php
ファイルを作成します:
次に、test.php
ファイルに以下の情報を入力します:
<?php
require_once 'hit_counter.php';
?>
<!DOCTYPE html>
<html>
<head>
<title>Sample Test Page</title>
</head>
<body>
<h1>Sample test page</h1>
<p>This is a sample test page.</p>
</body>
</html>
編集が完了したら、ファイルを保存して閉じます。このステップでは、訪問時にhit_counter.php
ファイルを読み込む簡単なHTMLウェブページを作成しました。次に、テストページの訪問を追跡するhit_counter.php
ファイルのコーディングを行います。
ステップ2 — Redisヒットカウンタースクリプトの作成
プロダクション環境で作業する際、再利用可能なPHPファイルを分離するのは非常に一般的です。これにより、コードをコピー&ペーストする代わりに、これらのファイルのロジックをプロジェクトの異なる部分に含めることができます。これにより、ロジックを変更する必要がある場合には、単一のファイルの編集だけで済むため、メンテナンスが容易になります。これにより、多くの時間が節約されます。
このガイドでも同じ戦略を適用します。訪問者の追跡が必要なウェブページで使用できる単一のhit_counter.php
ファイルを作成します。
このファイルでは、php-redis
ライブラリを使用してPHPからRedisサーバーに接続します。次に、Redisハッシュマップを作成して、ウェブサイトへの訪問回数を格納します。訪問者ごとのヒット数を区別するために、Redisのキーとして訪問者の固有のIPアドレスを使用します。
ターミナルウィンドウで、編集用に新しいhit_counter.php
ファイルを開きます:
今作成したhit_counter.php
ファイルを開いて、新しいPHPタグ<?php
を入力します。次に、try {
ブロック内に、以下のコードを入力してローカルのRedisサーバー(ポート6379
)に接続します。Redisサーバーの認証パスワードをEXAMPLE_PASSWORD
で置き換えてください:
<?php
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('EXAMPLE_PASSWORD');
次に、Redisハッシュマップ($siteVisitsMap
)に任意の名前を付けます。このガイドでは、デモンストレーション目的でsiteStats
を使用します。
$siteVisitsMap = 'siteStats';
Redisハッシュマップを定義した後、今度は空のRedisキー($visitorHashKey
)を初期化します。 次に、訪問者のIPアドレスをそれに挿入します。 あなたは、ウェブページを要求する各訪問者を一意に識別するために、$visitorHashKey
変数の値を使用します:
$visitorHashKey = '';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$visitorHashKey = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$visitorHashKey = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$visitorHashKey = $_SERVER['REMOTE_ADDR'];
}
このコードでは、PHPのif
ステートメントを使用して、$_SERVER['HTTP_CLIENT_IP']
、$_SERVER['HTTP_X_FORWARDED_FOR']
、または$_SERVER['REMOTE_ADDR']
変数が入力されているかどうかをチェックして、訪問者のIPアドレスを特定します。
これに続いて、各IPアドレスの合計訪問回数を保存するための$totalVisits
変数を初期化し、値0を割り当てます。 その後、PHPのif (...) {...} else {...}
および$redis->hExists($siteVisitsMap, $visitorHashKey)
ステートメントを使用して、IPアドレスがRedisサーバーにエントリーを持っているかどうかを確認します。
ステートメントif ($redis->hExists($siteVisitsMap, $visitorHashKey)) {...}
を使用して、マップ$siteVisitsMap
に$visitorHashKey
が存在するかどうかを確認します。
Redisサーバーに名前付きIPアドレスのマップとキーが存在する場合は、次のステートメントを使用してそれを取得します。$visitorData = $redis->hMget($siteVisitsMap, array($visitorHashKey));
そして$totalVisits = $visitorData[$visitorHashKey] + 1;
を使用して$totalVisits
変数をインクリメントします。IPアドレスに関連するヒット数データを取得するために$redis->hMget
ステートメントを使用しています。hMget
関数は、Redisサーバーから取得したいキーの配列を受け入れます。この場合、1つのキー($visitorHashKey
)しかありませんが、array($visitorHashKey)
ステートメントを使用してそれを配列に変換する必要があります。
スクリプトがIPアドレスに初めて遭遇した場合は、$totalVisits
変数を1に設定します。最後に、前のif (...) {...} else {...}
ステートメントの結果に応じて、$visitorHashKey
の値を設定するために$redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits);
を使用します。$redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits)
ステートメントは、Redisサーバーに$visitorHashKey
という名前のキーを持つ$siteVisitsMap
ハッシュマップを作成し、その値を$totalVisits
に設定します。
次に、訪問者を歓迎して総訪問数をエコーし、} catch (...) {...}
ブロックを閉じます:
$totalVisits = 0;
if ($redis->hExists($siteVisitsMap, $visitorHashKey)) {
$visitorData = $redis->hMget($siteVisitsMap, array($visitorHashKey));
$totalVisits = $visitorData[$visitorHashKey] + 1;
} else {
$totalVisits = 1;
}
$redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits);
echo "Welcome, you've visited this page " . $totalVisits . " times\n";
} catch (Exception $e) {
echo $e->getMessage();
}
完了したら、/var/www/html/hit_counter.php
ファイルは次のコードに似ている必要があります:
<?php
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('EXAMPLE_PASSWORD');
$siteVisitsMap = 'siteStats';
$visitorHashKey = '';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$visitorHashKey = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$visitorHashKey = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$visitorHashKey = $_SERVER['REMOTE_ADDR'];
}
$totalVisits = 0;
if ($redis->hExists($siteVisitsMap, $visitorHashKey)) {
$visitorData = $redis->hMget($siteVisitsMap, array($visitorHashKey));
$totalVisits = $visitorData[$visitorHashKey] + 1;
} else {
$totalVisits = 1;
}
$redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits);
echo "Welcome, you've visited this page " . $totalVisits . " times\n";
} catch (Exception $e) {
echo $e->getMessage();
}
編集が完了したら、ファイルを保存して閉じてください。これで、hit_counter.php
スクリプトをコーディングしました。次に、Redisハッシュマップで収集したデータからレポートを生成する別のPHPスクリプトを作成します。
ステップ3 — サイト統計レポートスクリプトの作成
Redisハッシュマップにデータを収集した後、その情報をレポートで取得して表現できない場合、それは意味がありません。このステップでは、テストWebページで異なるサイト訪問者とそれらが行った合計訪問回数を示すログレポートを作成します。
ログレポートスクリプトを作成するには、ターミナルウィンドウでnano
を実行し、新しい/var/www/html/log_report.php
ファイルを作成します:
次に、以下の情報をファイルに入力します。Redisサーバーの正しいパスワードでEXAMPLE_PASSWORD
を置き換えてください:
<!DOCTYPE html>
<html>
<head>
<title>Site Visits Report</title>
</head>
<body>
<h1>Site Visits Report</h1>
<table border = '1'>
<tr>
<th>No.</th>
<th>Visitor</th>
<th>Total Visits</th>
</tr>
<?php
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('EXAMPLE_PASSWORD');
$siteVisitsMap = 'siteStats';
$siteStats = $redis->HGETALL($siteVisitsMap);
$i = 1;
foreach ($siteStats as $visitor => $totalVisits) {
echo "<tr>";
echo "<td align = 'left'>" . $i . "." . "</td>";
echo "<td align = 'left'>" . $visitor . "</td>";
echo "<td align = 'right'>" . $totalVisits . "</td>";
echo "</tr>";
$i++;
}
} catch (Exception $e) {
echo $e->getMessage();
}
?>
</table>
</body>
</html>
編集が完了したらファイルを保存して閉じます。上記のスクリプトでは、Redis サーバーに接続し、$redis->HGETALL($siteVisitsMap);
ステートメントを使用してウェブページの訪問ハッシュマップを取得しています。その後、PHPのforeach ($siteStats as $visitor => $totalVisits) {
ステートメントを使用して、訪問者のIPアドレスとサイトへの訪問回数をループして表示しています。RedisのHGETALL
コマンドを使用して、siteVisitsMap
マップからすべてのフィールド(IPアドレス)と値(各IPアドレスごとの合計訪問回数)を取得しています。
今、テストページ、ヒットカウンタースクリプト、およびサイトの統計を確認するためのレポートページがあります。次に、ヒットカウンターの機能をテストし、すべてが正常に動作するかどうかを確認します。
ステップ 4 — Redis ヒットカウンターのテスト
このステップでは、ヒットカウンターのロジック全体をテストします。ウェブブラウザで以下のURLに移動します。 your-server-IP
をサーバーの公開IPアドレスまたはドメイン名に置き換えます。
http://your-server-IP/test.php
異なるデバイスを使用してページを数回更新し、十分な統計情報を生成します。各訪問後、以下の出力が表示されるはずです。
次に、次のURLを訪問して、HTMLテーブルにサイトの訪問レポートが表示されます。
http://your-server-IP/log_report.php
これで、以下の出力と同様のレポートが表示されるはずです。
ヒットカウンターが期待通りに動作しています。
結論
このガイドでは、Ubuntu 20.04サーバー上でRedisとPHPを使用してウェブサイトのヒットカウンターを設定しました。
このガイドのサンプルソースコードからわかるように、Redisはハッシュマップの作成と更新に対してより洗練された方法を提供しています。
このガイドの冒頭で述べたように、リレーショナルデータベース管理システムを使用することもできますが、基礎となるテーブルへのデータの挿入と更新に多くのコードを書く必要があります。また、ディスクベースのデータベースは、サイトが成長するにつれて拡張性の問題が発生する可能性があります。
Redisインメモリデータベースの使用に関する詳細は、以下のガイドを参照してください: