Google Cloud SQL の使用

Google Cloud SQL は、App Engine アプリケーションで使用できるリレーショナル データベースを提供します。Cloud SQL は Google のクラウド上で運用される MySQL データベースです。Google Cloud SQL の詳細については、Google Cloud SQL ドキュメントをご覧ください。

Cloud SQL と App Engine の両方で適用される価格設定と制限の詳細については、料金とアクセス制限をご覧ください。

始める前に

  1. Cloud Platform Console で Cloud Platform プロジェクトを作成または選択します。プロジェクトに App Engine アプリケーションが含まれていることを確認します。
    App Engine に移動

    プロジェクトに App Engine アプリケーションが存在する場合には、ダッシュボードが開きます。存在しない場合には、App Engine アプリケーションを配置するリージョンを選択するように指示されます。

  2. Java アプリを App Engine にデプロイするには、まず環境をセットアップする必要があります。詳細については、Apache Maven と App Engine プラグインの使用をご覧ください。

ローカル環境の設定

ローカルの MySQL サーバーを使用してアプリケーションをテストするか、Cloud SQL に接続します。

ローカルの MySQL サーバーでアプリケーションをテストする場合には、MySQL サーバーをインストールします。
  • 使用している Linux ディストリビューションで apt-get を使用できる場合には、次のコマンドを実行します。
    sudo apt-get install mysql-server
  • 他のオペレーティング システムの場合には、MySQL Community Server のダウンロード ページをご覧ください。

Cloud SQL インスタンスのセットアップ

  1. 第 2 世代の Cloud SQL インスタンスを作成して、ルートユーザーを設定します
  2. 接続にルートユーザーを使用しない場合には、ユーザーを作成します
  3. Cloud SDK を使用して、アプリケーション コード内で接続文字列として使用する Cloud SQL インスタンスの接続名を取得します。
    gcloud sql instances describe [INSTANCE_NAME]
    connectionName に返された値を記録します。この値は Google Cloud Platform Console のインスタンスの詳細ページでも確認できます。たとえば、Cloud SDK の出力は次のようになります。
    gcloud sql instances describe instance1
      connectionName: project1:us-central1:instance1
  4. sqldemo という名前の Cloud SQL インスタンスにデータベースを作成します。

    詳細については、データベースの作成をご覧ください。

App Engine へのアクセス付与

App Engine アプリケーションと Cloud SQL インスタンスが異なる Google Cloud Platform プロジェクトにある場合、サービス アカウントを使用して App Engine アプリケーションが Cloud SQL にアクセスできるようにする必要があります。

このサービス アカウントは App Engine アプリケーションを表し、Google Cloud Platform プロジェクトを作成するとデフォルトで作成されます。

  1. App Engine アプリケーションが Cloud SQL インスタンスと同じプロジェクトにある場合、設定に進みます。それ以外の場合は、次のステップに進みます。
  2. App Engine アプリケーションに関連付けられたサービス アカウントを特定します。デフォルトの App Engine サービス アカウント名は [PROJECT-ID]@appspot.gserviceaccount.com です。

    App Engine サービス アカウントは [IAM 権限] ページで確認できます。プロジェクトは Cloud SQL インスタンスではなく、必ず App Engine アプリケーションに対して選択してください。

    [IAM 権限] ページに移動

  3. Google Cloud Platform Console の [IAM と管理] ページに移動します。

    [IAM と管理] ページに移動

  4. Cloud SQL インスタンスを含むプロジェクトを選択します。
  5. サービス アカウント名を検索します。
  6. Cloud SQL Client または Editor の役割を持つサービス アカウントがすでにある場合は、設定に進みます。
  7. それ以外の場合、[追加] をクリックしてサービス アカウントを追加します。
  8. [メンバーを追加] ダイアログでサービス アカウントの名前を指定し、その役割の [Cloud SQL] > [Cloud SQL クライアント] を選択します。

    [役割] > [編集者] を選択することで、基本の役割として編集者を使用することもできますが、編集者の役割には Google Cloud Platform 全体に対する権限が含まれます。

  9. [追加] をクリックします。

    これで、指定した役割を持つサービス アカウントがリストされます。

設定

  1. Cloud SQL インスタンス接続名、データベース、ユーザー、パスワードを pom.xml に追加します。

      <properties>
    <!-- INSTANCE_CONNECTION_NAME from Cloud Console > SQL > Instance Details > Properties
         or gcloud sql instances describe <instance>
         project:region:instance for Cloud SQL 2nd Generation or
         project:instance        for Cloud SQL 1st Generation
    -->
        <INSTANCE_CONNECTION_NAME></INSTANCE_CONNECTION_NAME>
        <user>root</user>
        <password>myPassword</password>
        <database>sqldemo</database>
    
    <!-- ...
      </properties>

  2. アプリケーションに JDBC ライブラリを追加します。たとえば、Maven を使用する場合は、プロジェクトの pom.xml に依存関係を追加できます。
    <dependency> <!-- ONLY USED LOCALY -->
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.40</version>  <!-- v5.x.x is for production, v6.x.x EAP X DevAPI -->
    </dependency>
    <dependency>
      <groupId>com.google.cloud.sql</groupId>
      <artifactId>mysql-socket-factory</artifactId>
      <version>1.0.2</version>
    </dependency>

コードサンプルの概要

次のコードサンプルは、Cloud SQL インスタンスに訪問者ログを作成します。訪問情報を Cloud SQL に書き込み、次に最新の 10 件の訪問を読み取って返します。

@SuppressWarnings("serial")
public class CloudSqlServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException,
      ServletException {
    String path = req.getRequestURI();
    if (path.startsWith("/favicon.ico")) {
      return; // ignore the request for favicon.ico
    }
    // store only the first two octets of a users ip address
    String userIp = req.getRemoteAddr();
    InetAddress address = InetAddress.getByName(userIp);
    if (address instanceof Inet6Address) {
      // nest indexOf calls to find the second occurrence of a character in a string
      // an alternative is to use Apache Commons Lang: StringUtils.ordinalIndexOf()
      userIp = userIp.substring(0, userIp.indexOf(":", userIp.indexOf(":") + 1)) + ":*:*:*:*:*:*";
    } else if (address instanceof Inet4Address) {
      userIp = userIp.substring(0, userIp.indexOf(".", userIp.indexOf(".") + 1)) + ".*.*";
    }

    final String createTableSql = "CREATE TABLE IF NOT EXISTS visits ( visit_id INT NOT NULL "
        + "AUTO_INCREMENT, user_ip VARCHAR(46) NOT NULL, timestamp DATETIME NOT NULL, "
        + "PRIMARY KEY (visit_id) )";
    final String createVisitSql = "INSERT INTO visits (user_ip, timestamp) VALUES (?, ?)";
    final String selectSql = "SELECT user_ip, timestamp FROM visits ORDER BY timestamp DESC "
        + "LIMIT 10";

    PrintWriter out = resp.getWriter();
    resp.setContentType("text/plain");
    String url;
    if (System
        .getProperty("com.google.appengine.runtime.version").startsWith("Google App Engine/")) {
      // Check the System properties to determine if we are running on appengine or not
      // Google App Engine sets a few system properties that will reliably be present on a remote
      // instance.
      url = System.getProperty("ae-cloudsql.cloudsql-database-url");
      try {
        // Load the class that provides the new "jdbc:google:mysql://" prefix.
        Class.forName("com.mysql.jdbc.GoogleDriver");
      } catch (ClassNotFoundException e) {
        throw new ServletException("Error loading Google JDBC Driver", e);
      }
    } else {
      // Set the url with the local MySQL database connection url when running locally
      url = System.getProperty("ae-cloudsql.local-database-url");
    }
    log("connecting to: " + url);
    try (Connection conn = DriverManager.getConnection(url);
        PreparedStatement statementCreateVisit = conn.prepareStatement(createVisitSql)) {
      conn.createStatement().executeUpdate(createTableSql);
      statementCreateVisit.setString(1, userIp);
      statementCreateVisit.setTimestamp(2, new Timestamp(new Date().getTime()));
      statementCreateVisit.executeUpdate();

      try (ResultSet rs = conn.prepareStatement(selectSql).executeQuery()) {
        out.print("Last 10 visits:\n");
        while (rs.next()) {
          String savedIp = rs.getString("user_ip");
          String timeStamp = rs.getString("timestamp");
          out.print("Time: " + timeStamp + " Addr: " + savedIp + "\n");
        }
      }
    } catch (SQLException e) {
      throw new ServletException("SQL error", e);
    }
  }
}

maven pom に設定されたプロパティが使用されて、下記の接続 URL が作成されます。

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <threadsafe>true</threadsafe>
  <use-google-connector-j>true</use-google-connector-j>
  <system-properties>
    <property name="ae-cloudsql.cloudsql-database-url" value="jdbc:google:mysql://${INSTANCE_CONNECTION_NAME}/${database}?user=${user}&amp;password=${password}" />
    <property name="ae-cloudsql.local-database-url" value="jdbc:mysql://google/${database}?cloudSqlInstance=${INSTANCE_CONNECTION_NAME}&amp;socketFactory=com.google.cloud.sql.mysql.SocketFactory&amp;user=${user}&amp;password=${password}&amp;useSSL=false" />
  </system-properties>
</appengine-web-app>

開発環境でのテスト

ローカルの開発用サーバーでアプリをテストするには:

  1. ローカルの MySQL サーバーを使用する場合には、開発環境で MySQL サーバーを開始します。
  2. 開発用サーバーを起動します。たとえば、Maven を使用している場合は、次のコマンドを実行します。
    mvn appengine:devserver
  3. ウェブサーバーが起動し、ポート 8080 でリクエストをリッスンします。表示するには、次の URL にアクセスします。

    http://localhost:8080/

問題が発生する場合は、ローカル開発用サーバーの使用で詳細をご確認ください。

アプリのデプロイ

  1. アプリを App Engine にアップロードするには、次の Maven コマンドを実行します。

     mvn clean package
     mvn appengine:update
    

    App Engine にデプロイする方法については、Java アプリをデプロイするをご覧ください。

  2. ブラウザを開いて http://[YOUR_PROJECT_ID].appspot.com でアプリを表示します。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Java の App Engine スタンダード環境