正在尝试为具有托管虚拟机的 Java 应用引擎设置与克隆 SQL 第二代的连接。
我得到了什么:
- 虚拟机正在使用应用引擎兼容模式 (
FROM gcr.io/google_appengine/java-compat
) - 我在主机上看到一个MySQL管道(SSHed,我可以看到
/cloudsql/**
套接字),但默认的MySQL Java驱动程序不支持unix套接字 - 谷歌驱动程序似乎在托管虚拟机上不受支持 (
java.lang.ClassNotFoundException: com.mysql.jdbc.GoogleDriver
) - 并且我无法通过IP连接到MySQL
- 没有驱动程序,它
No suitable driver found
jdbc:google:mysql://__IP__:3306/__db__
- 或超时
jdbc:mysql://__IP__:3306/__db__
(我已经将 MVM 外部 IP 添加到 MySQL 上的授权网络) - 但是有趣的是,我可以从MVM机器连接到此端口,至少端口已打开。无论如何,我不喜欢通过公开开放的IP:PORT进行连接的想法。MVM 每次都有一个新 IP,所以我甚至无法添加防火墙规则来仅指定来自我的项目的访问权限
- 没有驱动程序,它
我应该如何配置托管虚拟机应用以连接到云 SQL?
我在使用 Java 启动托管 VM 应用程序时遇到问题,所以我现在无法亲自尝试,但看起来您应该能够利用此库从 Java 连接到 Unix 套接字。有一个示例,您只需更改套接字的路径:
props.put("junixsocket.file", "/cloudsql/project-id:region:instance-id");
其中project-id
是项目名称,region
是云 SQL 实例所在的区域(例如 us-east1
),instance-id
是云 SQL 实例的名称。该字符串将位于"实例连接名称"下的第二代实例的属性中。
我们有一个新的 Java 库,用于从托管 VM 和其他环境连接到 Cloud SQL 实例:https://github.com/GoogleCloudPlatform/cloud-sql-mysql-socket-factory
它仍然非常新,因此通常的警告适用,但我们在测试中没有发现任何问题。
我发现的最佳方法是从托管虚拟机配置 SSL 连接
你应该做两件事。
首先,准备从云SQL控制台获得的带有SSL的Java密钥库(文件server-ca.pem
,client-cert.pem
和client-key.pem
):
echo '---------- GENERATE TrustStore'
keytool -import -alias mysqlCACert -file server-ca.pem -keystore truststore -storepass 123456
echo '---------- GENERATE KeyStore'
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem
-out client.p12 -name clientalias -CAfile server-ca.pem -caname root
keytool -importkeystore -deststorepass 123456 -destkeystore keystore
-srckeystore client.p12 -srcstoretype PKCS12 -srcstorepass 123456 -alias clientalias
你将获得两个文件:需要放入目标 VM 的truststore
和keystore
。
其次,您应该使用自定义Dockerfile
,以及上一步中的文件:
FROM gcr.io/google_appengine/java-compat
RUN mkdir /keys
ADD keystore /keys/
ADD truststore /keys/
ENV JAVA_OPTS -Djavax.net.ssl.keyStore=/keys/keystore -Djavax.net.ssl.keyStorePassword=123456 -Djavax.net.ssl.trustStore=/keys/truststore -Djavax.net.ssl.trustStorePassword=123456
ADD . /app/
当然,不要忘记告诉MySQL驱动程序始终使用SSL:
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://__CLOUD_SQL_IP__:3306/__CLOUD_SQL_DB__?useSSL=true&requireSSL=true");
PS 注意,我正在使用密码123456来保护我的密钥。这只是一个例子。不要在项目中使用它。它已经被拿走了。