最近项目中有一个需求统计访客数据,为了保证效率。前端尽量轻量化,仅将访客原始请求信息不作任何处理直接写入消息队列。后端计划任务服务器监听消息队列,解析 user agent, ip 地址,处理结果写入 ES 供报表使用,其中 IP地址处理需要跟据 IP地址获取国家,本文主要研究解决PHP语言跟据IP获取国家的单一需求。
首先解决数据源
1 纯真IP库 缺点:主要为国内IP库,如果仅需要国家信息,则冗余信息多,解析效率低 2 高用第三方接口(如:ip138)解析。 缺点:延时高,稳定性差 排除以上数据源方案。 当前比较可靠的数据源:GEOIP 库,商业化运作,更新频率很高,有提供免费的IP库供下载 官网: https://geoip.com/ https://www.maxmind.com/ 这两个网站是同一家公司。 PHP官方 支持 geoip 扩展,相关方法见官方文档: https://www.php.net/manual/zh/book.geoip.php 更多的时候,项目不方便安装扩展,可以使用纯 php 的 composer 安装包 官方开发的 PHP composer 安装包: 在 composer 包管理网站 packagist.org 搜 geoip 排名靠前的. geoip2/geoip2,maxmind-db/reader, geoip/geoip 是官方提供的安装包,其中 "geoip/geoip". Abandoned,转到了 geo2/geoip2,
下载库文件:
composer requre geoip2/geoip2
编写代码前,首先需要下载最新版的 IP数据库, 官网下载地址:
https://www.maxmind.com/en/geoip2-country-database
默认是商业版,下载需要一定的费用。支持一次性/按月/按年三种付费方式
同时,官方提供了免费版本,首先在官网注册一个账号,成功后使用账号登录,在用户中心 点 "download files" 下载相关文件
程序示例:
<?php
// 指定 IP数据库,在调用代码中引用该文件:
$reader = new \GeoIp2\Database\Reader('/path/tp/your/GeoLite2-Country.mmdb');
$record = $reader->country('128.101.101.101');
print($record->country->isoCode . "\n"); // 'US'
print($record->country->name . "\n"); // 'United States'
print($record->country->names['zh-CN'] . "\n"); // '美国'
?>
简单测试下效率:
<?php
$reader = new \GeoIp2\Database\Reader( '/path/tp/your/GeoLite2-Country.mmdb');
$success = 0;
$t0 = microtime(1);
for ($i = 0; $i<2000; $i++) {
try {
$ip = rand(1,255) . '.' . rand(1,255) . '.' .rand(1,255) . '.' . rand(1,255);
$record = $reader->country($ip);
// echo $ip . ':' . $record->country->isoCode . "<br>\r\n";
$success++;
} catch (\Throwable $t) {
}
}
$t1 = microtime(1);
echo '用时:' . number_format($t1 - $t0, 3, '.', '') . '秒 <br/>';
echo '有效IP: ' . $success . ' 个';
?>









