geoserver发布地图服务_Python获取 bing 地图发布自己的 TMS 服务(二)解决海量瓦片存取问题...

本文探讨了金字塔结构瓦片的数量问题,揭示了直接存储在文件系统中的弊端,如数量限制和备份不便。提出了解决方案,包括单机存储时使用sqlite和集群存储时采用HDFS。通过一个试验展示了优化点,并提供了源码下载链接。
摘要由CSDN通过智能技术生成

040d255450dee53a7cbf95860db73af5.png

金字塔结构的瓦片数量有多大

以目前互联网常用的WebMecator为例

  • 第一层:4幅256*256影像瓦片(JPG或PNG等)
  • 第二层:42
  • 第三层:43
  • 依次类推
    比如计算第1层至第18层的瓦片总数目(等比数列求和)91625968980个,大约916亿。存储空间估算在近百T。

瓦片直接存储在文件系统中的缺点

  • 文件系统对文件数量、大小的限制
  • 不易迁移、备份
  • 等等

解决方案

这个问题本质上是对海量小数据的管理,很多互联网大厂都有比较成熟的方案,只需要根据具体情况进行选择调整即可。

单机存储

采用sqlite
存储在多个sqlite中,sqlite文件名保证了唯一性,与(row,column, level)一一对应。

  • (row,column, level)可以转为唯一数字,比如QuadKey,或者其他编码方式
  • sqlite移动与管理就比较方便。

注意sqlite单文件的大小不要太大。

集群存储

使用HDFS等网络化存储方案。

一个试验

# -*- coding: utf-8 -*- 
"""下载区域影像 
从第一层到指定层 
 
多线程版 
 
存储到sqlite中 
 
""" 
 
import requests 
# python3的thread模块 
import _thread 
import random 
import time 
from random import random 
import os.path 
import QuadKey.quadkey as quadkey 
import shutil 
import secrets as secrets 
 
import sqlite_util as dbutil 
 
 
# 下载的最细层 
tileZoom = 10 
rootTileDir = "tiles_db" 
 
# 分的db数量,采用质数 
 
db_num = 1511 
lat_min = -90 
lat_max = 90 
lon_min = -180 
lon_max = 180 
# MS doesn't want you hardcoding the URLs to the tile server. This request asks for the Aerial 
# url template. Replace {quadkey} 
response = requests.get("https://dev.virtualearth.net/REST/V1/Imagery/Metadata/Aerial?key=%s" % (secrets.bingKey)) 
 
# 返回结果 
data = response.json() 
print(data) 
 
# grabs the data we need from the response. 
# 例如:http://ecn.{subdomain}.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=7786 
tileUrlTemplate = data['resourceSets'][0]['resources'][0]['imageUrl'] 
# 例如:['t0', 't1', 't2', 't3'] 
imageDomains = data['resourceSets'][0]['resources'][0]['imageUrlSubdomains'] 
 
if (os.path.exists(rootTileDir) == False): 
    os.mkdir(rootTileDir) 
 
bingTilesDir = os.path.join(rootTileDir, "bing") 
 
if (os.path.exists(bingTilesDir) == False): 
    os.mkdir(bingTilesDir) 
 
 
 
def get_tiles_by_pixel(tilePixel): 
 """ 
    下载该点之上的瓦片 
 
    :param lat: 
    :param lon: 
    :return: 
    """ 
 
 """get pixel coordinates""" 
 # tilePixel = quadkey.TileSystem.geo_to_pixel((lat, lon), tileZoom) 
 
 # print(tilePixel) 
 
    pixel = tilePixel 
    geo = quadkey.TileSystem.pixel_to_geo(pixel, tileZoom) 
 # 计算四键 
    qk = quadkey.from_geo(geo, tileZoom) 
 
 # 四键 
    qkStr = str(qk) 
 
 
 # 
    qkArray = [] 
 for index in range(tileZoom): 
        qkArray.append(qkStr[0:index + 1]) 
 
    print(qkArray) 
 # 存放路径 
 for qk in qkArray: 
 # db位置 
        dbPath = "%s/%s.db" % (bingTilesDir, int(qk) % db_num ) 
        print(dbPath) 
 
 if (os.path.exists(dbPath) == False): 
 # os.mkdir(dbPath) 
            dbutil.create_db(dbPath) 
 
 
 
 # 下载影像 
 
 if (dbutil.is_exists(dbPath, qk)): 
 # already downloaded 
            dbutil.save_images(dbPath, qk) 
            ok = 1 
 else: 
            print("下载中", end='') 
 
            url = tileUrlTemplate.replace("{subdomain}", imageDomains[0]) 
            url = url.replace("{quadkey}", qk) 
            url = "%s&key=%s" % (url, secrets.bingKey) 
 
            response = requests.get(url, stream=True) 
            print(response) 
            dbutil.insert(dbPath, qk, response.content) 
 
 del response 
 # 强制睡一会,防止bing服务器限制 
            sleepTime = random() * 3 
            time.sleep(sleepTime) 
 
# 左上为原点 
tilePixelMax = quadkey.TileSystem.geo_to_pixel((lat_max, lon_max), tileZoom) 
tilePixelMin = quadkey.TileSystem.geo_to_pixel((lat_min, lon_min), tileZoom) 
print(tilePixelMax) 
print(tilePixelMin) 
 
tile_pixel_list = [] 
 
for x in range(tilePixelMin[0], tilePixelMax[0], 256): 
 for y in range(tilePixelMax[1], tilePixelMin[1], 246): 
        tile_pixel_list.append((x, y)) 
 
# 取决与服务器的硬件性能 
thread_pause = 30 
for i in range(len(tile_pixel_list)): 
    print("处理"+str(i)) 
    _thread.start_new_thread(get_tiles_by_pixel,(tile_pixel_list[i],) ) 
 
 if(i % thread_pause == (thread_pause-1)): 
        print("让正常运行的线程执行完,睡眠开始") 
        time.sleep(5) 
        print("睡眠结束") 
 
# _thread.start_new_thread( get_tiles_by_pixel, ( ) ) 
 
 
print('下载完毕') 

可以优化的点很多

  • 修改线程使用方式
  • 提高查询影像是否存在的效率
  • 减少建立sqlite连接的次数

源码

更多详情见下面链接

Python获取 bing 地图发布自己的 TMS 服务(二)解决海量瓦片存取问题 - 小专栏​xiaozhuanlan.com
1f7c307ac74f672114c480aef7faf7a6.png


文章尾部提供源码下载,对本专栏感兴趣的话,可以关注一波

GIS之家店铺:GIS之家
GIS之家源码咨询:GIS之家webgis入门开发系列demo源代码咨询

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值