ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Copernicus Dataspace下载提速:S3并发、OData筛选与云端Workspace实战

Copernicus Dataspace下载提速:S3并发、OData筛选与云端Workspace实战 做遥感的人十有八九都被 Copernicus Dataspace 的下载速度折磨过。明明家里带宽几百兆点开一个 Sentinel-2 的下载链接进度条却像卡了痰一样1GB 左右的产品动不动就是半小时起步遇到大场景 L1C 甚至能下到你怀疑人生。我最初从 SciHub 迁移过来的时候也踩过这个坑后来把官方文档翻了个底朝天加上自己动手做了各种测试才总结出几条真正能提速的路子。这篇就来聊透为什么 Copernicus Dataspace 下载 Sentinel-2 会这么慢以及我用下来最有效的三个提速技巧包括 S3 并发下载、OData 接口精准拉取还有 Workspace JupyterLab 的云端批处理玩法。这篇文章不挑基础哪怕你以前只用过网页点点点只要照着下面的命令复制粘贴也能把下载速度提上去。如果平时要批量下载多景影像或者打算做长时间序列分析那这几种方法更是刚需。1. 先说清楚Copernicus Dataspace 下载为什么会龟速1.1 从 SciHub 到 Dataspace慢是有历史原因的Copernicus Dataspace 是欧空局这几年主推的新一代数据访问平台说白了就是用来替代老牌 Sentinel 数据下载门户 SciHub 的。很多老用户习惯了 SciHub 那种“搜到产品、复制链接、浏览器直接拉”的流程到了 Dataspace 上发现页面上确实也能点下载但速度和稳定性都远不如以前。这里面的门道在于整个 Copernicus Dataspace 的后端存储换成了 S3 对象存储。数据不再是放在传统 Web 服务器上让你直接 HTTP 拉取而是存在一个以“桶Bucket”为单位的大规模对象存储系统里。浏览器下载只是走了一条最普通、最不优化的路一条 HTTPS 连接从头到尾把文件拆成一个个顺序块往下传中间任何一次网络抖动、会话过期都可能让下载断掉重来。我自己的实测数据是用浏览器从网页端下 Sentinel-2 L1C单连接速度基本在几百 KB/s 到 2MB/s 之间浮动。这个速度受两个因素影响一个是你本地网络到欧洲机房的链路质量另一个是对象存储单连接本身的限速。也就是说哪怕你家里是千兆宽带一条连接也跑不满。1.2 慢的根源对象存储、单连接、跨洋链路很多人以为慢是“网不行”但其实问题是出在传输方式上。S3 对象存储虽然支持 HTTP 访问但它的设计初衷是给程序并发调用用的而不是让你用浏览器一个链接慢慢拉。单连接下载大文件等于绕过了对象存储最大的优势——分段并发。打个比方你去仓库搬货仓库管理员一次只让你从一个小窗口搬后面哪怕排了十个搬运工也只能干等着。浏览器下载就是这个状态。而聪明的下载方式是让多个搬运工同时从不同窗口搬各搬各的最后再合并到货车上。S3 的并发下载本质就是这个多窗口搬运的过程。还有一个容易被忽略的点Copernicus Dataspace 的服务器在欧盟国内访问天然就有跨洋链路的延迟和丢包。这种环境下单连接传输效率就更差了。所以提速的核心思路有两个方向一个是绕开单连接限制、走并发另一个是干脆把“下载”这一步搬到数据所在的地方去也就是后面要讲的 Workspace。1.3 提速前先做好这几件事在开始折腾技巧之前先把基础工作搞定。这一步不会花太多时间但能省掉后面 90% 的坑。第一注册 Copernicus Dataspace 账号。地址是 dataspace.copernicus.eu用邮箱注册就行如果以前注册过 SciHub 账号两者不通用需要重新注册。第二在账号设置里创建一个 OAuth Client。路径是右上角头像 → Settings → OAuth Clients → Create New创建后会得到一组 Client ID 和 Client Secret。后面用 S3 认证或者 OData 带 token 请求时都会用到。第三装好两个基础工具Python3 和 AWS CLI v2。AWS CLI 是走 S3 并发下载的核心工具Python3 则是用来写批量脚本和调 OData 接口的。Windows、macOS、Linux 都有对应安装包不想折腾的话直接用 pip 或者官方安装器。最后一点经验之谈下数据之前先用一个小文件试速度。比如先在网页端找一个几百 MB 的 L2A 产品试试下载速度大概在什么水平再对比后面用 S3 方式下载同一个产品的速度。这样能直观感受到差异也方便判断是不是自己本地网络有问题。2. 提速技巧一用 S3 API 并发下载跑满带宽2.1 为什么 S3 协议比网页下载快S3 协议是对象存储的原生访问协议它最大的优势就是支持 Range 分片下载和大量并发请求。一个 1GB 的文件理论上可以被拆成几十个小块同时下载最后在本地拼起来。AWS CLI 这类工具天生就支持这个能力所以只要把下载地址从网页端换成 S3 接口速度提升立竿见影。Copernicus Dataspace 的公共数据是支持匿名读取的也就是说你甚至不需要配置账号凭证直接拿 AWS CLI 就能下载。当然如果某些受限数据集需要权限那就得用账号的 Client ID 和 Secret 来做 S3 认证。这里先说匿名方式适合绝大多数公开的 Sentinel-2 数据。2.2 准备工作安装工具与获取访问凭证在命令行里先验证一下能不能访问到 S3 桶。打开终端执行这条命令aws --endpoint-url https://eodata.dataspace.copernicus.eu --no-sign-request s3 ls s3://eodata/Sentinel-2/MSI/L1C/2024/01/01/正常情况下应该会列出一堆以 S2A 或 S2B 开头的产品文件夹。如果提示 AccessDenied大概率是路径写错了或者当天这个目录下确实没有产品。可以先用更上层的路径逐级找比如先列s3://eodata/Sentinel-2/看数据结构是什么样的。这里需要说明一下--no-sign-request参数是关键它表示匿名访问不需要 AK/SK。如果使用认证方式需要把你创建的 Client ID 和 Client Secret 配置到 AWS 的 credentials 文件里格式大概是[cdse] aws_access_key_id 你的ClientID aws_secret_access_key 你的ClientSecret然后命令行里加上--profile cdse去掉--no-sign-request即可。2.3 用 AWS CLI 一条命令同步整景数据确定能访问之后下载一整景产品就是一条命令的事。假设我要下载 2024 年 1 月 1 日的某景 L1C 产品完整的 S3 路径是aws --endpoint-url https://eodata.dataspace.copernicus.eu --no-sign-request s3 sync s3://eodata/Sentinel-2/MSI/L1C/2024/01/01/S2A_某ID_..._SAFE/ ./S2A_某ID_..._SAFE/注意这里我用的是s3 sync而不是s3 cp。sync 的好处是它会自动对比本地和远端文件大小如果本地已经有相同文件就跳过不下载。这样即使中途断了重新跑一遍就能接着下比 cp 更适合大文件传输。默认情况下 AWS CLI 的并发数不算高需要手动调一下。在~/.aws/config文件里加一段[profile cdse] s3 max_concurrent_requests 20 max_queue_size 1000这个配置的意思是把并发请求数提到 20排队上限 1000。我实测下来 20 并发是个比较稳妥的数值既不会触发限流又基本能把带宽跑满。如果你的网络状况特别好可以试试 30但再高就容易被服务器限流。2.4 用 Python boto3 写一个可控并发下载脚本如果只是偶尔下几景AWS CLI 完全够用。但如果你有一批产品要下载手动一条条执行 s3 sync 就太蠢了。这时候可以写一个简单的 Python 脚本用 boto3 库批量下载。顺手写一个我用得最多的模板你只需要改产品列表就行import boto3 from boto3.s3.transfer import TransferConfig from botocore import UNSIGNED from botocore.config import Config from concurrent.futures import ThreadPoolExecutor, as_completed s3 boto3.client( s3, endpoint_urlhttps://eodata.dataspace.copernicus.eu, configConfig(signature_versionUNSIGNED), ) download_config TransferConfig(multipart_threshold50 * 1024 * 1024, max_concurrency10) product_s3_paths [ s3://eodata/Sentinel-2/MSI/L1C/2024/01/01/S2A_xxxx_SAFE/, s3://eodata/Sentinel-2/MSI/L1C/2024/01/02/S2A_yyyy_SAFE/, ] def download_one(s3_url, local_dir): bucket eodata key s3_url.replace(s3://eodata/, ) filename key.strip(/).split(/)[-1] local_path f{local_dir}/{filename} s3.download_file(bucket, key, local_path, Configdownload_config) return local_path local_dir ./sentinel2_data with ThreadPoolExecutor(max_workers4) as executor: futures [executor.submit(download_one, url, local_dir) for url in product_s3_paths] for future in as_completed(futures): print(完成:, future.result())这个脚本做了两件事一是每个文件内部通过 TransferConfig 并发下载分片二是多个产品之间用 ThreadPoolExecutor 再并行。整体速度非常可观。不过要提醒一句并发不是无限往上加的。服务器端对匿名请求有流量控制我之前开过 50 个线程同时下结果很快就收到了 429 限流错误。建议单脚本总并发控制在 10~20 之间稳妥第一。3. 提速技巧二用 OData API 精准筛选后直接下载3.1 OData API 能解决什么问题S3 并发下载虽然快但有一个前提——你得先知道产品的 S3 路径。如果数据量大靠网页翻找产品 ID 再拼路径效率反而很低。OData API 就是来解决这个问题的。Copernicus Dataspace 提供了一套 OData 查询接口支持按时间范围、云量、轨道号、地理范围等条件做精确筛选返回结果里直接包含产品 ID、下载链接等信息。把筛选结果和 S3 下载结合起来就形成了一套完整的高效工作流先用 OData 查出要哪些产品再用 S3 并发把它们下下来。3.2 查询语法与 URL 拼接示例OData 的基础入口是https://catalogue.dataspace.copernicus.eu/odata/v1/查询产品用的核心接口是/Products。比如我想查 2024 年 6 月整个月区域内云量低于 20% 的 Sentinel-2 L2A 产品URL 大概长这样https://catalogue.dataspace.copernicus.eu/odata/v1/Products? $filterCollection/Name eq SENTINEL-2 and ContentDate/Start gt 2024-06-01T00:00:00.000Z and ContentDate/Start lt 2024-06-30T23:59:59.999Z and Attributes/OData.CSC.StringAttribute/any(att: att/Name eq productType and att/OData.CSC.StringAttribute/Value eq S2MSI2A) and Attributes/OData.CSC.StringAttribute/any(att: att/Name eq cloudCover and att/OData.CSC.DoubleAttribute/Value lt 20) and OData.CSC.Intersects(areageographySRID4326;POLYGON((121.0 31.0,121.5 31.0,121.5 31.5,121.0 31.5,121.0 31.0))) $orderbyContentDate/Start desc $top20这条 URL 里几个关键点解释一下。ContentDate/Start是产品拍摄时间用 ISO8601 格式。productType是产品级别S2MSI2A 对应 L2A 地表反射率产品S2MSI1C 对应 L1C 大气表观反射率产品。cloudCover的过滤条件不能直接写必须要用Attributes/OData.CSC.StringAttribute/any(...)这种嵌套语法。最后那个OData.CSC.Intersects就是空间范围过滤括号里的 SRID4326 是 WGS84 坐标系后面跟一个多边形坐标串。在浏览器里打开这条 URL会返回一段 JSON里面有每个产品的Id、Name、S3Path等字段。如果返回结果里直接带 S3Path那就省事了直接把这个路径丢给 AWS CLI 下载。3.3 用 Python 脚本实现带断点续传的批量下载OData 接口不仅能查产品列表还能直接下载产品打包文件。官方提供了一条下载整景产品压缩包的路径https://catalogue.dataspace.copernicus.eu/odata/v1/Products(产品ID)/$value这条链接理论上可以直接用浏览器拉取但单连接下载慢的问题依然存在。我的建议是把它和 curl 的断点续传结合使用至少能解决“下到一半断了要重来”的问题curl -L -C - -o S2A_xxx.zip https://catalogue.dataspace.copernicus.eu/odata/v1/Products(产品ID)/$value-C -参数让 curl 支持断点续传断了之后重新执行这条命令它会从断点继续而不是从头再来。如果要做批量下载还是建议写个 Python 脚本。先用 OData 查询拿产品 ID 列表再用 requests 流式下载这一步其实不少人会直接用 requests 加自定义 headers 实现 Range 请求效果和 curl 断点续传类似。我这里不展开全部代码但思路很清晰第一步查列表第二步逐个下载第三步对下载失败的产品标记重试。OData 方式虽然下载速度不如 S3 并发快但它的优势是精确、可控、适合按条件筛选。如果你要下的产品不多不想折腾 AWS CLI用这个方式最省事。4. 提速技巧三用 Workspace JupyterLab 把下载变成内网拷贝4.1 Workspace 是什么为什么它能从根本上解决慢的问题前面两种技巧再怎么优化本质上还是“从欧洲服务器往你本地拉数据”。只要数据还要穿过跨洋链路速度天花板就摆在那里。那有没有办法绕开这个瓶颈有就是把下载这件事搬到欧空局的云端去干下载完直接在云端处理处理完只把结果拿回来。这个就是 Workspace JupyterLab 方案的核心思想。Copernicus Dataspace 给每个用户提供了一个个人工作区Personal Workspace你可以把它理解成一块云上硬盘。最关键的是这个工作区和数据所在的 S3 存储位于同一机房内网所以从数据区导入产品到你的 Workspace走的是内网高速通道速度比从外面拉快一个数量级。一景 1GB 左右的 Sentinel-2 产品我在本地下载要十几分钟用 Workspace 导入基本一两分钟就完成了。4.2 创建 Workspace 并把数据 Import 到云端操作步骤不复杂。登录 Dataspace 网页端后在个人中心的 Workspace Files 里新建一个文件夹比如按日期命名2024_06_sentinel2。然后把需要的数据导入进去。有两种导入方式。一种是在数据检索页面找到某个产品点进详情里面会有 Import to Workspace 或者类似按钮选择目标文件夹即可。另一种是直接在产品批量检索结果页面勾选多个产品统一导入。如果产品特别多等它慢慢拷就行期间可以干别的不需要一直盯着浏览器。这里面我踩过一个小坑如果一次性导入几百景产品Web 界面可能会卡很久甚至看起来像是死了。其实后台还在跑建议不要刷新页面耐心等。如果实在担心可以每次只导入 50~100 景分批进行。4.3 在 JupyterLab 中读取共享数据并进行批处理数据进了 Workspace接下来就要把它用起来。Copernicus Dataspace 配套了一个 JupyterLab 在线环境入口地址是 jupyterhub.dataspace.copernicus.eu。用你的 Dataspace 账号登录后选择计算资源配置一般 Medium 起步就够用然后启动实例。启动后在文件浏览器里找到你的 Workspace 文件夹。如果没看到可以在终端里执行ls /看看挂载目录通常在某个共享路径下。找到刚才导入的 SAFE 文件夹后就能直接用 Python 读了。举个例子用 rasterio 读取 10m 分辨率的 B2、B3、B4 波段合成一张真彩色预览图import rasterio from rasterio.plot import show import numpy as np base /path/to/your/workspace/S2A_xxx.SAFE/GRANULE/XXXX/IMG_DATA/R10m/ b2 rasterio.open(base T33XXX_20240601T..._B02_10m.jp2).read(1) b3 rasterio.open(base T33XXX_20240601T..._B03_10m.jp2).read(1) b4 rasterio.open(base T33XXX_20240601T..._B04_10m.jp2).read(1) rgb np.stack([b4, b3, b2], axis-1) rgb (rgb / rgb.max() * 255).astype(np.uint8)这种处理在云端做速度取决于分配的 CPU/内存而不是你的本地网络。批量处理 100 景影像的时候体验差距尤其明显。4.4 进阶玩法不下载整景直接按需裁剪处理Workspace 方案除了解决下载慢的问题还能顺便解决“很多数据用不上”的浪费问题。很多时候我们并不需要整景 Sentinel-2只需要某个区域、某几个波段的数据。这时候可以用 sentinelhub-py 库通过 Process API 直接在云端做按需裁剪和波段提取只下载结果。配置方法也很简单from sentinelhub import SHConfig config SHConfig() config.sh_client_id 你的ClientID config.sh_client_secret 你的ClientSecret config.sh_datasource s3设置好之后就能用 SentinelHubRequest 请求指定 bbox、波段、时间范围内的数据返回结果是裁剪好的 GeoTIFF几百 MB 的整景数据瞬间变成几十 MB 的目标区域。这个功能特别适合做时序分析比如连续几个月 NDVI 变化监测用 Process API 一次把所有日期的小块数据拉回来比下载整景再裁剪高效得多。5. 一批典型报错的排查思路遇到别慌5.1 HTTP 403 与 401访问被拒绝这是大家遇到最多的报错。403 一般出现在 S3 匿名访问时最常见的原因是路径拼错了。比如某个产品目录下确实没有文件你却去访问服务器就会返回 AccessDenied。解决办法是逐级向上用aws s3 ls列出目录结构确认产品 ID 是否正确。401 则多出现在 OData 下载或 JupyterLab 登录时通常是因为身份凭证过期。OAuth token 默认有效期比较短尤其是用密码模式获取的 token个把小时就会失效重新获取一次即可。另外网页端长时间挂机后再点下载也容易出现 401刷新页面重新登录一般就能解决。5.2 429请求太快被限流429 就是服务器在说“你太快了歇会儿”。很多人在 AWS CLI 里把并发调到很高或者在脚本里用几十个线程同时下载结果很快就触发限流。这个限流不是永久封禁稍微等一下就能恢复但如果反复触发可能会被限制更长时间。我的建议是把并发控制在 10~20 之间。对于 Python 脚本可以在每次请求后休眠几十毫秒或者捕获 429 异常后做指数退避重试退避时间按 1 秒、2 秒、4 秒递增。这样既不会太慢也不会把服务器惹毛。5.3 下载中断、文件损坏怎么办下载大文件中断是常态不用太担心。AWS CLI 的话优先用s3 sync它会跳过本地已存在且大小一致的文件相当于天然的断点续传。如果是用 curl 拉 OData 整景包加上-C -参数就能续传。脚本下载的话建议下载完成后做一个文件大小校验如果远端文件大小和本地不一致就标记为失败并重新下载。还有一个小细节Sentinel-2 的 SAFE 文件夹里有一个manifest.safe文件里面记录了文件清单和校验信息。如果怀疑下载不完整可以检查这个文件所列的文件是否都存在。不过最简单粗暴的办法还是重新跑一遍 sync反正已经存在的文件会被跳过。5.4 遇到提示 “please open a folder or workspace to continue” 怎么办这个提示我一开始也遇到过尤其是在网页端打开某些内置应用或者 Notebook 的时候。它并不是说系统坏了而是在提醒你当前没有指定工作目录请先打开一个文件夹或 Workspace。解决办法很直接。在 Workspace Files 里新建并进入一个文件夹然后重新打开应用或者在 JupyterLab 左侧文件浏览器中点击你的工作区目录让当前活动目录落到该文件夹。如果是某项功能需要特定的 Workspace 路径可以在界面的路径输入框里手动填上。简单说就是给程序指个路告诉它“去这个文件夹干活”。5.5 “workspace unavailable. the isolated linux environment failed to start” 的排查思路这类报错字面上是“工作区不可用隔离 Linux 环境启动失败”在 JupyterHub 这类在线工作区里比较常见。我第一次遇到时也傻了眼后来总结了一套排查顺序。首选检查是不是资源配额定太高了。比如选了 XL 或者 XXL 规格但免费配额不够就会启动失败。换个 Medium 或 Small 规格再启动通常就好了。如果还不行去 JupyterHub 控制台把当前实例 Stop 掉等一两分钟再重新 Start相当于重启。第三个可能是浏览器缓存问题开个无痕窗口重新登录试试。最后如果账号的 Workspace 存储已经满了也可能导致环境启动异常清理掉一些不用的文件然后重试。这几步走下来90% 的情况都能解决。如果还不行可以到官方论坛或者社区搜索报错代码大概率是平台临时故障过一段时间自己就恢复了。6. 三种技巧怎么选我的推荐工作流6.1 按任务规模选方案每个人场景不一样用的方案也不一样。我把自己的选择逻辑整理成一个表格方便你对号入座。场景推荐方案原因临时下载一两景网页端直接下载或 OData $value不用配置环境最省事下载几十景需要筛选条件OData 查询 AWS CLI 并发下载精准筛选速度快方便留档下载上百景要做批量处理Workspace 导入 JupyterLab 批处理省本地磁盘省带宽处理效率高只要某个区域/波段Process API 按需裁剪数据量小几秒出结果这个表格基本覆盖了我日常的绝大多数需求。简单说数据量越大越应该把工作往云端搬数据量小本地直接拉也没问题。6.2 从检索到下载的完整示例最后分享一个我很习惯的完整链路。假设我要下载某区域一个月内的 L2A 影像流程是这样的先用 STAC API 按时间和空间范围检索拿到产品的 S3 路径然后直接用 AWS CLI 批量 sync如果这批数据要立刻做处理那就改走 Workspace 导入在 JupyterLab 里跑分析。STAC 的检索通常比手拼 URL 更友好。比如用 pystac_clientfrom pystac_client import Client catalog Client.open(https://catalogue.dataspace.copernicus.eu/stac/) results catalog.search( collections[sentinel-2-l2a], bbox[121.0, 31.0, 121.5, 31.5], datetime2024-06-01/2024-06-30, query{eo:cloud_cover: {lt: 20}}, limit50, ) items list(results.items()) for item in items: print(item.id, item.assets.get(s3, {}).href)如果 item 的 assets 里带有 S3 href直接提取出来丢给 AWS CLI 就行。这套流程跑顺之后从检索到整景落盘基本是分钟级的事。6.3 Sentinel-2 数据下载完怎么快速进入预处理数据到手里下一步自然是预处理。Sentinel-2 的 L1C 产品是大气表观反射率要做定量分析的话需要先做大气校正。官方工具是 Sen2Cor安装在本地跑也行在 JupyterLab 里跑也行。处理之后会生成 L2A 产品就能直接算 NDVI、NDWI 这些指数了。完整流程大致是L1C 大气校正转 L2A然后按矢量边界裁剪、重投影到目标坐标系再做云掩膜最后计算所需指数。这一步如果你选择的是 L2A 产品前面的大气校正就可以省掉直接从裁剪开始。我个人的建议是能用 L2A 就直接用 L2A省时省力官方 L2A 产品已经覆盖了全球大部分区域。还有个小技巧Sentinel-2 的 JP2 格式文件体积大、读取慢可以先合并成 VRT 或转成 Cloud Optimized GeoTIFF后续读取和处理都会快不少。在批处理场景下这个转换时间摊到每景上是物有所值的。最后说点实在的。这三个技巧我用了大半年整体感受是网页下载一景产品动辄半小时起步的日子已经彻底翻篇了。现在小批量数据直接 OData 查询加 S3 并发三五分钟就能拿到手大批量任务直接丢到云端 Workspace 里本地电脑只负责写代码和看结果带宽和硬盘压力几乎为零。如果你也在被 Copernicus Dataspace 的下载速度折磨建议从 S3 并发下载开始试起这是投入产出比最高的一步。等跑顺了再尝试 Workspace你会打开新世界的大门。
返回列表