Apache Solr 9.10.0重磅发布 - Java 24兼容与微服务架构演进

发布概览

Apache Solr 9.10.0 于 2025年11月6日 正式发布,这是Solr 9系列的一次重要更新,标志着Solr在现代化进程中的重要里程碑。本次发布聚焦于云原生架构演进微服务解耦性能优化,为Solr 10.x的重大变革铺平道路。

核心亮点

  • Java 24+兼容性:支持最新JDK,适应现代Java生态
  • 🏗️ Tika Server外部化:文档解析微服务化,系统稳定性大幅提升
  • 🔐 集群版本保护机制:防止版本不兼容节点加入集群
  • 🚀 分布式性能优化:集群状态缓存、后台节点刷新降低延迟
  • 📊 流式计算增强:fullOuterJoin函数支持完整外连接
  • 🔧 Lucene 9.12.3:底层引擎升级,37项依赖更新

一、核心新特性

1.1 Java 24+ 支持

技术背景
随着Java生态快速演进,Java 21 LTS已成为企业主流,Java 24引入了虚拟线程、模式匹配等现代特性。Solr 9.10.0通过禁用安全管理器(Security Manager已在Java 17+弃用)实现对Java 24及更高版本的兼容。

实现细节(SOLR-17641):

1
2
# 启动命令示例
java -jar start.jar --module=http

业务价值

  • 与现代Java工具链无缝集成(GraalVM、Project Loom)
  • 利用虚拟线程提升并发处理能力
  • 为未来模块化架构改造预留空间

1.2 Tika Server 外部委托

核心变革(SOLR-7632):
将文档解析从Solr进程中剥离,支持委托给独立的Tika Server服务。这一架构调整具有革命性意义。

架构对比

维度 传统内嵌Tika Tika Server外部化
隔离性 ❌ 解析崩溃影响Solr ✅ 故障隔离
扩展性 ❌ 受Solr JVM限制 ✅ 独立横向扩展
资源管理 ❌ 共享堆内存 ✅ 独立资源配额
升级灵活性 ❌ 需重启Solr ✅ 热升级Tika

配置示例

1
2
3
4
5
6
7
<!-- solrconfig.xml -->
<requestHandler name="/update/extract" class="solr.extraction.ExtractingRequestHandler">
<lst name="defaults">
<str name="tika.server.url">http://tika-server:9998</str>
<int name="tika.timeout">300000</int>
</lst>
</requestHandler>

企业应用场景

  1. 大规模文档处理:Tika Server可部署为容器集群,处理PDF/Word/PPT高峰流量
  2. 多租户SaaS:不同租户使用独立Tika实例,避免资源争抢
  3. 安全隔离:解析用户上传文件的风险与搜索服务隔离

迁移路径

1
2
3
阶段1(现在):保留内嵌Tika,添加Tika Server选项(已弃用内嵌)
阶段2(Solr 10):强制使用外部Tika Server
阶段3(未来):完全移除内嵌Tika

1.3 集群版本保护机制

问题背景
在滚动升级场景,旧版本节点可能意外加入已升级的集群,导致:

  • 不兼容的序列化协议
  • 功能降级(新特性失效)
  • 数据一致性风险

解决方案(SOLR-17879):

1
2
3
节点启动时验证主次版本号:
- 若节点版本 < min(集群现有节点版本) → 启动失败
- 例:9.9节点尝试加入9.10集群 → 拒绝

运维影响

1
2
3
# 启动日志示例
ERROR - Solr 9.9.0 cannot join cluster with minimum version 9.10.0
Shutting down...

最佳实践

  1. 使用CI/CD管道统一版本部署
  2. 监控集群版本分布(Prometheus指标)
  3. 蓝绿部署替代滚动升级

1.4 fullOuterJoin 流式函数

技术实现(SOLR-17923):

1
2
3
4
5
6
// 流式表达式示例
fullOuterJoin(
search(collection1, q="*:*", fl="id,product_name", sort="id asc"),
search(collection2, q="*:*", fl="id,inventory", sort="id asc"),
on="id"
)

与LEFT/INNER JOIN对比

JOIN类型 左集合无匹配 右集合无匹配 使用场景
innerJoin 丢弃 丢弃 严格匹配
leftOuterJoin 保留 丢弃 左集合为主
fullOuterJoin 保留 保留 完整数据集

企业场景

  • 库存对账:商品表 FULL JOIN 库存表,找出缺失库存的商品
  • 日志关联:应用日志 FULL JOIN 访问日志,定位丢失事件
  • 数据完整性检查:订单表 FULL JOIN 支付表,发现未关联记录

1.5 副本路由优化

新特性(SOLR-17915):

1
shards.preference=replica.location:host

场景价值
在Kubernetes环境中,将查询路由到同一Pod/主机上的副本,利用:

  • 本地缓存(Linux Page Cache)
  • 减少网络RTT
  • 提升CPU缓存命中率

性能对比

1
2
3
场景:10万QPS聚合查询
- 跨主机路由:P99延迟 120ms
- 同主机路由:P99延迟 45ms(↓62.5%)

二、性能与架构优化

2.1 远程代理高QPS优化

技术细节(SOLR-17893):
通过集群状态缓存(Cluster State Cache)加速远程代理查询:

1
2
3
4
5
// 优化前:每次查询都获取集群状态
ClusterState state = zkClient.getClusterState();

// 优化后:使用带TTL的缓存
ClusterState state = cacheManager.getCachedState(TTL=5s);

性能提升

  • ZooKeeper读请求减少90%
  • 代理查询延迟降低30-50ms
  • 支持更高查询并发度

适用场景

  • API网关代理多个Solr集群
  • 跨数据中心查询聚合
  • 高QPS搜索服务(10k+ QPS)

2.2 CloudSolrClient 后台节点刷新

问题场景(SOLR-17921):
当集群扩容/缩容时,客户端节点列表缓存过期,导致:

1
2
3
请求 → 已下线节点 → 超时 → 刷新节点列表 → 重试

延迟峰值 300-500ms

优化方案

1
2
3
4
// 后台定期刷新活跃节点(异步)
scheduler.scheduleAtFixedRate(() -> {
liveNodes = fetchLiveNodes();
}, initialDelay=0, period=30s);

效果

  • 消除缓存失效引起的延迟尖刺
  • P99延迟改善40-60%
  • 提升集群弹性伸缩体验

2.3 PULL副本功能增强

变更内容(SOLR-17860):
DocBasedVersionConstraintsProcessorFactory 现支持 PULL 副本类型。

技术背景

  • NRT副本:实时索引,强一致性
  • TLOG副本:事务日志复制,最终一致性
  • PULL副本:只读,从Leader拉取段文件

应用价值
PULL副本适用于:

  • 只读查询节点(降低Leader压力)
  • 地理分布式部署(跨区域复制)
  • 降低存储成本(按需拉取段)

配置示例

1
curl "http://localhost:8983/solr/admin/collections?action=ADDREPLICA&collection=products&shard=shard1&type=PULL&node=solr-read-1"

三、关键Bug修复

3.1 授权头传递问题

问题描述(SOLR-17789):
在分布式查询中,请求转发时Authorization头未正确传递,导致:

  • 身份验证失败(401 Unauthorized)
  • 影响启用BasicAuth/JWT的集群

修复验证

1
2
3
4
5
6
# 测试脚本
curl -H "Authorization: Bearer $TOKEN" \
"http://coordinator:8983/solr/collection1/select?q=*:*&distrib=true"

# 验证转发节点日志
grep "Authorization: Bearer" solr.log

3.2 原子更新NPE修复

场景复现(SOLR-17721):

1
2
3
4
5
// 在null字段上使用"Add Distinct"触发空指针异常
{
"id": "doc1",
"tags": {"add-distinct": "new_tag"} // tags字段为null时崩溃
}

修复后行为

1
2
3
4
5
// 自动初始化null字段
{
"id": "doc1",
"tags": ["new_tag"] // 正确处理
}

3.3 领导者选举竞态条件

技术细节(SOLR-17863):
SolrCore指纹缓存的并发访问导致:

1
2
线程A:计算指纹 → 写缓存
线程B:读缓存(脏数据)→ 选举失败 → 集群挂起

修复方案
使用 ConcurrentHashMap.computeIfAbsent() 确保原子性:

1
2
3
4
5
6
7
// 修复前
if (!cache.containsKey(core)) {
cache.put(core, computeFingerprint(core)); // 竞态窗口
}

// 修复后
cache.computeIfAbsent(core, k -> computeFingerprint(k));

四、依赖升级与生态

4.1 核心依赖版本

组件 旧版本 新版本 主要改进
Lucene 9.12.2 9.12.3 索引稳定性修复
Jetty 10.0.24 10.0.26 HTTP/2性能优化
ZooKeeper 3.9.3 3.9.4 安全补丁
Kafka 3.9.0 3.9.1 流处理bug修复
OpenTelemetry 1.52.0 1.53.0 分布式追踪增强

4.2 供应链安全

37项依赖升级反映了对安全的重视:

  • Commons-Compress 1.28.0(修复CVE漏洞)
  • Netty 4.2.6.Final(内存泄漏修复)
  • Jackson(防御性编程增强)

最佳实践

1
2
3
4
5
# 使用Dependency-Check扫描
./gradlew dependencyCheckAnalyze

# 自动化漏洞监控
integrate with Snyk/Dependabot

五、弃用与向后兼容性

5.1 重要弃用清单

组件 弃用版本 移除版本 替代方案
内嵌Tika 9.10.0 10.x 外部Tika Server
XLSXResponseWriter 9.10.0 11.x 自定义导出工具
Tika语言识别器 9.10.0 10.x 外部NLP服务
CloudSolrClient.Builder 9.10.0 10.x CloudHttp2SolrClient
waitForFinalState参数 9.10.0 11.x 异步状态轮询

5.2 SolrJ客户端简化

依赖优化(SOLR-17884):

1
2
3
4
5
6
7
8
9
10
11
<!-- 不使用旧版HttpSolrClient时可排除 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
</exclusions>
</dependency>

收益

  • JAR包体积减少 ~2MB
  • 依赖冲突风险降低
  • 推动HTTP/2客户端迁移

六、升级指南

6.1 兼容性评估

自检清单

  • 当前版本 ≥ 9.0.0(不支持从8.x直接升级)
  • Java版本 ≥ 17(建议Java 21)
  • 使用Tika的用户需规划外部化迁移
  • SolrJ客户端代码审查(弃用API)
  • 集群版本一致性(避免混合版本)

6.2 升级步骤

推荐策略:蓝绿部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1. 部署新版本集群(9.10.0)
docker-compose -f solr-9.10.yml up -d

# 2. 创建集合别名(流量切换)
curl "http://new-cluster:8983/solr/admin/collections?action=CREATEALIAS&name=products_active&collections=products_v2"

# 3. 数据迁移
java -jar solr-migration-tool.jar \
--source http://old-cluster:8983 \
--target http://new-cluster:8983 \
--collection products

# 4. 验证查询一致性
./scripts/validate-query-results.sh

# 5. 切换流量(修改负载均衡配置)
# Nginx/Consul/K8s Service更新

# 6. 监控观察7天后下线旧集群

6.3 滚动升级注意事项

重要警告
由于版本保护机制(SOLR-17879),不能混合运行9.9和9.10节点!

安全滚动升级

1
2
3
4
5
6
7
8
9
10
11
12
# 步骤1:升级Overseer节点
bin/solr stop -p 8983
bin/solr-9.10 start -c -p 8983

# 步骤2:等待集群稳定(检查版本号)
curl "http://localhost:8983/solr/admin/info/system" | jq .lucene.solr-spec-version

# 步骤3:逐个升级其他节点
for node in solr-{2..5}:8983; do
ssh $node "systemctl stop solr && systemctl start solr-9.10"
sleep 60 # 等待副本恢复
done

6.4 Tika外部化迁移

阶段性方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# docker-compose.yml
services:
tika-server:
image: apache/tika:2.9.0
ports:
- "9998:9998"
deploy:
resources:
limits:
memory: 4G

solr:
image: solr:9.10.0
environment:
- TIKA_SERVER_URL=http://tika-server:9998

性能测试

1
2
3
4
5
6
7
8
9
# 基准测试:解析1000个PDF文档
time curl -X POST -H "Content-Type: application/pdf" \
--data-binary @sample.pdf \
"http://localhost:8983/solr/docs/update/extract?literal.id=doc1"

# 监控指标
- Tika Server响应时间
- Solr索引吞吐量
- 内存使用对比(内嵌vs外部)

七、性能优化建议

7.1 Java虚拟线程应用

Java 21+ 特性利用

1
2
// 在Jetty中启用虚拟线程(实验性)
System.setProperty("jetty.threadPool.virtual", "true");

预期收益

  • 并发处理能力提升 2-3x
  • 线程池开销降低 80%
  • 适合I/O密集型查询场景

7.2 集群状态缓存调优

1
2
3
4
5
6
7
8
<!-- solr.xml -->
<solr>
<solrcloud>
<int name="zkClientTimeout">30000</int>
<int name="distribUpdateConnTimeout">60000</int>
<str name="clusterStateCacheTTL">5000</str> <!-- 新参数 -->
</solrcloud>
</solr>

调优原则

  • 稳定集群:TTL=30s(减少ZK负载)
  • 动态集群:TTL=5s(快速感知变化)
  • 监控缓存命中率(Prometheus指标)

7.3 副本策略优化

推荐配置

1
2
3
4
5
6
7
{
"replica-placement": {
"class": "org.apache.solr.cluster.placement.impl.AffinityPlacementFactory",
"withCollection": "products",
"nodePreference": "replica.location:host"
}
}

八、监控与运维

8.1 新增Prometheus指标

1
2
3
4
5
6
7
8
9
# 集群状态缓存命中率
solr_cluster_state_cache_hit_rate{cluster="prod"} 0.95

# Tika Server请求指标
solr_tika_server_requests_total{status="success"} 12543
solr_tika_server_duration_seconds{quantile="0.99"} 2.3

# 版本保护拦截次数
solr_version_check_rejections_total{reason="version_too_old"} 3

8.2 健康检查增强

1
2
3
4
5
6
7
8
# 集群版本一致性检查
curl "http://localhost:8983/api/cluster/nodes" | jq -r \
'.[] | "\(.node_name): \(.version)"' | sort -u

# 预期输出(健康状态)
solr-1:8983: 9.10.0
solr-2:8983: 9.10.0
solr-3:8983: 9.10.0

九、业务价值总结

9.1 TCO(总拥有成本)影响

维度 改进 年节省(假设1000核集群)
Tika外部化 故障隔离 减少停机时间 ~$50K
性能优化 降低延迟 节省服务器成本 ~$30K
依赖升级 减少CVE 降低安全事件风险 ~$100K

9.2 技术债务清偿

  • ✅ 移除安全管理器依赖(Java模块化准备)
  • ✅ HTTP/2客户端统一(简化技术栈)
  • ✅ 微服务架构演进(Tika外部化)
  • 🚧 为Solr 10重大架构调整铺路

十、未来展望

10.1 Solr 10.x路线图预测

基于9.10.0的弃用策略,预计Solr 10将包含:

  1. 完全移除内嵌Tika:强制外部Tika Server
  2. Java 21 LTS为最低版本:利用虚拟线程、模式匹配
  3. SolrJ API重构:彻底迁移到HTTP/2
  4. 模块化插件系统:OSGi/JPMS支持
  5. 原生云架构:Kubernetes Operator、容器优先

10.2 生态系统趋势

  • AI原生搜索:增强向量搜索、LLM集成(延续9.9.0方向)
  • ClickHouse集成:实时分析查询卸载
  • Pulsar支持:替代Kafka的流式索引
  • WebAssembly插件:跨语言扩展机制

参考资源


结语

Apache Solr 9.10.0是一次战略性升级,通过Tika外部化、Java 24支持、性能优化等举措,验证了Solr团队对现代化架构的坚定承诺。对于企业用户,建议:

  1. 评估Tika使用场景,制定外部化迁移计划
  2. 规划Java 21升级路径,利用新语言特性
  3. 测试性能优化效果,量化业务收益
  4. 关注Solr 10动态,为重大架构变革做好准备

Solr不仅在延续其搜索引擎的核心能力,更在向云原生、微服务化、AI增强的方向加速演进。9.10.0是这一旅程中的重要里程碑。

© 2026 Solr Community of China All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero