能否通过反向代理使用Java SDK连接Azure Cosmos DB?
错误原因说明
- 第一种配置报错原因:你直接将
AccountSettings.HOST设为https://localhost:3308时,请求发到Cosmos服务端的Host头为localhost,而Cosmos DB仅识别自身官方域名(你的实例域名my-instance-cosmos-dev.documents.azure.com),因此直接返回403错误提示账户不存在。 - 第二种配置报错原因:你将Nginx配置为正向HTTP代理传入SDK,但你部署的Nginx是反向代理服务,未配置支持正向代理所需的CONNECT方法,因此SDK发起代理连接请求时直接超时,触发SSL握手失败。
模式说明
这种通过反向代理转发访问Cosmos DB的模式是官方支持的,你当前的问题是对代理类型和SDK配置逻辑存在误解:SDK的ProxyOptions是给正向HTTP/HTTPS代理场景用的,你部署的Nginx属于反向代理,不需要走代理配置,直接将代理地址作为Cosmos endpoint访问即可。
修正步骤
- 第一步:调整Nginx配置,补全SSL透传、Host头重写、SNI配置,修正后的配置片段如下:
server { listen {{ .Values.cosmosDB.port }} ssl so_keepalive=on; # 此处需要配置Nginx的ssl_certificate和ssl_certificate_key,使用自签证书或正规证书都可 ssl_certificate /path/to/your/cert.pem; ssl_certificate_key /path/to/your/key.pem; proxy_connect_timeout 5s; proxy_timeout 60m; proxy_buffer_size 30M; proxy_socket_keepalive on; proxy_ssl_session_reuse on; # 开启SNI透传,否则Cosmos服务端无法识别你要访问的实例 proxy_ssl_server_name on; # 重写Host头为Cosmos实例域名,解决账户不存在的问题 proxy_set_header Host my-instance-cosmos-dev.documents.azure.com; proxy_pass https://my-instance-cosmos-dev.documents.azure.com:443; }
- 第二步:关闭SDK的端点自动发现功能,避免SDK自动获取Cosmos官方区域端点绕开代理
- 第三步:无需配置
ProxyOptions,直接将本地端口转发的地址作为endpoint传入SDK,使用自签证书的场景可按需配置跳过SSL主机名验证 - 修正后的Java客户端代码示例如下:
client = new CosmosClientBuilder() .endpoint("https://localhost:3308") // 直接用反向代理地址作为endpoint .key(AccountSettings.MASTER_KEY) .endpointDiscoveryEnabled(false) // 关闭端点发现 .gatewayMode() .preferredRegions(Collections.singletonList("你的Cosmos实例所在区域,比如ChinaEast2")) .userAgentSuffix("CosmosDBJavaQuickstart") .consistencyLevel(ConsistencyLevel.EVENTUAL) .buildClient();
额外排查点
如果还是报SSL错误,可以先本地用curl测试代理是否正常:curl https://localhost:3308 -k -H "x-ms-version: 2018-12-31" -H "Authorization: 你的Cosmos密钥签名",确认代理链路通了再调试SDK。
内容的提问来源于stack exchange,提问作者Funsaized
相关产品推荐
相关产品推荐

