在平时开发应用中,经常会有通过经纬度获取地址信息的需求,这种需要可以通过高德等地图软件提供的收费API处理,也可以自己搭建地址编码服务器。

Nominatim

Nominatim(https://github.com/osm-search/Nominatim)是一个可以按名称和地址来搜索OSM中的数据,并生成OSM点的合成地址的工具(反向地理编码)。可用在http://nominatim.openstreetmap.org找到这个工具。Nominatim也用在OpenStreetMap首页搜索工具栏中,同时也为MapQuest Open Initiative提供搜索支持。

数据导入阶段

读取原始OSM数据,并提取对地理编码有用的所有信息。这部分由osm2pgsql完成,该工具也可用于导入渲染数据库。它使用osm2pgsql/src/output-gatetter中的特殊地名词典输出插件。[ch]pp.导入的结果可以在数据库表中找到。

地址计算或索引阶段

从位置获取数据,并添加地理编码所需的其他信息。它按重要性对地点进行排名,将属于一起的对象链接在一起,并计算地址和搜索索引。大部分工作是通过数据库触发器在PL/pgSQL中完成的,可以在sql/functions/目录中的文件中找到。

搜索前端

实现了实际的API。它接受用户的搜索和反向地理编码查询,查找数据并以请求的格式返回结果。这部分是用PHP编写的,可以在lib/和website/目录中找到。使用apache。

Docker compose安装

services:
    nominatim:
        container_name: nominatim
        image: mediagis/nominatim:4.4
        ports:
            - "5432:5432"
            - "8080:8080"
        environment:
            TZ: Asia/Shanghai
            PBF_URL: https://download.geofabrik.de/asia/china-latest.osm.pbf
            REPLICATION_URL: https://download.geofabrik.de/asia/china-updates/
            NOMINATIM_PASSWORD: 123456
            IMPORT_WIKIPEDIA: "true"
            IMPORT_US_POSTCODES: "true"
            IMPORT_GB_POSTCODES: "true"
            REPLICATION_UPDATE_INTVAL: 86400
            THREADS: 16
        volumes:
            - type: bind
              source: /home/test/nominatim/data/db
              target: /var/lib/postgresql/14/main
            - type: bind
              source: /home/test/nominatim/data/flatnode
              target: /nominatim/flatnode
        shm_size: 1gb

5432是PostgreSQL数据库的端口,8080是服务启动之后提供的web接口端口

PBF_URL:数据包地址

REPLICATION_URL:更新包地址

NOMINATIM_PASSWORD:数据库密码

IMPORT_WIKIPEDIA:导入wiki数据

IMPORT_US_POSTCODES:导入美国邮编

IMPORT_GB_POSTCODES:导入邮编

REPLICATION_UPDATE_INTVAL:更新间隔,单位秒

THREADS:解析地址的线程

如果docker下载osm.pbf很慢,也可以用下载工具下完之后,映射到docker里面:

#PBF_URL: https://download.geofabrik.de/asia/china-latest.osm.pbf
PBF_PATH: /nominatim/data/osm/planet-latest.osm.pbf

volumes:
  - /home/test/nominatim/data/osm:/nominatim/data/osm

这里使用中国的pbf,安装解析过程比较长(可能需要2、3天的时间),具体时间由服务器配置决定。

看到日志出现下面的内容表示服务启动成功:

LOG: database system was shut down at 2022-08-16 05:33:06 UTC
LOG: database system is ready to accept connections

全球地址数据

如果使用全量pbf数据,替换PBF_URL和REPLICATION_URL 的链接:https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/pbf/planet-latest.osm.pbf

https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/replication/day/

全量数据对硬件要求比较高,而且解析时间更长,可能需要一周的时间:

- 16 core CPU (set THREADS variable to number of cores/threads available)
- 64GB RAM
- 1.5TB (NVMe) SSD storage

接口API

https://nominatim.org/release-docs/develop/api/Overview/

这里主要介绍其中的3个

健康检查(/search?q=avenue%20pasteur)

[]

逆地址编码(/reverse?lat=28.259719364765736&lon=112.91566526653007&format=jsonv2&accept-language=zh)

{
    "place_id": 52339186,
    "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright",
    "osm_type": "node",
    "osm_id": 3569911293,
    "lat": "-41.2903464",
    "lon": "174.7779487",
    "category": "place",
    "type": "house",
    "place_rank": 30,
    "importance": 0.00000999999999995449,
    "addresstype": "place",
    "name": "",
    "display_name": "138, Wakefield Street, Te Aro, 惠灵顿 / 惠靈頓 / 威靈頓, 6011, 紐西蘭/新西兰",
    "address": {
        "house_number": "138",
        "road": "Wakefield Street",
        "suburb": "Te Aro",
        "city": "惠灵顿 / 惠靈頓 / 威靈頓",
        "county": "惠灵顿 / 惠靈頓 / 威靈頓",
        "state": "惠灵顿 / 惠靈頓 / 威靈頓",
        "ISO3166-2-lvl4": "NZ-WGN",
        "postcode": "6011",
        "country": "紐西蘭/新西兰",
        "country_code": "nz"
    },
    "boundingbox": [
        "-41.2903964",
        "-41.2902964",
        "174.7778987",
        "174.7779987"
    ]
}

ID详情(/details?osmtype=W&osmid=1274999787&format=json&accept-language=zh)

{
    "place_id": 73967428,
    "parent_place_id": 74020996,
    "osm_type": "N",
    "osm_id": 3569911293,
    "category": "place",
    "type": "house",
    "admin_level": 15,
    "localname": "138",
    "names": [],
    "addresstags": {
        "city": "Wellington",
        "housenumber": "138",
        "postcode": "6011",
        "street": "Wakefield Street",
        "suburb": "Te Aro"
    },
    "housenumber": "138",
    "calculated_postcode": "6011",
    "country_code": "nz",
    "indexed_date": "2024-08-13T00:20:54+00:00",
    "importance": 9.99999999995449e-6,
    "calculated_importance": 9.99999999995449e-6,
    "extratags": [],
    "calculated_wikipedia": null,
    "rank_address": 30,
    "rank_search": 30,
    "isarea": false,
    "centroid": {
        "type": "Point",
        "coordinates": [
            174.7779487,
            -41.2903464
        ]
    },
    "geometry": {
        "type": "Point",
        "coordinates": [
            174.7779487,
            -41.2903464
        ]
    }
}

压力测试

使用lua脚本进行压力测试

-- 设置随机数种子
math.randomseed(os.time())

-- 随机生成经度和纬度的函数
function generate_random_coordinates()
        local longitude = math.random() * 360 - 180 -- [-180, 180]
        local latitude = math.random() * 180 - 90 -- [-90, 90]
        return longitude, latitude
end

-- 定义请求的函数,wrk会在每次请求之前调用这个函数
request = function()
        -- 生成随机的经纬度
        local longitude, latitude = generate_random_coordinates()

    -- 构建带有随机经纬度的请求URL
    local url = "/reverse?lon=" .. string.format("%.6f", longitude) .. "&lat=" .. string.format("%.6f", latitude).."&format=jsonv2&accept-language=zh"

    -- 返回 GET 请求,包含自定义的 URL
    --print(url)
    return wrk.format("GET", url)
end

-- 定义返回的函数
response = function(status, headers, body)
        if status ~= 200 then
                print(body)
        return
      

测试命令

wrk -t100 -c10000 -d600s -s request.lua --latency http://localhost:8080

开启100个线程,模拟10000个连接,持续600秒,结果如下:
Running 10m test @ http://localhost:8080
100 threads and 10000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 32.97ms 38.66ms 1.99s 92.99%
Req/Sec 70.11 61.57 2.96k 89.25%
Latency Distribution
50% 24.34ms
75% 42.52ms
90% 64.47ms
99% 116.16ms
2609713 requests in 10.00m, 1.22GB read
Socket errors: connect 0, read 17012, write 50793, timeout 26407
Requests/sec: 4349.02
Transfer/sec: 2.08MB
0

本文为原创文章,转载请注明出处,欢迎访问作者网站(和而不同)

发表评论

error: Content is protected !!