作者选择了Apache软件基金会作为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哈希映射。这是一种实现键值对的数据结构。哈希映射提供了一个哈希表,将键映射到值。一旦用户访问您的网页,您就根据他们的公共IP地址或用户名(对于经过身份验证的用户)创建一个键,然后将他们的总访问次数初始化为值为1。然后,每当用户重新访问您的网页时,您就根据他们的IP地址/用户名从Redis哈希映射中检查他们的总访问量,并增加该值。
在本指南中,您将在Ubuntu 20.04服务器上使用Redis和PHP设置网站点击计数器。本指南中的PHP脚本使用访客的公共IP地址来跟踪他们的访问。
先决条件
要按照本指南操作,请确保具备以下条件:
-
已配置使用Ubuntu 20.04初始服务器设置指南的Ubuntu 20.04服务器。
-
具有
sudo
特权的非root用户。请按照我们的如何在Ubuntu 20.04上创建新的启用sudo的用户[快速入门]指南设置非root sudo用户。 - Apache和PHP。要设置这些,请使用我们的如何在Ubuntu 20.04上安装Linux、Apache、MySQL、PHP(LAMP)堆栈教程。您可以跳过步骤2 —— 安装MySQL和步骤4 —— 为您的网站创建虚拟主机,因为您不需要MySQL数据库或虚拟主机来测试此指南。
-
Redis服务器。阅读我们的如何在Ubuntu 20.04上安装和保护Redis [快速入门]教程,以安装和保护Redis服务器。
步骤1 — 安装PHP Redis扩展
在这一步中,您将安装一个Redis扩展,使PHP能够与Redis服务器通信。您还将创建一个测试网页,该网页实现了Redis哈希映射来跟踪网站访问。
在安装Redis扩展之前,请刷新您的Ubuntu软件包信息索引:
然后,运行以下命令以安装php-redis
。该扩展提供了与Redis服务器键值存储通信的API:
重新启动Apache以加载新的扩展:
您现在已安装了一个与Redis服务器通信的PHP扩展。接下来,您将在Apache Web服务器的根目录下创建一个test.php
网页。这只是一个示例文件,访问者在使用浏览器访问您的网站时会请求它。在幕后,test.php
页面文件会加载一个hit_counter.php
脚本,稍后您将创建该脚本以使用Redis服务器跟踪页面访问。
在实际场景中,您的网站可能有几十甚至上百个网页。对于本指南,您将为演示目的设置一个单独的网页。
在您的终端窗口中,使用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>
编辑完成后保存并关闭文件。在此步骤中,您已经创建了一个简单的HTML网页,在访问时加载了一个hit_counter.php
文件。接下来,您将编写hit_counter.php
文件来跟踪测试页面的访问量。
第二步 —— 创建一个Redis点击计数器脚本
在生产环境中工作时,将可重用的 PHP 文件分离出来是非常常见的做法。这样可以通过包含它们的路径而不是复制粘贴代码来在项目的不同部分实现这些文件中的逻辑。这样做可以更容易地进行维护,因为您只需要在需要更改逻辑的情况下编辑单个文件。这会节省大量时间。
您将在本指南中应用相同的策略。您将创建一个名为hit_counter.php
的单个文件,可以将其包含在需要跟踪访客的任何网页中。
在此文件中,您将使用php-redis
库来从 PHP 连接到 Redis 服务器。然后,您将创建一个 Redis 哈希映射来存储访问者对您的网站的访问次数。您将使用访问者的唯一 IP 地址作为 Redis 键来区分 Redis 服务器中每个访问者的点击次数。
在您的终端窗口中,使用nano
打开一个新的hit_counter.php
文件以进行编辑:
现在创建了hit_counter.php
文件,打开一个新的 PHP 标签<?php
。然后,在一个try {
块中输入以下代码以连接到端口6379
上的本地 Redis 服务器。将EXAMPLE_PASSWORD
替换为 Redis 服务器的身份验证密码:
<?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 地址。
接着,初始化一个 $totalVisits
变量来存储每个 IP 地址的总访问次数,并将其赋值为 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
变量。您正在使用 $redis->hMget
语句获取与 IP 地址关联的点击计数数据。 hMget
函数接受您的映射的名称($siteVisitsMap
)和要从 Redis 服务器检索的密钥数组。在这种情况下,您只有一个密钥($visitorHashKey
),但必须使用语句 array($visitorHashKey)
将其转换为数组。
如果您的脚本首次遇到 IP 地址,请将 $totalVisits
变量设置为 1。最后,使用 $redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits);
根据前面的 if (...) {...} else {...}
语句的结果设置 $visitorHashKey
的值。 $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
脚本。接下来,您将创建另一个 PHP 脚本,用于从收集到的 Redis 哈希映射数据生成报告。
步骤 3 — 创建网站统计报告脚本
在收集了 Redis 哈希映射中的数据之后,如果无法检索和表示信息,则可能毫无意义。在此步骤中,您将创建一个日志报告,显示不同的站点访问者以及他们在测试网页上的总访问量。
要创建日志报告脚本,请在终端窗口上运行 nano
并创建一个新的 /var/www/html/log_report.php
文件:
然后,将以下信息输入到文件中。将 EXAMPLE_PASSWORD
替换为 Redis 服务器的正确密码:
<!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 点击计数器
在此步骤中,您将测试点击计数器的整个逻辑。在您的 Web 浏览器中导航至以下 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数据库的更多信息,请参阅以下指南: