最近項目中有一個需求統(tǒng)計訪客數(shù)據(jù),為了保證效率。前端盡量輕量化,僅將訪客原始請求信息不作任何處理直接寫入消息隊列。后端計劃任務(wù)服務(wù)器監(jiān)聽消息隊列,解析 user agent, ip 地址,處理結(jié)果寫入 ES ?供報表使用,其中 IP地址處理需要跟據(jù) IP地址獲取國家,本文主要研究解決PHP語言跟據(jù)IP獲取國家的單一需求。
首先解決數(shù)據(jù)源
1 純真IP庫
缺點:主要為國內(nèi)IP庫,如果僅需要國家信息,則冗余信息多,解析效率低
2 高用第三方接口(如:ip138)解析。
缺點:延時高,穩(wěn)定性差
排除以上數(shù)據(jù)源方案。
當前比較可靠的數(shù)據(jù)源:GEOIP 庫,商業(yè)化運作,更新頻率很高,有提供免費的IP庫供下載
官網(wǎng):
https://geoip.com/
https://www.maxmind.com/
這兩個網(wǎng)站是同一家公司。
PHP官方 支持 geoip 擴展,相關(guān)方法見官方文檔:
https://www.php.net/manual/zh/book.geoip.php
更多的時候,項目不方便安裝擴展,可以使用純 php 的 composer 安裝包
官方開發(fā)的 PHP composer 安裝包:
在 composer 包管理網(wǎng)站 packagist.org 搜 geoip
排名靠前的. geoip2/geoip2,maxmind-db/reader, geoip/geoip 是官方提供的安裝包,其中 "geoip/geoip". Abandoned,轉(zhuǎn)到了 geo2/geoip2,

下載庫文件:
composer requre geoip2/geoip2
編寫代碼前,首先需要下載最新版的 IP數(shù)據(jù)庫, 官網(wǎng)下載地址:
https://www.maxmind.com/en/geoip2-country-database
默認是商業(yè)版,下載需要一定的費用。支持一次性/按月/按年三種付費方式

同時,官方提供了免費版本,首先在官網(wǎng)注冊一個賬號,成功后使用賬號登錄,在用戶中心 點 "download files" 下載相關(guān)文件

程序示例:
<?php
// 指定 IP數(shù)據(jù)庫,在調(diào)用代碼中引用該文件:
$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 . ' 個';
?>
18款MAC筆記本電腦(4核16G 固態(tài)硬盤) docker 環(huán)境運行結(jié)果:
用時:0.834秒
有效IP: 1723 個
隨機生成的IP有一部分無效,相當于1秒執(zhí)行了 2000+ 隨機IP查詢,已經(jīng)相當高了,這種高IO 的查詢操作固態(tài)硬盤是主要因素
如果有更高的效率需求,可以將 IP數(shù)據(jù)庫轉(zhuǎn)入 REDIS
跟據(jù)CSV版本的IP數(shù)據(jù),當前版本的 IPv4(IPv6 應(yīng)該需求不多) 數(shù)據(jù)庫僅有 37萬多條記錄(3711110),
GeoLite2-Country-Blocks-IPv4.csv 內(nèi)容示例:
network,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider
1.0.0.0/24,2077456,2077456,,0,0
1.0.1.0/24,1814991,1814991,,0,0
1.0.2.0/23,1814991,1814991,,0,0
1.0.4.0/22,2077456,2077456,,0,0
1.0.8.0/21,1814991,1814991,,0,0
...
223.255.244.0/22,1269750,1269750,,0,0
223.255.248.0/22,1819730,1819730,,0,0
223.255.252.0/23,1814991,1814991,,0,0
223.255.254.0/24,1880251,1880251,,0,0
223.255.255.0/24,2077456,2077456,,0,0
其中第一列 network 為網(wǎng)段/子網(wǎng)掩碼,geoname_id 等列關(guān)聯(lián)了另一個 csv 中的國家信息元數(shù)據(jù)。
可以以網(wǎng)段為鍵名(可IP2Long 轉(zhuǎn)INT),子網(wǎng)掩碼+對應(yīng)的國家二字碼為鍵值 存入 redis, 以內(nèi)存換取更快的IO操作,相信查詢效率會有更大提升。
國為當前項目是在計劃任務(wù)中執(zhí)行,有消息隊列緩沖,可多臺計劃任務(wù)服務(wù)器并行處理。官方 composer 庫效率也足夠高,暫時不折騰了,以后有機會了再嘗試 REDIS 方案
本文原始網(wǎng)址:https://www.liu12.com/article/ip2country,轉(zhuǎn)載請保留出處