如何在Ubuntu20.04上使用Redis和PHP设置网站点击计数器
作为 Write for DOnations 计划的一部分,作者选择了 Apache Software Foundation 来接受捐赠。
介绍
命中计数器是一种应用程序,用于记录并指示您的网页已收到的访问次数。 计数器从 1 开始,每次访问网页时递增一次。
为了跟踪访问,命中计数器应用程序需要一种数据库形式。 虽然像 MySQL 这样的基于磁盘的数据库管理系统可以工作,但内存数据库在速度、性能、可扩展性、简单性和易用性方面更好。 这就是 Redis 服务器发挥作用的地方。 Redis 将数据存储在计算机的 RAM 中,而不是每次执行输入/输出操作时都敲击磁盘。 这显着增加了吞吐量。
要跟踪您的站点访问,您需要一个 Redis 哈希图。 这是一个实现键值对的数据结构。 哈希映射提供了将键映射到值的哈希表。 一旦用户访问您的网页,您将根据他们的公共 IP 地址或用户名(对于经过身份验证的用户)创建一个密钥,然后将他们的总访问次数初始化为 值 为 1。 然后,每次用户重新访问您的网页时,您都会根据他们的 IP 地址/用户名从 Redis 哈希映射中检查他们的总访问量并增加该值。
在本指南中,您将在 Ubuntu 20.04 服务器上使用 Redis 和 PHP 设置网站点击计数器。 本指南中的 PHP 脚本使用访问者的公共 IP 地址来跟踪他们的访问。
先决条件
要遵循本指南,请确保您具备以下条件:
- 使用带有 Ubuntu 20.04 指南的 Initial Server Setup 配置的 Ubuntu 20.04 服务器。
- 具有
sudo权限的非 root 用户。 按照我们的 如何在 Ubuntu 20.04 [快速入门] 指南上创建启用 Sudo 的新用户来设置非 root sudo 用户。 - 阿帕奇和 PHP。 要设置这些,请使用我们的 如何在 Ubuntu 20.04 教程上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈。 您可以跳过 第 2 步 — 安装 MySQL 和 第 4 步 — 为您的网站创建虚拟主机,因为您不需要 MySQL 数据库或虚拟主机来测试本指南。
- Redis 服务器。 阅读我们的 如何在 Ubuntu 20.04 [快速入门] 上安装和保护 Redis 教程以安装和保护 Redis 服务器。
第 1 步 — 安装 PHP Redis 扩展
在此步骤中,您将安装一个允许 PHP 与 Redis 服务器对话的 Redis 扩展。 您还将创建一个测试网页,该网页实现了 Redis 哈希映射来跟踪 Web 访问。
在安装 Redis 扩展之前,刷新你的 Ubuntu 包信息索引:
sudo apt update
然后,运行以下命令安装 php-redis。 该扩展提供了一个 API 用于与 Redis 服务器键值存储进行通信:
sudo apt install -y php-redis
重新启动 Apache 以加载新的扩展:
sudo systemctl restart apache2
您现在已经安装了一个与您的 Redis 服务器对话的 PHP 扩展。 接下来,您将在 Apache 网络服务器的根目录下创建一个 test.php 网页。 这只是访问者使用浏览器访问您的网站时请求的示例文件。 在后台,test.php 页面文件加载了一个 hit_counter.php 脚本,您稍后将创建该脚本以使用 Redis 服务器跟踪页面访问。
在现实生活中,您的网站可能有数十甚至数百个网页。 对于本指南,您将设置一个网页用于演示目的。
在您的终端窗口中,使用 nano 在您的网络服务器 /var/www/html/ 的根目录下创建一个新的 test.php 文件:
sudo nano /var/www/html/test.php
然后,在 test.php 文件中输入以下信息:
/var/www/html/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 文件以跟踪测试页面访问。
第 2 步 — 创建 Redis 命中计数器脚本
在生产环境中工作时,分离可重用的 PHP 文件是非常常规的做法。 这允许您通过包含它们的路径而不是复制粘贴代码来在项目的不同部分实现这些文件中的逻辑。 这使得维护更容易,因为您只需要编辑一个文件以防您需要更改逻辑。 这可以为您节省大量时间。
您将在本指南中应用相同的策略。 您将创建一个 hit_counter.php 文件,您可以将其包含在任何需要访问者跟踪的网页上。
在此文件中,您将使用 php-redis 库从 PHP 连接到 Redis 服务器。 然后,您将创建一个 Redis 哈希映射来存储访问者对您网站的访问次数。 您将使用访问者的唯一 IP 地址作为 Redis 键来区分每个访问者在 Redis 服务器中的点击数。
在您的终端窗口中,使用 nano 打开一个新的 hit_counter.php 文件以进行编辑:
sudo nano /var/www/html/hit_counter.php
现在创建了 hit_counter.php 文件,打开一个新的 PHP 标签 <?php。 然后,在 try { 块中输入以下代码以连接到端口 6379 上的本地 Redis 服务器。 将 EXAMPLE_PASSWORD 替换为 Redis 服务器的认证密码:
/var/www/html/hit_counter.php
<?php
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('EXAMPLE_PASSWORD');
接下来,为 Redis 哈希映射 ($siteVisitsMap) 指定您选择的名称。 本指南使用 siteStats 进行演示:
/var/www/html/hit_counter.php
$siteVisitsMap = 'siteStats';
定义 Redis 哈希映射后,您现在将初始化一个空的 Redis 键 ($visitorHashKey)。 然后,您将使用访问者的 IP 地址填充它。 您将使用 $visitorHashKey 变量的值来唯一标识请求您的网页的每个访问者:
/var/www/html/hit_counter.php
$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'] 变量是否是人口稠密。
在此之后,初始化一个 $totalVisits 变量来存储每个 IP 地址的总访问量,并为其分配一个值 0。 然后,使用 PHP if (...) {...} else {...} 和 $redis->hExists($siteVisitsMap, $visitorHashKey) 语句检查该 IP 地址是否在 Redis 服务器中有任何条目。
您将使用语句 if ($redis->hExists($siteVisitsMap, $visitorHashKey)) {...} 来检查 $visitorHashKey 是否存在于名为 $siteVisitsMap 的映射中。
如果 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。 最后,根据前面if (...) {...} else {...}语句的结果,使用$redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits);设置$visitorHashKey的值。 $redis->hSet($siteVisitsMap, $visitorHashKey, $totalVisits) 语句在 Redis 服务器中创建一个 $siteVisitsMap 哈希映射,其键名为 $visitorHashKey,值为 $totalVisits。
然后,通过回显总访问量来欢迎访问者并关闭 } catch (...) {...} 块:
/var/www/html/hit_counter.php
$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 文件应类似于以下代码:
/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 文件:
sudo nano /var/www/html/log_report.php
然后,在文件中输入以下信息。 将 EXAMPLE_PASSWORD 替换为 Redis 服务器的正确密码:
/var/www/html/log.php
<!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 内存数据库的更多信息,请遵循以下指南: