LoginSignup
0
0

More than 3 years have passed since last update.

Cloud Functionsをjavaで書いてCloud SQL(MySQL)に接続する

Posted at

概略

Cloud Functionsをjavaで書いて、Cloud SQLに接続するサンプルコードが見当たらなかったので備忘録が共有しようと思います。

※Cloud FunctionsとCloud SQLの設置手順は、Qiitaメンバーの解説記事がわかりやすいので割愛します。

割り当てられるメモリ の設定

256MiB以上をお勧めします。

最初、128MiBで動作確認したのですがメモリ不足でエラーになりました。

ランタイム環境変数 の設定

以下の変数をセットします。

変数
DB_NAME MySqlでCREATEしたデータベース名
DB_USER データベースへの接続ユーザー
DB_PASS データベースへの接続ユーザーのパスワード
CLOUD_SQL_CONNECTION_NAME CloudSQLに構築したデータベースインスタンスのインスタンス接続名

※暗号化した値を設定する場合は実装側で複合処理を実装してください。
以降は平文設定している前提です。

pom.xml

com.zaxxer(DBコネクション管理)、com.google.cloud.sql(CloudSQL接続用)、mysql(MySQL接続用)が最低限必要(だった)。

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cloudfunctions</groupId>
  <artifactId>http-function</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.0.1</version>
    </dependency>
     <dependency>
      <groupId>com.zaxxer</groupId>
      <artifactId>HikariCP</artifactId>
      <version>4.0.3</version>
    </dependency>
    <dependency>
      <groupId>com.google.cloud.sql</groupId>
      <artifactId>mysql-socket-factory</artifactId>
      <version>1.2.2</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.23</version>
    </dependency>
  </dependencies>

  <!-- Required for Java 11 functions in the inline editor -->
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <excludes>
            <exclude>.google/</exclude>
          </excludes>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Example.java

Example.java

package com.example;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.BufferedWriter;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Example implements HttpFunction {
  private static final String CLOUD_SQL_CONNECTION_NAME = System.getenv("CLOUD_SQL_CONNECTION_NAME");
  private static final String DB_USER = System.getenv("DB_USER");
  private static final String DB_PASS = System.getenv("DB_PASS");
  private static final String DB_NAME = System.getenv("DB_NAME");
  private static DataSource pool;
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {

    if (pool == null) {
      HikariConfig config = new HikariConfig();
      config.setJdbcUrl(String.format("jdbc:mysql:///%s", DB_NAME));
      config.setUsername(DB_USER); // e.g. "root", "mysql"
      config.setPassword(DB_PASS); // e.g. "my-password"
      config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
      config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_CONNECTION_NAME);
      config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");
      config.setMaximumPoolSize(5);
      config.setMinimumIdle(5);
      config.setConnectionTimeout(10000); // 10 seconds
      config.setIdleTimeout(600000); // 10 minutes
      config.setMaxLifetime(1800000); // 30 minutes
      pool = new HikariDataSource(config);
    }

    BufferedWriter writer = response.getWriter();
    try (Connection conn = pool.getConnection()) {
      String stmt = "SELECT * FROM {DB名.テーブル名};";
      try (PreparedStatement secectTableStatement = conn.prepareStatement(stmt);) {
        try (ResultSet rs = secectTableStatement.executeQuery();) {
          while (rs.next()) {
            int id = rs.getInt("ID");
            String name = rs.getString("NAME");
            writer.write("id = " + id + ",Name = " + name);  //クライアントにreplyする値
          }
        }
      }
    } catch (Exception e) {
      writer.write("error cause by -> " + e.getClass().getName() + ": " + e.getMessage());
    }
  }
}

クライアント側との連携仕様に合わせてReply方法は設計してください。

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0