重要说明-最后在Edit#2中取得了突破,因此请务必阅读该内容。
我陷入了困境,试图使用JDBC连接到我们公司的PostgreSQL服务器。服务器正在使用pgBouncer。
这是我的项目依赖项:
:dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/java.jdbc "0.3.6"]
[org.postgresql/postgresql "9.4-1200-jdbc41"]]
这是我的代码:
(ns pg-test.core
(:require [clojure.java.jdbc :as jdbc]))
(def db
{:subprotocol "postgresql"
:subname "//the-server-name:the-port/db-name"
:sslmode "require"
:user "my-username"
:password "super-secret-password"})
(jdbc/query db ["SELECT 5"])
运行此代码时,得到以下三个结果之一:
org.postgresql.util.PSQLException:连接尝试失败。
org.postgresql.util.PSQLException:错误:错误的数据包标头:“ 70”
很少(现在三百次,数百次尝试),它实际上可以工作!返回
({:?column? 5})
到底是怎么回事?为什么有时会起作用,但几乎永远不会起作用?
我的设定
OS X Yosemite(但是我也无法使它在我的Ubuntu虚拟机上运行。)
在emacs中,先按
lein repl :headless :port 2358
,再按cider-connect
。服务器是postgres 9.1.12
编辑#2
刚刚了解了
:loglevel 2
选项。这将其设置为“ DEBUG”级别的输出,并且我收集了一些更有趣的数据。这是输出:21:45:34.921 (31) PostgreSQL 9.4 JDBC4.1 (build 1200)
21:45:34.927 (31) Trying to establish a protocol version 3 connection to the-server-name:the-port
21:45:35.020 (31) FE=> SSLRequest
21:45:35.120 (31) <=BE SSLOk
21:45:35.120 (31) converting regular socket connection to ssl
21:45:35.324 (31) Receive Buffer Size is 131072
21:45:35.324 (31) Send Buffer Size is 131136
21:45:35.324 (31) FE=> StartupPacket(user=my-username, database=db-name, client_encoding=UTF8, DateStyle=ISO, TimeZone=America/Denver, extra_float_digits=2)
21:45:35.435 (31) <=BE AuthenticationReqMD5(salt=f244b442)
21:45:35.436 (31) FE=> Password(md5digest=md52e3d9f29d44d48ab19ef3469d54d50d1)
21:45:35.520 (31) <=BE ErrorMessage(ERROR: bad packet header: '70')
然后给出以下堆栈跟踪:
org.postgresql.util.PSQLException: ERROR: bad packet header: '70'
at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:420)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:195)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66)
at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:127)
at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:29)
at org.postgresql.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:21)
at org.postgresql.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:41)
at org.postgresql.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:24)
at org.postgresql.Driver.makeConnection(Driver.java:414)
at org.postgresql.Driver.connect(Driver.java:282)
at java.sql.DriverManager.getConnection(DriverManager.java:571)
at java.sql.DriverManager.getConnection(DriverManager.java:187)
at clojure.java.jdbc$get_connection.invoke(jdbc.clj:255)
at clojure.java.jdbc$db_query_with_resultset.invoke(jdbc.clj:798)
at clojure.java.jdbc$query.doInvoke(jdbc.clj:832)
at clojure.lang.RestFn.invoke(RestFn.java:425)
at pg_test.core$eval4536.invoke(core.clj:14)
at clojure.lang.Compiler.eval(Compiler.java:6703)
at clojure.lang.Compiler.load(Compiler.java:7130)
at pg_test.core$eval4524.invoke(form-init6588155330850041472.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6703)
at clojure.lang.Compiler.eval(Compiler.java:6666)
at clojure.core$eval.invoke(core.clj:2927)
at clojure.main$repl$read_eval_print__6625$fn__6628.invoke(main.clj:239)
at clojure.main$repl$read_eval_print__6625.invoke(main.clj:239)
at clojure.main$repl$fn__6634.invoke(main.clj:257)
at clojure.main$repl.doInvoke(main.clj:257)
at clojure.lang.RestFn.invoke(RestFn.java:1523)
at clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__592.invoke(interruptible_eval.clj:67)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.core$apply.invoke(core.clj:624)
at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1862)
at clojure.lang.RestFn.invoke(RestFn.java:425)
at clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:51)
at clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__634$fn__637.invoke(interruptible_eval.clj:183)
at clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__627.invoke(interruptible_eval.clj:152)
at clojure.lang.AFn.run(AFn.java:22)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
但是,它给出了这个错误代码!
SQLException: SQLState(08P01)
根据this website的意思是“协议违规”。
我在Google上搜索了08P01协议违规情况,并在this bug report上找到了一个完全不相关的项目,该项目在GitHub上尝试将编码的Unicode字符写入字符串字段时标题为“'08P01 PROTOCOL VIOLATION'”。
因此,让我们看一下我们要发送的内容:
StartupPacket(user=my-username, database=db-name, client_encoding=UTF8, DateStyle=ISO, TimeZone=America/Denver, extra_float_digits=2)
。请注意,我们的编码为UTF8。然后,我们发送
Password(md5digest=md52e3d9f29d44d48ab19ef3469d54d50d1)
,并立即获得“坏数据包头'70'”异常。UTF8是否再次毁了我的生活?我以为很久以前就把这些糟糕的日子抛在了身后。
所以现在我想知道是否有一种方法可以更改客户端编码。或可能更改所使用的身份验证方法。
最佳答案
根据PgJDBC驱动程序,“ PgJDBC对于某些功能具有对其他库的可选依赖项。如果您希望使用这些功能,则这些库也必须位于类路径上;否则,您将在运行时获得PSQLException。尝试使用缺少库的功能。”
可能缺少一些可靠的或可能是本机编译的SSL库。不过,我不知道为什么在某些情况下有时会在蓝月亮中起作用。
https://github.com/pgjdbc/pgjdbc/blob/f96f6b3c0fdcb9c393b870b834adb1248f955cee/README.md#dependencies
关于java - 为什么PostgreSQL JDBC驱动程序在身份验证期间向服务器发送错误的数据包头?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28466014/