上一篇我们对Nginx的access.log进行了初步的解析和提取字段处理,如果想进一步对客户端的IP来源进行分析和地理定位,我们需要借助第三方库GeoIP来进行地理定位。
GeoIP的使用
这里要说明一下GeoIP是一个免费的IP定位数据库,现在目前有两个版本GeoIP和GeoIP2
GeoIP官网地址:
这里GeoIP和GeoIP2我都尝试过了,使用GeoIP2是因为GeoIP不支持IPv6,开始access.log日志的IP使用的IPv6,但是ES 2.x版本也只支持IPv4类型,所以为了简单把access.log日志的IP改为了IPv4。下面说一下GeoIP和GeoIP2的安装和使用
安装GeoIP数据库
GeoIP(免费版叫GeoLite)数据库下载地址
|
|
Logstash配置文件中指定GeoIP数据库文件
Logstash默认是安装了logstash-filter-geoip插件的,所以可以直接使用下面的配置。我们继续上一篇的Logstash配置文件修改如下:
|
|
GeoIP的格式
|
|
安装GeoIP2数据库
GeoIP2(免费版叫GeoLite2)数据库下载地址
|
|
Logstash配置文件中指定GeoIP2数据库文件
|
|
这里需要单独安装geoip2插件,因为geoip2插件不是Logstash的官方插件。不使用geoip是因为对IPv6支持的不好,但是ES 2.x版本也只支持IPv4,不支持IPv6类型存储,所以后来只是将access.log的IP地址改为IPv4了。这里只是介绍下如何使用GeoIP2。
|
|
注意这里的field不能直接用geoip插件的写法,因为有一些字段在geoip2中已经被去掉了,例如:real_region_name,否则会报如下错误
|
|
下面是GeoIP2的格式,可以对比一下GeoIP的格式,不同的地方用*号标识出来了。
GeoIP2的格式
|
|
ES的索引Template模板
引用GeoIP之后,对应的ES的索引Template模板也有相应的变化
|
|
这里添加了一个geoip字段,并且使用dynamic,这样允许Logstash的geoip插件将解析后的详细字段也保存到ES索引中。这里geoip插件解析出来会带有一个location字段,这个字段就是经纬度的坐标点,所以这里设置geoip.location字段的类型是geo_point。
从Logstash的1.3.0版本开始,如果GeoIP查询返回纬度和经度,则会创建一个[geoip] [location]字段。 该字段存储为GeoJSON格式。 此外,弹性搜索输出提供的默认Elasticsearch模板将[geoip] [location]字段映射到Elasticsearch geo_point。
以下是elastic.co官方文档对于geo_point类型的解释
用于索引字段
geo_point映射将索引具有lat,lon格式的单个字段。lat_lon选项可以设置为也将.lat和.lon作为数字字段索引,geohash可以设置为true以索引.geohash值。
一个好的做法是启用索引lat_lon,因为geo距离和边界框过滤器可以使用内存检查或使用索引的lat lon值执行,并且它实际上取决于哪个数据集执行得更好。请注意,索引lat lon只有当字段有一个地理点值,而不是多个值时才有意义。
Geohashes
地理散列是一种纬度/经度编码的形式,它将地球分成网格。此网格中的每个单元格都由geohash字符串表示。每个单元又可以被进一步细分成由较长串表示的较小单元。因此,geohash越长,单元格越小(从而更精确)。
因为geohash只是字符串,它们可以像任何其他字符串一样存储在倒排索引中,这使得查询非常有效。
如果启用geohash选项,geohash“子字段”将被索引为,例如pin.geohash。geohash的长度由geohash_precision参数控制,geohash_precision参数可以设置为绝对长度(例如12,默认值)或距离(例如1km)。
更有用的是,将geohash_prefix选项设置为true不仅可以索引geohash值,还可以索引所有包围的单元格。例如,u30的geohash将被索引为[u,u3,u30]。此选项可以由Geohash单元格过滤器用于非常有效地查找特定单元格中的地理位置。
geo_point类型支持4种方式,下面是官网给出的例子。
|
|
以下是翻译自elastic.co官方文档
说明:
- 方式1:Geo-point表示为一个object,具有lat和lon两个key
- 方式2:Geo-point表示为一个string,格式为”lat,lon”
- 方式3:Geo-point表示为geohash
- 方式4:Geo-point表示为一个array,格式为: [lon, lat]
- 查询方式:地理边界框查询,它查找落在框内的所有geo-points
注意:
string方式的geo-points顺序是lat,lon,而数组方式的geo-points顺序是反过来的lon,lat。最初,lat,lon用于数组和字符串,但是数组格式早期改变以符合GeoJSON使用的格式。
|
|
Kibana配置TileMap
创建TileMap视图
在Visualization中选择创建TileMap
TileMap配置后的效果图
然后在索引中选择geoip.location字段,如下图左边所示。注意:我这里替换成了高德地图后的效果,具体可以参考Kibana系列的文章。
配置错误处理
如果配置的过程中报错”No Compatible Fields: The “[nginx_access_logsindex*]” index pattern does not contain any of the following field types: geo_point”
错误原因:这个错误是因为我们的geoip的location字段类型不是geo_point,之前尝试Logstash写入数据到ES的时候没有在nginx_access_logsindex*索引模板中明确的指定geoip.location的类型,所以默认使用的dynamic_templates的配置,动态创建出来的geoip.location字段是string类型的,所以需要在ES的模板中指定好geoip.location字段的类型是geo_point。
参考文章:
- https://www.maxmind.com/zh/home
- https://www.elastic.co/guide/en/elasticsearch/reference/2.4/ip.html
- https://www.elastic.co/guide/en/elasticsearch/reference/2.4/geo-point.html
- https://www.elastic.co/guide/en/logstash/2.4/plugins-filters-geoip.html
- http://kibana.logstash.es/content/logstash/plugins/filter/geoip.html
- https://github.com/logstash-plugins/logstash-filter-geoip/issues/12
- http://dev.maxmind.com/geoip/legacy/codes/iso3166/
- http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/
- http://blog.csdn.net/yanggd1987/article/details/50469113