web-dev-qa-db-ja.com

DataflowジョブからCloudSQLに接続する

JdbcIOとApacheBeam 2.0(Java)を使用して、同じプロジェクト内のDataflowからCloudSQLインスタンスに接続するのに苦労しています。

次のエラーが発生します:

Java.sql.SQLException: Cannot create PoolableConnectionFactory (Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.)
  • ドキュメントによると、データフローサービスアカウント* @ dataflow-service-producer-prod.iam.gserviceaccount.comは、「編集者」権限を持っている場合、同じプロジェクト内のすべてのリソースにアクセスできる必要があります。

  • DirectRunnerで同じDataflowジョブを実行すると、すべてが正常に機能します。

これは私が使用しているコードです:

private static String JDBC_URL = "jdbc:mysql://myip:3306/mydb?verifyServerCertificate=false&useSSL=true";

PCollection < KV < String, Double >> exchangeRates = p.apply(JdbcIO. < KV < String, Double >> read()
 .withDataSourceConfiguration(JdbcIO.DataSourceConfiguration.create("com.mysql.jdbc.Driver", JDBC_URL)
  .withUsername(JDBC_USER).withPassword(JDBC_PW))
 .withQuery(
  "SELECT CurrencyCode, ExchangeRate FROM mydb.mytable")
 .withCoder(KvCoder.of(StringUtf8Coder.of(), DoubleCoder.of()))
 .withRowMapper(new JdbcIO.RowMapper < KV < String, Double >> () {
  public KV < String, Double > mapRow(ResultSet resultSet) throws Exception {
   return KV.of(resultSet.getString(1), resultSet.getDouble(2));
  }
 }));

編集:

別のデータフロージョブ内でビームの外部で次のアプローチを使用すると、データベースが問題ではない可能性があることを示すDataflowRunnerで正常に機能するようです。

Java.sql.Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PW);
7
Jimmy

JavaからCloudSQLに接続する方法に関する次の手順に従います。

https://cloud.google.com/sql/docs/mysql/connect-external-app#Java

私はなんとかそれを機能させることができました。

これはコードがどのように見えるかです(MYDBNAME、MYSQLINSTANCE、USER、およびPASSWORDを自分の値に置き換える必要があります。

Heads up:MYSQLINSTANCE形式はproject:zone:instancenameです。

また、キーと値のペアではなく、カスタムクラス(Customer)を使用して各行の値を格納しています。

p.apply(JdbcIO. <Customer> read()
    .withDataSourceConfiguration(
        JdbcIO.DataSourceConfiguration.create(
            "com.mysql.jdbc.Driver", 
            "jdbc:mysql://google/MYDBNAME?cloudSqlInstance=MYSQLINSTANCE&socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=USER&password=PASSWORD&useUnicode=true&characterEncoding=UTF-8"
        )
    )
    .withQuery( "SELECT CustomerId, Name, Location, Email FROM Customers" )
    .withCoder( AvroCoder.of(Customer.class) )
    .withRowMapper(
        new JdbcIO.RowMapper < Customer > ()
        {
            @Override
            public Customer mapRow(Java.sql.ResultSet resultSet) throws Exception
            {
                final Logger LOG = LoggerFactory.getLogger(CloudSqlToBq.class);
                LOG.info(resultSet.getString(2));
                Customer customer = new Customer(resultSet.getInt(1), resultSet.getString(2), resultSet.getString(3), resultSet.getString(3));
                return customer;
            }
        }
    )
);

これがお役に立てば幸いです。

5
Borja

こんにちはそれはあなたがそれをした方法で私のために働きました。さらに私はdb設定メソッドからwithusernameとpasswordメソッドを削除しました、そして私のパイプライン設定は以下のようになります

PCollection < KV <  Double, Double >> exchangeRates = p.apply(JdbcIO. < KV <  Double, Double >> read()
     .withDataSourceConfiguration(JdbcIO.DataSourceConfiguration.create("com.mysql.jdbc.Driver", "jdbc:mysql://ip:3306/dbname?user=root&password=root&useUnicode=true&characterEncoding=UTF-8")
             )
     .withQuery(
      "SELECT PERIOD_YEAR, PERIOD_YEAR FROM SALE")
     .withCoder(KvCoder.of(DoubleCoder.of(), DoubleCoder.of()))
     .withRowMapper(new JdbcIO.RowMapper < KV < Double, Double >> () {
      @Override
       public KV<Double, Double> mapRow(Java.sql.ResultSet resultSet) throws Exception {
         LOG.info(resultSet.getDouble(1)+ "Came");
          return KV.of(resultSet.getDouble(1), resultSet.getDouble(2));
      }
     }));

これが役立つことを願っています

3

このアプローチの方がうまくいくと思います。com.mysql.jdbc.GoogleDriverを試して、ここにリストされているMavenの依存関係を使用してください。

https://cloud.google.com/appengine/docs/standard/Java/cloud-sql/#Java_Connect_to_your_database

関連する質問: このjarファイルcom.mysql.jdbc.GoogleDriverを見つけてダウンロードする場所

2
Alex Amato