avatica-go client read Phoenix Query Server:[driver: bad connection]

99 Views Asked by At

Hbase 2.0.0v Phoenix 5.0.0v Avatica-go-client 5.2.0v Nginx 1.8.1 with sticky module

3 Regionserver,3 Query Server , Nginx configed stick load balance for 3Query server

nginx conf nginx in 192.168.3.236

upstream phoenix_balance {
        sticky expires=1m;
        server 192.168.3.190:8765;
        server 192.168.3.236:8765;
        server 192.168.3.165:8765;
    }

server {

        listen 8766;
        server_name localhost;
        location / {
                proxy_pass http://phoenix_balance/;
        }
    }

when i use Java to Read PQS its ok(connect one PQS, connect load balance url),

Class.forName("org.apache.phoenix.queryserver.client.Driver");
String url = "jdbc:phoenix:thin:url=http://192.168.3.236:8766;serialization=PROTOBUF";
conn = DriverManager.getConnection(url, prop);

i use go to connect one PQS its ok,connect to load balance url its failed, code from avatica-go-client-reference

db, err := sql.Open("avatica", "http://192.168.3.236:8765") //ok
db, err := sql.Open("avatica", "http://192.168.3.236:8766") // faield ,driver:bad connection
rows, err := db.Query("SELECT COUNT(*) FROM test.test1")

Is there a problem with my nginx configuration?

I really hope someone can answer this question for me

1

There are 1 best solutions below

0
Zeke Lu On

I guess the reason is that the Avatica Go client does not support cookies. We can provide our own baseClient that supports cookies to the connector. See the demo below:

Note: I don't have the environment to test the implementation. Please let me know if it does not work and I will look into it. Thank you!

package main

import (
    "context"
    "database/sql"
    "database/sql/driver"
    "fmt"
    "net"
    "net/http"
    "net/http/cookiejar"
    "runtime"
    "time"

    avatica "github.com/apache/calcite-avatica-go/v5"
    "golang.org/x/net/publicsuffix"
)

func init() {
    sql.Register("sticky-avatica", &StickyDriver{})
}

type StickyDriver struct{}

func (d *StickyDriver) Open(dsn string) (driver.Conn, error) {
    jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
    if err != nil {
        return nil, err
    }

    // Create our own baseClient that supports cookies.
    baseClient := &http.Client{
        Transport: &http.Transport{
            Proxy: http.ProxyFromEnvironment,
            DialContext: (&net.Dialer{
                Timeout:   30 * time.Second,
                KeepAlive: 30 * time.Second,
            }).DialContext,
            MaxIdleConns:          100,
            IdleConnTimeout:       90 * time.Second,
            TLSHandshakeTimeout:   10 * time.Second,
            ExpectContinueTimeout: 1 * time.Second,
            MaxIdleConnsPerHost:   runtime.GOMAXPROCS(0) + 1,
        },
        Jar: jar,
    }

    // Since we create our own baseClient, the auth method provided in the DSN
    // string is not applied. If this is needed, set it manually. See:
    // https://github.com/apache/calcite-avatica-go/blob/ed4c274f52a98593e6c99de0d7a88802d4a92cb6/http_client.go#L72-L85

    connector := avatica.NewConnector(dsn).(*avatica.Connector)

    // Provide our own baseClient to the connector.
    connector.Client = baseClient

    return connector.Connect(context.TODO())
}

func main() {
    db, err := sql.Open("sticky-avatica", "http://192.168.3.236:8766")
    if err != nil {
        panic(err)
    }
    rows, err := db.Query("SELECT COUNT(*) FROM test.test1")
    if err != nil {
        panic(err)
    }
    defer rows.Close()

    fmt.Printf("%v\n", rows)
}