Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java app using MariaDB 2.1.2 driver fails to connect #4603

Closed
derekperkins opened this issue Feb 9, 2019 · 5 comments
Closed

Java app using MariaDB 2.1.2 driver fails to connect #4603

derekperkins opened this issue Feb 9, 2019 · 5 comments

Comments

@derekperkins
Copy link
Member

I'm trying to connect an off the shelf app (prisma.io) to Vitess, but it is failing on the client handshake. It is using mariadb-java-client 2.1.2 to connect. I'm not a Java user, so I don't know how to test/debug this any further.

There is already interest in using Vitess with Prisma in this issue: prisma/prisma#2451

vtgate logs

server.go:295] Cannot parse client handshake response from client 4449 (11.240.2.81:49192): 
parseClientHandshakePacket: can't read connection attribute value

Java client logs

Exception in thread "main" java.sql.SQLTransientConnectionException: database - Connection is not available, request timed out after 5000ms.
	at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:548)
	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:186)
	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:145)
	at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83)
	at slick.jdbc.hikaricp.HikariCPJdbcDataSource.createConnection(HikariCPJdbcDataSource.scala:14)
	at slick.jdbc.JdbcBackend$BaseSession.<init>(JdbcBackend.scala:453)
	at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:46)
	at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:37)
	at slick.basic.BasicBackend$DatabaseDef.acquireSession(BasicBackend.scala:249)
	at slick.basic.BasicBackend$DatabaseDef.acquireSession$(BasicBackend.scala:248)
	at slick.jdbc.JdbcBackend$DatabaseDef.acquireSession(JdbcBackend.scala:37)
	at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:274)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to vtgate-aks.vitess:3306 : unexpected end of stream, read 0 bytes from 4
	at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:161)
	at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.getException(ExceptionMapper.java:106)
	at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1036)
	at org.mariadb.jdbc.internal.util.Utils.retrieveProxy(Utils.java:490)
	at org.mariadb.jdbc.MariaDbConnection.newConnection(MariaDbConnection.java:144)
	at org.mariadb.jdbc.Driver.connect(Driver.java:90)
	at slick.jdbc.DriverDataSource.getConnection(DriverDataSource.scala:101)
	at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:341)
	at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:193)
	at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:430)
	at com.zaxxer.hikari.pool.HikariPool.access$500(HikariPool.java:64)
	at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:570)
	at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:563)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	... 3 more
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to vtgate-aks.vitess:3306 : unexpected end of stream, read 0 bytes from 4
	at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:161)
	at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.connException(ExceptionMapper.java:79)
	at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.handleConnectionPhases(AbstractConnectProtocol.java:724)
	at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connect(AbstractConnectProtocol.java:402)
	at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1032)
	... 14 more
Caused by: java.io.EOFException: unexpected end of stream, read 0 bytes from 4
	at org.mariadb.jdbc.internal.io.input.StandardPacketInputStream.getPacketArray(StandardPacketInputStream.java:240)
	at org.mariadb.jdbc.internal.io.input.StandardPacketInputStream.getPacket(StandardPacketInputStream.java:208)
	at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.authentication(AbstractConnectProtocol.java:744)
	at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.handleConnectionPhases(AbstractConnectProtocol.java:713)
	... 16 more
@erizocosmico
Copy link

Just to add a little bit more of detail to this issue, it breaks in this commit: fa42f53

Reproduction case:

package main

import (
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"log"
	"strings"
	"time"
	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/sqltypes"
)

func main() {
	auth := mysql.NewAuthServerStatic()
	pwd := nativePassword("")

	auth.Entries["root"] = []*mysql.AuthServerStaticEntry{{
		MysqlNativePassword: pwd,
		Password:            pwd,
	}}

	l, err := mysql.NewListener("tcp", ":3306", auth, new(handler), 10*time.Minute, 10*time.Minute)
	if err != nil {
		log.Fatal(err)
	}

	l.Accept()
}

type handler struct{}

func (*handler) NewConnection(c *mysql.Conn) {
	log.Println("CONNECTION OPENED")
}

func (*handler) ConnectionClosed(c *mysql.Conn) {
	log.Println("CONNECTION CLOSED")
}

func (*handler) ComQuery(c *mysql.Conn, query string, callback func(*sqltypes.Result) error) error {
	log.Println("QUERY: " + query)
	return nil
}

func (*handler) WarningCount(c *mysql.Conn) uint16 { return 0 }

func nativePassword(password string) string {
	if len(password) == 0 {
		return ""
	}

	// native = sha1(sha1(password))

	hash := sha1.New()
	hash.Write([]byte(password))
	s1 := hash.Sum(nil)

	hash.Reset()
	hash.Write(s1)
	s2 := hash.Sum(nil)

	s := strings.ToUpper(hex.EncodeToString(s2))
	return fmt.Sprintf("*%s", s)
}

Scala app to trigger this:

import java.sql._

object Main extends App {
  val connection = DriverManager.getConnection(
    s"jdbc:mariadb://0.0.0.0:3306",
    "root",
    ""
  )

  val stmt: PreparedStatement = connection.prepareStatement("SHOW TABLES")

  val rs = stmt.executeQuery
  rs.close()
  stmt.close()
}

@sougou
Copy link
Contributor

sougou commented Apr 30, 2019

I believe it's because you're using the prepared statement protocol, which is not yet supported by vitess.

@erizocosmico
Copy link

erizocosmico commented Apr 30, 2019 via email

@sougou
Copy link
Contributor

sougou commented Apr 30, 2019

Yeah. This looks like a handshake error. We'll need to add some instrumentation here: https://github.com/vitessio/vitess/blob/master/go/mysql/server.go#L732. It's not receiving the number of bytes its' expecting.

@morgo morgo added this to the v5.0 milestone Oct 25, 2019
@morgo morgo modified the milestones: v5.0, v6.0 Feb 4, 2020
@morgo morgo added this to To do in MySQL Compatibility via automation Feb 19, 2020
@aquarapid
Copy link
Contributor

#4897 seems to have fixed this specific problem; however, there are other issues with the mariadb connector, for which I will log a separate issue.

@morgo morgo closed this as completed Feb 24, 2020
MySQL Compatibility automation moved this from To do to Done Feb 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

No branches or pull requests

5 participants