You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark应用连接SSL启用Mongo集群报错求助(自签名证书)

解决Spark连接启用SSL的Mongo集群(自签名证书)的SSL握手错误

看起来你遇到的是典型的SSL握手失败问题,根源有两个:一是你的自签名证书里没有包含连接用的CLUSTER_NAME(主机名不匹配),二是当前的TrustAllX509TrustManager只跳过了证书信任校验,但没处理主机名验证的问题。结合你的Spark 2.2.0 + Mongo 3.4环境,给你几个针对性的解决方案:

方案1:修正自签名证书(生产环境推荐)

这个方案从根源解决问题,确保证书的主机名与你连接的集群名称匹配:

  • 重新生成自签名证书时,务必在**Common Name(CN)或者Subject Alternative Name(SAN)**字段中包含你的CLUSTER_NAME,如果是副本集,还要添加所有节点的主机名/IP地址。
  • 用openssl生成证书的示例命令:
openssl req -x509 -newkey rsa:4096 -keyout mongo-key.pem -out mongo-cert.pem -days 365 \
  -subj "/CN=CLUSTER_NAME" \
  -addext "subjectAltName=DNS:CLUSTER_NAME,DNS:node1.mongo.local,DNS:node2.mongo.local,IP:192.168.1.10,IP:192.168.1.11"
  • 将生成的证书导入到Spark集群所有节点的JVM信任存储中(路径一般为$JAVA_HOME/jre/lib/security/cacerts),或者在Spark应用中指定证书路径。

方案2:临时禁用主机名验证(仅限测试环境)

如果只是测试环境想快速打通连接,可以在Mongo连接URI中添加sslInvalidHostNameAllowed=true参数,跳过主机名匹配检查:

  • 修改你的URI生成代码:
val uri: String = "mongodb://" + URLEncoder.encode(Login, "UTF-8") + ":" + URLEncoder.encode(Password, "UTF-8") + "@" + cluster + ":27017/" + database + "." + collection + "?authSource=" + (if (authenticationDatabase != "") authenticationDatabase else "admin") + (if (replicaset == null) "" else "&replicaSet=" + replicaset) + "&ssl=true&sslInvalidHostNameAllowed=true"

注意:这个方法会降低连接安全性,绝对不能在生产环境使用。

方案3:正确配置自定义SSL信任(生产规范做法)

不要用TrustAllX509TrustManager这种完全信任所有证书的方式,应该只信任你的自签名证书,同时保留主机名验证(如果证书已修正):

import java.io.FileInputStream
import java.security.cert.X509Certificate
import java.security.{KeyStore, SecureRandom}
import javax.net.ssl.{SSLContext, TrustManagerFactory, CertificateFactory}
import com.mongodb.client.MongoClients
import com.mongodb.connection.SslSettings
import com.mongodb.MongoClientSettings

// 加载你的自签名证书
val certPath = "/path/to/your/mongo-cert.pem"
val certInputStream = new FileInputStream(certPath)
val certFactory = CertificateFactory.getInstance("X.509")
val mongoCert = certFactory.generateCertificate(certInputStream).asInstanceOf[X509Certificate]

// 创建仅信任该证书的信任管理器
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
keyStore.load(null, null)
keyStore.setCertificateEntry("mongo-trust-cert", mongoCert)
trustManagerFactory.init(keyStore)
val trustManagers = trustManagerFactory.getTrustManagers

// 初始化SSLContext
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustManagers, new SecureRandom())

// 构建Mongo客户端配置
val mongoClientSettings = MongoClientSettings.builder()
  .applyConnectionString(com.mongodb.ConnectionString(uri))
  .sslSettings(SslSettings.builder()
    .enabled(true)
    .sslContext(sslContext)
    // 如果证书仍未匹配主机名,测试环境可临时开启这行,生产环境请删除
    //.invalidHostNameAllowed(true)
    .build())
  .build()

// 创建Mongo客户端
val mongoClient = MongoClients.create(mongoClientSettings)

额外注意事项

  • 确保Spark使用的Mongo驱动版本与Mongo 3.4兼容(推荐使用Mongo Java Driver 3.6.x版本,Spark 2.2.0对应的mongo-spark-connector版本建议选2.2.x)。
  • 如果Spark以集群模式运行,要保证所有Worker节点都能访问到证书文件,或者将证书统一导入到所有节点的JVM信任存储中。

内容的提问来源于stack exchange,提问作者knowledge_seeker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:51:54