是否可以使用 Java SDK 通过反向代理连接到 Azure Cosmos DB?

Posted

技术标签:

【中文标题】是否可以使用 Java SDK 通过反向代理连接到 Azure Cosmos DB?【英文标题】:Is it possible to connect to Azure Cosmos DB via a reverse proxy using Java SDK? 【发布时间】:2021-11-27 15:07:53 【问题描述】:

我正在尝试使用 java sdk 连接到 cosmos。我有一个在 AKS 中运行的 nginx 代理指向我的 cosmos 实例(下面是 nginx.conf 的子集):

  server 
    listen  .Values.cosmosDB.port  so_keepalive=on;
    proxy_connect_timeout 5s;
    proxy_timeout 60m;
    proxy_buffer_size 30M;
    proxy_socket_keepalive on;
    proxy_ssl_session_reuse on;
    proxy_pass my-instance-cosmos-dev.documents.azure.com:443;
  

我的想法是,通过端口转发,我可以通过这个代理使用我的本地作为 cosmos 主机 url:

kubectl port-forward svc/data-proxy 3308:443

运行 java 的快速入门(通过 Azure 门户生成)我无法配置连接的 cosmos 客户端。我尝试了几种配置:

默认网关模式:

        client = new CosmosClientBuilder()
            .endpoint(AccountSettings.HOST)
            .key(AccountSettings.MASTER_KEY)
            .endpointDiscoveryEnabled(true)
            .gatewayMode()
            .userAgentSuffix("CosmosDBJavaQuickstart")
            .consistencyLevel(ConsistencyLevel.EVENTUAL)
            .buildClient();

但是这会在启动时返回错误Database Account localhost does not exist

CosmosExceptionuserAgent=azsdk-java-cosmos/4.4.0 MacOSX/10.15.7 JRE/15.0.2, 
error="code":"Forbidden","message":"Database Account localhost does not exist\r\nActivityId: 742a632d-cd00-42b7-8599-8fc6ff1eccad, Microsoft.Azure.Documents.Common/2.14.0, StatusCode: Forbidden","additionalErrorInfo":null, resourceAddress='null', requestUri='null', statusCode=403, message=Database Account localhost does not exist

然后我尝试如下传递代理配置,但收到 SSL 验证错误:

    ProxyOptions opts = new ProxyOptions(ProxyOptions.Type.HTTP,  InetSocketAddress.createUnresolved("127.0.0.1", 3308));
    gatewayConnectionConfig.setProxy(opts);


    gatewayConnectionConfig.setMaxConnectionPoolSize(5);
    
    //  Create sync client
    client = new CosmosClientBuilder()
        .endpoint(AccountSettings.HOST)
        .key(AccountSettings.MASTER_KEY)
        .endpointDiscoveryEnabled(true)
        .gatewayMode(gatewayConnectionConfig)
        .userAgentSuffix("CosmosDBJavaQuickstart")
        .consistencyLevel(ConsistencyLevel.EVENTUAL)
        .buildClient();

输出:

INFO: Getting database account endpoint from http://localhost:3308
Oct 07, 2021 10:01:31 AM com.azure.cosmos.implementation.RxGatewayStoreModel 
lambda$toDocumentServiceResponse$2
SEVERE: Network failure
javax.net.ssl.SSLException: failure when writing TLS control frames
    at io.netty.handler.ssl.SslHandler.setHandshakeFailureTransportFailure(SslHandler.java:1863)
    at io.netty.handler.ssl.SslHandler.access$600(SslHandler.java:167)
    at io.netty.handler.ssl.SslHandler$2.operationComplete(SslHandler.java:978)
    at io.netty.handler.ssl.SslHandler$2.operationComplete(SslHandler.java:973)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:577)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:551)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:490)
    at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:615)
    at io.netty.util.concurrent.DefaultPromise.setFailure0(DefaultPromise.java:608)
    at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:117)
    at io.netty.channel.PendingWriteQueue.safeFail(PendingWriteQueue.java:279)
    at io.netty.channel.PendingWriteQueue.removeAndFailAll(PendingWriteQueue.java:177)
    at io.netty.handler.proxy.ProxyHandler.failPendingWrites(ProxyHandler.java:435)
    at io.netty.handler.proxy.ProxyHandler.failPendingWritesAndClose(ProxyHandler.java:352)
    at io.netty.handler.proxy.ProxyHandler.setConnectFailure(ProxyHandler.java:347)
    at io.netty.handler.proxy.ProxyHandler.access$100(ProxyHandler.java:39)
    at io.netty.handler.proxy.ProxyHandler$2.run(ProxyHandler.java:199)
    at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98)
    at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: io.netty.handler.proxy.ProxyConnectException: http, none, /127.0.0.1:3308 => localhost/<unresolved>:3308, timeout
    ... 10 more

我不确定如何继续。这是受支持的连接模式吗?也许我在这里通过 SDK 误解了客户端设置...

【问题讨论】:

【参考方案1】:

我认为代理方法应该可行,但您必须在连接字符串中写入原始 Cosmos-DB-URL,您在 AccountSettings.HOST 中使用。

我想那里仍然引用了“localhost”,因为您第一次尝试直接访问。但是当您现在通过代理时,应该有真正的 URL。 (my-instance-cosmos-dev.documents.azure.com)

此外,您没有收到 SSL 验证错误,它看起来像是超时。 (因为代理尝试连接本地主机)


如果您确实想使用第一种(直接)方法,那么您可以在 /etc/hosts 中添加一个条目,这将使 cosmos-db SDK 在请求中发送正确的 Host-header。

127.0.0.1 my-instance-cosmos-dev.documents.azure.com

然后你还需要在连接字符串中引用真实的 URL,然后指向 localhost。

【讨论】:

以上是关于是否可以使用 Java SDK 通过反向代理连接到 Azure Cosmos DB?的主要内容,如果未能解决你的问题,请参考以下文章

将 nginx 反向代理连接到应用程序洞察力

如何使用代理从 Cosmos SDK .Net 连接到 Azure Cosmos?

无法使用 Nginx 反向代理连接到 Websocket 服务器

无法通过代理连接到 websocket

Gnirehtetadb安卓手机通过USB连接到电脑上网

我可以在不使用 websockets 的情况下使用本机 mqtt 连接到我的 mqtt 代理吗?