Apache SDAP 1.4.0 安装指南

Apache SDAP 1.4.0 安装指南:Ubuntu 22.04 部署 nexus Web 服务,含源码包下载、Python 依赖修正、Solr 8.11.3 双 core、systemd 托管与 REST,ingester 受限

Apache SDAPApache SDAP2026/10/13

Apache SDAP 1.4.0 安装指南

目标:在真实 Ubuntu 22.04 服务器上从零部署 Apache SDAP 1.4.0 的 nexus Web 服务,涵盖官方源码包下载、Python 依赖安装与兼容性修正、Solr 8.11.3 双 core 集成、systemd 托管与 REST 全链路验证。以下命令与回显均在 Ubuntu 22.04.5 真实环境逐步实测;ingester 组件因依赖整套 Spark 摄取链未实测,相关步骤按 ⚠️ 受限标注。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Java:OpenJDK 11.0.32.1(openjdk-11-jdk-headless)
  • Python:3.10.12(pip 22.0.2)
  • Apache SDAP:1.4.0(2024-10 发布,官方仅提供源码包,无二进制发行版)
  • nexus 组件:Python 3.8+ tornado Web 服务,默认端口 8083
  • nexusproto 组件:Gradle + protobuf 定义包(DataTile.proto),同时提供 PyPI 包
  • ingester 组件:Spark 摄取引擎(⚠️ 受限,未实测)
  • Solr:8.11.3(nexus 必选后端,端口 8983,双 core:nexustiles / nexusdatasets)
  • 安装目录:/opt/sdap-nexus(nexus 源码)、/opt/solr(Solr)、/opt/Apache-SDAP(nexusproto 源码)
  • 运行用户:root

二、前置条件

  • 一台 Ubuntu 22.04 服务器,root 权限,内存建议不低于 8GB。
  • 安装 openjdk-11-jdk-headless(Solr 需要 Java 11)、python3、python3-pip、wget、tar、net-tools(含 netstat)、procps、lsof(Solr 启动脚本依赖)。
  • 服务器可访问 downloads.apache.org(源码包)与 archive.apache.org(Solr 包)。

三、版本选型说明

组件版本说明
Apache SDAP1.4.0最新稳定版(2024-10);官方仅发布源码包,无二进制制品
nexus1.4.0(源码)Python tornado Web 服务,端口 8083,poetry 管理依赖
nexusproto1.4.0(源码)Gradle + protobuf 定义包;PyPI 同步提供 nexusproto 1.4.0
ingester1.4.0(源码,约 198MB)Spark 摄取引擎,⚠️ 受限(未实测)
Solr8.11.3nexus 必选后端(瓦片索引 + 数据集目录),运行于 JDK 11
Spark3.2.1(pyspark)nexus 部分 Spark 算法的计算依赖(本地模式可选)
Cassandra3.11.x可选瓦片数据后端(本批次以 Solr 为主后端实测)

⚠️ 受限前置说明:Apache SDAP 官方仅提供源码包。下载页 https://downloads.apache.org/sdap/1.4.0/ 提供 nexus、nexusproto、ingester 三个源码包(均无二进制)。其中 ingester 源码包约 198MB,依赖整套 Spark 集群(spark-submit + granule 摄取链 + RabbitMQ / Cassandra / Solr),本批次跳过实测,其官方安装方式(sbt 构建 + spark-submit 提交)在本文以 ⚠️ 标注说明;nexus 与 nexusproto 已完整实测。

四、部署步骤

4.1 更新软件源并安装基础工具

apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y \
    openjdk-11-jdk-headless python3 python3-pip wget tar net-tools procps lsof

验证版本回显:

# java -version
openjdk version "11.0.32.1" 2026-08-18
OpenJDK Runtime Environment (build 11.0.32.1+1-post-1ubuntu1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 11.0.32.1+1-post-1ubuntu1-22.04-Ubuntu, mixed mode, sharing)

# python3 --version
Python 3.10.12

# pip3 --version
pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10)

4.2 下载官方源码包

cd /opt
wget https://downloads.apache.org/sdap/1.4.0/apache-sdap-nexus-1.4.0-src.tar.gz
wget https://downloads.apache.org/sdap/1.4.0/apache-sdap-nexusproto-1.4.0-src.tar.gz

下载结果回显:

# ls -lh /opt/*.tar.gz
-rw-r--r-- 1 root root 878K Oct 29  2024 apache-sdap-nexus-1.4.0-src.tar.gz
-rw-r--r-- 1 root root  21K Oct 29  2024 apache-sdap-nexusproto-1.4.0-src.tar.gz

⚠️ 受限说明:同目录下另有 apache-sdap-ingester-1.4.0-src.tar.gz(约 198MB)。因 ingester 依赖整套 Spark 摄取链(spark-submit + granule 摄取链 + RabbitMQ / Cassandra),本批次未下载未实测,后续小节涉及其安装步骤处均以 ⚠️ 标注。

4.3 解压源码

cd /opt
tar -xzf apache-sdap-nexus-1.4.0-src.tar.gz
mv apache-sdap-nexus-1.4.0-src /opt/sdap-nexus
mkdir -p /opt/Apache-SDAP
tar -xzf apache-sdap-nexusproto-1.4.0-src.tar.gz -C /opt/Apache-SDAP

nexus 源码关键目录:

  • analysis/webservice/webapp.py —— Web 服务入口(默认端口 8083)
  • analysis/webservice/config/web.ini、algorithms.ini、scheduler.xml —— Web 配置
  • data-access/nexustiles/ —— 瓦片数据访问层(pysolr + cassandra-driver + pyspark)
  • data-access/config/schemas/solr/{nexustiles,dataset}/ —— Solr core schema
  • tools/ —— CLI 工具(build / deletebyquery / domspurge / cdms / rmqmonitor 等)

nexusproto 源码:/opt/Apache-SDAP/apache-sdap-nexusproto-1.4.0-src/src/main/proto/DataTile.proto(protobuf 瓦片定义)。

4.4 安装 Python 依赖(含兼容性修正)

pip3 install tornado==6.1 pysolr==3.9.0 PyYAML schema==0.7.8 pytz utm==0.6.0 \
    shapely==1.8.5 pillow mpld3==0.5.12 geopy psutil importlib-metadata \
    backports-functools-lru-cache boto3 botocore aiohttp s3fs fsspec
pip3 install numpy scipy pandas xarray dask zarr==2.11.3 matplotlib pyproj \
    cassandra-driver elasticsearch urllib3==1.26.2 netcdf4==1.7.4 \
    pyspark==3.2.1 py4j
pip3 install nexusproto protobuf==3.20.3

⚠️ 兼容性修正(实测踩坑,务必按上述版本安装):

  1. nexusproto 的 PyPI 依赖默认锁定 protobuf 3.2.0,与 Python 3.10 不兼容,报 AttributeError: module 'collections' has no attribute 'MutableMapping',必须升级 protobuf==3.20.3;
  2. shapely 2.x 移除了 shapely.geos.WKTReadingError(算法模块导入报 ImportError),必须固定 shapely==1.8.5;
  3. netcdf4 的 pyproject 锁定 1.5.5.1,无 Python 3.10 wheel,改用 1.7.4(manylinux wheel)可正常安装。

4.5 模块导入预检

cd /opt/sdap-nexus
PYTHONPATH=/opt/sdap-nexus/analysis:/opt/sdap-nexus/data-access python3 -c "import nexustiles.nexustiles; import webservice.webapp; import webservice.algorithms; print('import OK')"

回显:

2026-10-12T21:32:28 - webservice.NexusHandler - INFO - Adding algorithm module 'MatchupDoms' with path '/match_spark_doms'
2026-10-12T21:32:28 - webservice.NexusHandler - INFO - Adding algorithm module 'Time Series Spark' with path '/timeSeriesSpark'
import OK

4.6 安装 Solr 8.11.3

cd /opt
wget https://archive.apache.org/dist/lucene/solr/8.11.3/solr-8.11.3.tgz
tar -xzf solr-8.11.3.tgz
mv solr-8.11.3 /opt/solr

⚠️ 踩坑:官方主下载站 downloads.apache.org/lucene/solr/8.11.3/solr-8.11.3.tgz 返回 404,需改用归档站 archive.apache.org(215MB,实测可下载)。

Solr 的 geo 字段还需 jts-core jar(JtsSpatialContextFactory 依赖):

cd /opt
wget https://repo1.maven.org/maven2/org/locationtech/jts/jts-core/1.15.0/jts-core-1.15.0.jar
cp jts-core-1.15.0.jar /opt/solr/server/solr-webapp/webapp/WEB-INF/lib/

💡 说明:nexustiles core 的 managed-schema 中地理字段使用 com.spatial4j.core.context.jts.JtsSpatialContextFactory,必须把 jts-core jar 放入 Solr webapp 的 WEB-INF/lib(官方 apache/sdap-solr-cloud 镜像同样显式 ADD 该 jar)。

4.7 配置 Solr JVM 堆(256-512MB)

编辑 /opt/solr/bin/solr.in.sh:

# 修改前(默认被注释):#SOLR_JAVA_MEM="-Xms512m -Xmx512m"
SOLR_JAVA_MEM="-Xms256m -Xmx512m"

4.8 启动 Solr 并创建 core

cd /opt/solr
./bin/solr start -force

回显:

NOTE: Please install lsof as this script needs it to determine if Solr is listening on port 8983.
Started Solr server on port 8983 (pid=6691). Happy searching!

把源码 schema 拷入 configset 并创建两个 core(nexustiles 瓦片索引 + nexusdatasets 数据集目录):

cd /opt/solr
cp -r /opt/sdap-nexus/data-access/config/schemas/solr/nexustiles server/solr/configsets/nexustiles
cp -r /opt/sdap-nexus/data-access/config/schemas/solr/dataset server/solr/configsets/dataset
rm -f server/solr/configsets/nexustiles/core.properties server/solr/configsets/dataset/core.properties
./bin/solr create_core -c nexustiles -d nexustiles -force
./bin/solr create_core -c nexusdatasets -d dataset -force

回显:

Created new core 'nexustiles'
Created new core 'nexusdatasets'

⚠️ 踩坑(Found multiple cores):源码 schema 目录自带 core.properties,若连同拷入 configset,Solr 重启会报 Found multiple cores with the name [nexustiles]。因为 Solr 用 core.properties 标识 core 实例目录,configset 内不允许存在,必须在拷贝后删除 configsets 下两个 core.properties 再创建 core。

4.9 摄入示例数据(验证用,可选)

数据集目录记录(nexusdatasets core):

curl "http://localhost:8983/solr/nexusdatasets/update?commit=true" -H 'Content-Type: application/json' \
  -d '[{"id":"test-dataset","dataset_s":"test-dataset","store_type_s":"nexusproto","short_name_s":"test-dataset","title_s":"test-dataset","beginning_date_time_dt":"2020-01-01T00:00:00Z","ending_date_time_dt":"2020-12-31T23:59:59Z","slcp_short_name_s":"test-dataset"}]'

瓦片记录(nexustiles core,geo 用 WKT POINT):

curl "http://localhost:8983/solr/nexustiles/update?commit=true" -H 'Content-Type: application/json' \
  -d '[{"id":"test-tile-1","solr_id_s":"test-tile-1","dataset_s":"test-dataset","tile_count_i":1,"geo":"POINT(-120 30)","tile_min_lat":30.0,"tile_max_lat":31.0,"tile_min_lon":-121.0,"tile_max_lon":-119.0,"tile_min_time_dt":"2020-01-01T00:00:00Z","tile_max_time_dt":"2020-12-31T23:59:59Z"}]'

两次 update 响应 JSON 中 responseHeader.status 均为 0,表示提交成功。

💡 说明:nexustiles 使用 managed-schema(动态字段 *_s / *_d / *_f / *_i,必填 solr_id_s);nexusdatasets 使用 dataset 的 schema.xml(字段 ShortName / DataSetId / LongName / Description / SlcpShortName / DOI,uniqueKey 为 id)。

4.10 启动 nexus Web 服务(手动)

cd /opt/sdap-nexus
PYTHONPATH=/opt/sdap-nexus/analysis:/opt/sdap-nexus/data-access \
  python3 analysis/webservice/webapp.py --port=8083 --address=0.0.0.0

启动日志关键行:

- webservice.NexusHandler - INFO - Adding algorithm module 'Backend Services Status' with path '/heartbeat'
- nexus-tile-svc.backends - INFO - Finished dataset update: 1 added, 0 removed, 1 total
- __main__ - INFO - SDAP started in 0:00:04.490194. Starting HTTP listener...

⚠️ 踩坑:webapp.py 启动时若 Solr 未就绪(core 返回 404),后台 _update_datasets 线程抛 pysolr.SolrError,is_update_thread_alive() 返回 False 后进程 exit(-1)。必须先确认 Solr core 正常再启动 nexus。

4.11 systemd 托管

创建 /etc/systemd/system/solr.service:

[Unit]
Description=Apache Solr 8.11.3
After=network.target

[Service]
Type=forking
ExecStart=/opt/solr/bin/solr start -force
ExecStop=/opt/solr/bin/solr stop -force
PIDFile=/opt/solr/bin/solr-8983.pid
Restart=on-failure
User=root

[Install]
WantedBy=multi-user.target

创建 /etc/systemd/system/nexus.service:

[Unit]
Description=Apache SDAP 1.4.0 Nexus Web Service
After=network.target solr.service
Requires=solr.service

[Service]
Type=simple
Environment=PYTHONPATH=/opt/sdap-nexus/analysis:/opt/sdap-nexus/data-access
WorkingDirectory=/opt/sdap-nexus
ExecStart=/usr/bin/python3 /opt/sdap-nexus/analysis/webservice/webapp.py --port=8083 --address=0.0.0.0
Restart=on-failure
User=root

[Install]
WantedBy=multi-user.target

依次启用并启动(每行仅一个单元名):

systemctl daemon-reload
systemctl enable solr
systemctl enable nexus
systemctl start solr
systemctl start nexus

回显:

Created symlink /etc/systemd/system/multi-user.target.wants/solr.service → /etc/systemd/system/solr.service.
Created symlink /etc/systemd/system/multi-user.target.wants/nexus.service → /etc/systemd/system/nexus.service.

状态查看:

systemctl status solr
systemctl status nexus

回显(节选):

● solr.service - Apache Solr 8.11.3
     Active: active (running) since Tue 2026-10-13 00:04:40 UTC; 8s ago
   Main PID: 8900 (java)

● nexus.service - Apache SDAP 1.4.0 Nexus Web Service
     Active: active (running) since Tue 2026-10-13 00:08:36 UTC; 18s ago
   Main PID: 14426 (python3)

⚠️ 踩坑(systemd 反复重启):若 Solr core 未就绪就启动 nexus,Restart=on-failure 会令 nexus 反复重启(每次 exit(-1) 后自动拉起)。排查以 /version、/heartbeat 与 systemctl status nexus 为准,务必先启 Solr、确认 core 正常再启 nexus(unit 已加 Requires=solr.service 兜底顺序)。

4.12 验证(REST 全链路)

curl -s http://localhost:8083/version
curl -s http://localhost:8083/heartbeat
curl -s http://localhost:8083/list
netstat -tlnp | grep -E "8083|8983"

回显:

1.4.0
{"nexusproto": true}
[{"shortName": "test-dataset", "title": "test-dataset", "tileCount": 1, "type": "nexusproto", "start": 1577836800.0, "end": 1609459199.0, "iso_start": "2020-01-01T00:00:00+0000", "iso_end": "2020-12-31T23:59:59+0000", "spatial_extent": "-121.00,30.00,-119.00,31.00"}]
tcp        0      0 0.0.0.0:8083            0.0.0.0:*               LISTEN      14426/python3
tcp6       0      0 :::8983                 :::*                    LISTEN      14161/java

五、配置说明

5.1 Solr JVM 堆内存(256-512MB)

按 4.7 修改 solr.in.sh 后,用如下命令核对实际生效值:

ps -ef | grep [j]ava | head -1 | tr ' ' '\n' | grep -E "^-X(mx|ms)"

回显:

-Xms256m
-Xmx512m

Solr 状态中的内存占用也可佐证(258MB 即 256MB 上限):

# /opt/solr/bin/solr status
Found 1 Solr nodes:
Solr process 14161 running on port 8983
{
  "solr_home":"/opt/solr/server/solr",
  "version":"8.11.3 baa7c80af4278cc8951a344d8e9320386588d12d - houstonputman - 2024-02-05 15:08:45",
  "startTime":"2026-10-13T00:08:05.953Z",
  "uptime":"0 days, 0 hours, 1 minutes, 4 seconds",
  "memory":"74.2 MB (%14.5) of 258 MB"}

5.2 nexus 服务端口与配置目录

  • nexus 默认监听 127.0.0.1:8083,命令行 --address=0.0.0.0 --port=8083 可改为全网卡监听(实测部署即用此参数)。
  • Web 配置目录:/opt/sdap-nexus/analysis/webservice/config/(web.ini、algorithms.ini、scheduler.xml)。
  • 数据集目录配置:/opt/sdap-nexus/data-access/nexustiles/config/datasets.ini.default([solr] host=http://localhost:8983 core=nexusdatasets)。
  • 数据存储后端配置:/opt/sdap-nexus/data-access/nexustiles/backends/nexusproto/config/datastores.ini.default(含 [cassandra]、[solr]、[s3]、[dynamo]、[datastore] 段)。
  • 各参数含义与生产模板详见同专栏配置详解篇。

5.3 ingester 安装步骤(⚠️ 受限)

⚠️ 受限前置说明:ingester(Spark 摄取引擎)源码包约 198MB,官方安装方式为 sbt 构建后以 spark-submit 提交到 Spark 集群(granule 摄取链依赖 RabbitMQ 消息队列、Cassandra/Solr 后端与 collectionConfig.yml 集合配置)。因依赖整套 Spark 集群,本批次未实测,此处仅给出官方步骤概要,不提供实测回显:

  1. 下载 apache-sdap-ingester-1.4.0-src.tar.gz 并解压;
  2. 按官方 docs/build.rst 用 sbt 构建 ingester 各模块;
  3. 编写集合配置 collectionConfig.yml(声明数据集、granule 路径、切片大小);
  4. 以 spark-submit 提交 collection-manager 与 granule-ingester 到 Spark 集群,配置 RabbitMQ / Cassandra / Solr 连接参数。

六、注意事项

  • 启动顺序:先 Solr 后 nexus。nexus 启动即依赖 Solr core 就绪,顺序颠倒会导致 nexus 反复重启。
  • 版本号读取依赖发行元数据:/version 通过 pkg_resources.get_distribution("sdap-nexus") 读取版本。直接运行源码且未注册发行元数据时 /version 会返回 500,需在项目内注册 sdap_nexus.egg-info(PKG-INFO 写入 Name: sdap-nexus、Version: 1.4.0)后重启服务。
  • /list 缓存:DataSeriesList 带 1 小时 TTL 缓存,首次查询空结果会被缓存;摄入新数据后需重启 nexus 才能在 /list 看到新数据集。
  • 生产托管:建议使用 systemd(见 4.11),不要用 nohup 后台裸跑。
  • 端口规划:8083(nexus REST)、8983(Solr);生产环境注意防火墙放行。

七、常见问题

Q1:Solr 8.11.3 下载 404

原因:downloads.apache.org/lucene/solr/8.11.3/ 路径已归档下线。 解决:改用 archive.apache.org/dist/lucene/solr/8.11.3/solr-8.11.3.tgz(实测 215MB 可下载)。

Q2:Solr 重启报 Found multiple cores with the name [nexustiles]

原因:configset 目录里混入了源码 schema 自带的 core.properties,Solr 误将其识别为 core 实例目录。 解决:删除 server/solr/configsets/nexustiles/core.properties 与 server/solr/configsets/dataset/core.properties 后重启 Solr 并重建 core。

Q3:pip 安装 nexusproto 后导入报 AttributeError: module 'collections' has no attribute 'MutableMapping'

原因:protobuf 3.2.0 与 Python 3.10 不兼容(collections.MutableMapping 在 Python 3.10 已移除)。 解决:升级 protobuf==3.20.3 后重新导入。

Q4:算法模块导入报 ImportError: cannot import name 'WKTReadingError'

原因:shapely 2.x 移除了 shapely.geos.WKTReadingError,而 SDAP 1.4.0 算法代码仍引用它。 解决:固定安装 shapely==1.8.5。

Q5:systemd 下 nexus 反复重启(journal 里反复出现 exit code 1)

原因:Solr core 未就绪时 _update_datasets 抛 pysolr.SolrError,进程 exit(-1),Restart=on-failure 持续拉起。 解决:先 systemctl start solr 并确认 solr status 正常、core 可访问,再启 nexus。

Q6:curl http://localhost:8083/version 返回 500

原因:pkg_resources.get_distribution("sdap-nexus") 找不到发行元数据(直接运行源码未安装)。 解决:在项目内注册 sdap_nexus.egg-info/PKG-INFO(写入 Name: sdap-nexus、Version: 1.4.0)后重启 nexus。

Q7:摄入数据后 /list 仍为空

原因:DataSeriesList 的 1 小时 TTL 缓存,首次空结果被缓存。 解决:重启 nexus 服务清缓存后再查询。

Q8:/datainbounds 报 Bad Y value 或 badly formed hexadecimal UUID string

原因:b 参数格式错误(应为 minLon,minLat,maxLon,maxLat)或瓦片 id 不是 UUID 格式。 解决:按 minLon,minLat,maxLon,maxLat 传参;瓦片 id 使用标准 UUID。

八、卸载方式

systemctl stop nexus
systemctl stop solr
systemctl disable nexus
systemctl disable solr
rm -f /etc/systemd/system/nexus.service /etc/systemd/system/solr.service
systemctl daemon-reload
rm -rf /opt/sdap-nexus /opt/solr /opt/Apache-SDAP
apt-get remove -y openjdk-11-jdk-headless

九、参考链接