巧用 Nginx 的 geo 模块来记录地理信息

Nginx 提供了 GeoIP 来记录来源 IP 的地理位置信息,但 GeoIP 所依赖的 IP 库是收费项目,免费的模块只能区分国家信息,不大适合在线上使用。而 Nginx 另外也提供了 Geo 指令,一直以为 IP 库比较庞大,Nginx 加载的时候开销会增加,以前特意试了下,其实情况还很不错。

GEO 指令介绍

语法

geo $address $variable

默认值

-

上下文

http

geo 指令主要是可以根据指定变量的值映射出一个新变量。 如果不指定变量,默认为$remote_addr,从 nginx 0.7.27 开始,可以根据任意变量映射新变量。

指令

用法解释

delete

删除指定的网络,从 nginx 0.7.23 开始支持

default

默认值。 如果使用 CIDR,可以用“0.0.0.0/0”或"::0"代替 default,如果 default 没有指定,则默认值为空字符串。

include

包含一个定义地址和值的文件,可以包含多个。

proxy

定义可信地址(0.8.7 0.7.63)。 如果请求来自可信地址,nginx 将使用其“X-Forwarded-For”头来获得地址。 相对于普通地址,可信地址是顺序检测的。从 nginx 1.3.0 和 1.2.1 开始支持 ipv6。

proxy_recursive

开启递归查找地址(1.3.0 1.2.1)。 如果关闭递归查找,在客户端地址与某个可信地址匹配时,nginx 将使用“X-Forwarded-For”中的最后一个地址来代替原始客户端地址。如果开启递归查找,在客户端地址与某个可信地址匹配时,nginx 将使用“X-Forwarded-For”中最后一个与所有可信地址都不匹配的地址来代替原始客户端地址。

ranges

使用以地址段的形式定义地址(0.7.23),这个参数必须放在首位。为了加速装载地址库,地址应按升序定义。

IP 库收敛

没有进行收敛的 IP 库行数很多,有的文件还特别大,加载起来比较慢,所以进行 IP 库的收敛以减少库文件的大小,还是很有必要的。

IP 库来自于 GSLB 和视频的修改版本,为了减少存储,特意将国家和省份的中文转换为英文,部分运营商的中文就没有简化了,可按 GSLB 的标准简化为数字代码。

GSLB 是英文Global Server Load Balance的缩写,意思是全局负载均衡。

geo 的拼音版本见附件 geo_en_20160918.tar.gz。

IP 网段收敛的工具来自于以前写的一个单线程的程序,处理上千万行的文本时,内存不够用了,如果要处理的文本过大,得手工分割下,多次收敛后再合并。因为没法贴附件,如果需要可以在评论区留言。

利用该工具,针对国家、省份和运营商三个维度进行了收敛,收敛后三个文件不到 3.5M。如果有必要,也可以针对城市再进行收敛。

另外,港澳台既在国家地区里,另外又在中国的省份文件里。

中国运营商映射文件

收敛后的文件扩展名为.geo,方便 include 进 nginx 的配置文件。按运营商收敛后,ip 段共 9983 行。

geo $geo_isp {
        ranges;
        1.0.1.0-1.0.3.255       CTC;
        1.0.8.0-1.0.15.255      CTC;
        1.0.32.0-1.0.63.255     CTC;
        1.1.0.0-1.1.0.255       CTC;
        1.1.2.0-1.1.63.255      CTC;
        1.2.0.0-1.2.1.255       CTC;
        ......
}

国家/地区映射文件

GSLB 的 IP 库引入了很多干扰项,譬如组播地址、内网地址、保留地址都对应了地理位置,为了保证纯粹性,下载了 2016 年 9 月 15 日的 delegated-arin-extended 库文件,提取了国家和地区信息。

去掉了部分内网和多播网段,按国家收敛后有 87007 行。

geo  $geo_zone {
        ranges;
        1.0.0.0-1.0.0.255       AU;
        1.0.1.0-1.0.3.255       CN;
        1.0.4.0-1.0.7.255       AU;
        1.0.8.0-1.0.15.255      CN;
        1.0.16.0-1.0.31.255     JP;
        1.0.32.0-1.0.63.255     CN;
        1.0.64.0-1.0.127.255    JP;
        1.0.128.0-1.0.255.255   TH;
        1.1.0.0-1.1.0.255       CN;
        1.1.1.0-1.1.1.255       AU;
        ......
}

中国省份映射文件

国内按省份收敛后有 13240 行。

geo $geo_prov {
        ranges;
        1.0.1.0-1.0.3.255       FJ;
        1.0.8.0-1.0.15.255      GD;
        1.0.32.0-1.0.63.255     GD;
        1.1.0.0-1.1.0.255       FJ;
        1.1.2.0-1.1.7.255       FJ;
        1.1.8.0-1.1.63.255      GD;
        1.2.0.0-1.2.1.255       FJ;
        1.2.2.0-1.2.2.255       BJ;
        1.2.4.0-1.2.4.255       BJ;
        1.2.5.0-1.2.7.255       FJ;
        ......
}

应用场景

网上说的用 geo 来做负载均衡来调度,不大靠谱,不适合腾讯网之类的大网站,不过比较适合各地都有站点的地方站、论坛、城市、房产、旅游等网站,可以根据访客地理位置将请求 302 到特定站点。

另外,最常规的应用,就是将$geo_isp、$geo_zone、$geo_prov 三个变量加到日志格式定义里,这样,在日志里就可看到每次请求的地理位置,以供后续的统计分析。

使用方法

将这三个 geo 文件放置在 nginx 安装目录的 conf/geo 子目录下,然后用下述指令包含进去,前面说的三个变量就可以用了。

include  geo/*.geo;

效果

下面简单列出了 9 月 22 日 17 点前每个省的访问次数分布图,后续也可很容易分析出跨省/跨网访问趋势来。

性能消耗

找了 1 台 2008 年的 C1,活动连接不到 1 万,出入包量各在 3 万左右,在 nginx 里加载了这 3 个文件,性能消耗基本可以忽略不计。

启动时间

加载起来很快,大大出乎我的意料,fw.qq.com 加载的是 SNG 的 ip 库,有段时间文件非常大,加载起来都是以分钟计的,所以以前对 ip 库的加载一直有阴影,看来加载个 4.3M 的文件,基本无影响。

# time /usr/local/nginx/sbin/nginx -s reload

real    0m0.480s
user    0m0.316s
sys     0m0.104s

性能

加载的时候负载有上升 50%,稍后又恢复,CPU 基本看不出变化。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

尹磊的专栏

1 篇文章1 人订阅

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏嵌入式程序猿

那些一看就懂的MQX实时操作系统高级培训

经过了MQX入门,进阶培训,是不是想在提升一下逼格,在掌握一些技能呢,今天我们就来看看小猿带给你的精彩高级培训。 Modbus 通信 众所周知,Modbus通信...

2655
来自专栏程序员互动联盟

【专业领域】jvm虚拟机android移植-接口篇

上一篇我们讲了如何下载phoneme虚拟机开源代码,如何配置编译脚本,编译测试验证基本功能。但是要让她在android上显示运行java小游戏我们还得费点劲。好...

3357
来自专栏PPV课数据科学社区

【观点】R语言在做为数据分析工具的优点

我从事数据分析工作已经有十年之久。最初是出于工作需要,我的经理给我一堆数据,我需要处理这些数据。当时我一直使用的工具是 Excel,因为这是我熟练掌握的一款工具...

3438
来自专栏腾讯技术工程官方号的专栏

Paxos和Raft的前世今生

? 前言 在保证数据安全的基础上,保持服务的持续可用,是核心业务对底层数据存储系统的基本要求。业界常见的1主N备的方案面临的问题是“最大可用(Maxi...

6.7K4
来自专栏进击的程序猿

raft 解读系列(1) 之 原理一致性的来龙去脉Leader ElectionLog Replication参考

首先我们知道在单机系统中不存在数据的一致性问题,在分布式系统中,由于采用多机器进行分布式部署,必然带来数据的复制,那为什么引入数据的复制呢?主要试图解决的两个问...

733
来自专栏QQ会员技术团队的专栏

日请求亿级的 QQ 会员 AMS 平台 PHP 7 升级实践

自2015年5月,我们就开始规划 PHP 底层升级,最终的目标是升级到 PHP 7。那时, PHP 7尚处于研发阶段,而我们讨论和预研就已经开始了。

12.6K6
来自专栏CDA数据分析师

R语言 PK Excel,谁更适合做数据分析?

我从事数据分析工作已经有十年之久。最初是出于工作需要,我的经理给我一堆数据,我需要处理这些数据。当时我一直使用的工具是 Excel,因为这是我熟练掌握的一款工具...

2277
来自专栏玉树芝兰

如何用 Python 和 API 收集与分析网络数据?

本文以一款阿里云市场历史天气查询产品为例,为你逐步介绍如何用 Python 调用 API 收集、分析与可视化数据。希望你举一反三,轻松应对今后的 API 数据收...

802
来自专栏逆向技术

学习逆向知识之用于游戏外挂的实现.第三讲,通过游戏外挂.分析红色警戒金钱基址.以及确定基址小技巧.

                          分析红色警戒金钱基址.以及确定基址小技巧.

581
来自专栏美团技术团队

Android OOM案例分析

在Android(Java)开发中,基本都会遇到java.lang.OutOfMemoryError(本文简称OOM),这种错误解决起来相对于一般的Except...

4364

扫码关注云+社区