Protryon / klickhouse

Rust crate for accessing Clickhouse
Apache License 2.0
92 stars 21 forks source link

Connect to Clickhouse Cloud server causes UnexpectedEof #44

Closed jona-wilmsmann closed 8 months ago

jona-wilmsmann commented 8 months ago

This may be a Clickhouse Cloud issue rather than a klickhouse issue, and I also cannot fully rule out that it was user error, but considering the prominent position that Clickhouse Cloud has for Clickhouse I thought it might be useful to still report.

I was unable to connect to clickhouse cloud, with the Client::connect() function returning ProtocolError("failed to receive blocks from upstream: channel closed"). I tracked this down to the receive_hello function, which receives a packet (Io(Custom { kind: UnexpectedEof, error: "early eof" })).

Connecting to a clickhouse server running locally (set up with a password as well) in docker works. Attempting to connect to the local clickhouse server with an invalid password returns a differnt packet (code 516, authorization failed), so this is not just the response to wrong login data.

In general, I verified that I could connect to the clickhouse server using the same username / password, and I also verified that the connection worked without TLS to ensure it wasn't that.

Since it seems like this is an error with the protocol / serialization, I am afraid I'm unqualified to track this down further myself.

To reproduce, I used a free trial Clickhouse Cloud account with a development setup on Google Cloud.

Protryon commented 8 months ago

I've never tried to use clickhouse cloud, or this library in particular with it. Does it have an authentication scheme other than username/password? Also, I assume that the clickhouse CLI works to access the cloud?

jona-wilmsmann commented 8 months ago

It also just uses username and password.

On top of that, it has an optional IP access list (where only added IPs can access the server). Just to confirm it wasn't that, I turned that off and tried again, and that wasn't it. Also wouldn't really be consistent considering the connection does seem to work in general.

Yes, the clickhouse CLI does work. I was also able to connect with a different crate, but that works with a HTTP connection, so not really comparable.

jona-wilmsmann commented 8 months ago

After working with the Clickhouse Cloud support I figured out that I was trying to connect to a port that only supports a TLS connection, which explains the error. I haven't figured out what the correct port to use is unfortunately, since port 9000 is just giving me a timeout error. But regardless, this seems like a Clickhouse Cloud problem and not a klickhouse problem, so I'm closing this issue.

MichalGabonay commented 6 months ago

I have problem to connect to the Clickhouse cloud. Can you please provide example, how you was able to make it work? Thanks. My calling looks like this:

    let client = klickhouse::Client::connect(
        "<appkey>.eu-west-1.aws.clickhouse.cloud:9440",
        ClientOptions {
            username: "default".to_string(),
            password: "<password>".to_string(),
            default_database: "default".to_string(),
        },
    )
    .await
    .unwrap();

    client
        .insert_native_block(
            "INSERT INTO rocks SETTINGS  FORMAT native",
            rows,
        )
        .await
        .unwrap();
negezor commented 6 months ago

@MichalGabonay Is the problem occurring on the first connection? Or with prolonged use? Is feature tls used?

MichalGabonay commented 6 months ago

My problem is with the first connection. I got an error ProtocolError("failed to receive blocks from upstream: channel closed"). I am able to make it work with crate clickhouse-rs, which should be very similar to klickhouse (native protocol, TCP, connection, TLS, ...), so there should be a way on how to connect to cloud clickhouse. Feature tls is used, but I am calling connect and not connect_tls because I was not able to use it (I don't know what to fill into name and connector). If this is a problem, I would appreciate the example, on how to call it with TLS.

negezor commented 6 months ago

If you are connecting without TLS, then you need to use a different port. Try this (I don't know how AWS cloud will work):

let client = klickhouse::Client::connect(
        "<appkey>.eu-west-1.aws.clickhouse.cloud:9000",
        ClientOptions {
            username: "default".to_string(),
            password: "<password>".to_string(),
            default_database: "default".to_string(),
        },
    )
    .await
    .unwrap();
MichalGabonay commented 6 months ago

I tried ports 9440, 9000, and 8443, but none of them worked. clickhouse-rs works with port 9440.

jona-wilmsmann commented 6 months ago

To add some context, I was told by the clickhouse cloud support that clickhouse cloud only supports TLS connections. I switched to a self hosted server so didn't have to deal with this after all, but I strongly assume that you need to use connect_tlsto make this work.

I also am unsure what the extra parameters need to be though (some extra documentation or an example would be helpful)

MichalGabonay commented 6 months ago

@negezor Can you please provide example how to use klickhouse with connect_tls? It would be very helpful. Thanks.