Usa Cloud SQL para PostgreSQL

En esta página, se muestra cómo conectarse a una instancia de Cloud SQL para PostgreSQL desde una aplicación de App Engine y cómo leer y escribir en Cloud SQL. Cloud SQL es una base de datos SQL que se encuentra en la nube de Google.

Para obtener más información sobre Cloud SQL, consulta la documentación de Cloud SQL. Para obtener más información sobre los precios y límites de Cloud SQL, consulta la página de precios de Cloud SQL. Las aplicaciones de App Engine también están sujetas a las cuotas de App Engine.

Antes de comenzar

  1. Crea o selecciona un proyecto de GCP en GCP Console y, luego, asegúrate de que el proyecto incluya una aplicación de App Engine y de que la facturación esté habilitada:
    Ir a App Engine

    El panel se abre si ya existe una aplicación de App Engine en tu proyecto y la facturación está habilitada. De lo contrario, sigue las instrucciones para seleccionar una región y habilitar la facturación.

  2. Habilita las Cloud SQL API necesarias.

    Habilita las API

  3. Para implementar una aplicación de Java en App Engine, primero debes configurar el entorno. Consulta Cómo usar Apache Maven y el complemento de App Engine para obtener información detallada.

Cómo configurar la instancia de Cloud SQL

Para crear y configurar una instancia de Cloud SQL, sigue estos pasos:

  1. Crea una instancia de Cloud SQL para PostgreSQL.
  2. Si aún no lo hiciste, establece la contraseña para el usuario predeterminado en tu instancia de Cloud SQL.
    gcloud sql users set-password postgres no-host --instance [INSTANCE_NAME] --password [PASSWORD]
    
  3. Si no deseas utilizar el usuario predeterminado para conectarte, crea un usuario.
  4. Registra el nombre de la conexión para la instancia con el siguiente comando:
    gcloud sql instances describe [INSTANCE_NAME]
    

    Por ejemplo:

    connectionName: project1:us-central1:instance1
    

    También puedes encontrar este valor en la página Detalles de la instancia de Google Cloud Platform Console.

  5. En este ejemplo, crea una base de datos en tu instancia de Cloud SQL denominada sqldemo.
    gcloud sql databases create sqldemo --instance=[INSTANCE_NAME]
    
    Si quieres obtener más información sobre cómo crear y administrar bases de datos, consulta la Documentación de Cloud SQL.

Cómo configurar strings de conexión y agregar una biblioteca

Usa la biblioteca de sockets de la fábrica de sockets de JDBC de Cloud SQL para conectarte a tu instancia de Cloud SQL con el fin de realizar pruebas locales y, también, implementaciones.

  1. Actualiza pom.xml con tu nombre de conexión, nombre de usuario y contraseña:

      <properties>
    <!--
        INSTANCE_CONNECTION_NAME from Cloud Console > SQL > Instance Details > Properties
        or `gcloud sql instances describe <instance> | grep connectionName`
    -->
        <INSTANCE_CONNECTION_NAME>Project:Region:Instance</INSTANCE_CONNECTION_NAME>
        <user>root</user>
        <password>myPassword</password>
        <database>sqldemo</database>
        <sqlURL>jdbc:postgresql://google/${database}?useSSL=false&amp;socketFactoryArg=${INSTANCE_CONNECTION_NAME}&amp;socketFactory=com.google.cloud.sql.postgres.SocketFactory&amp;user=${user}&amp;password=${password}</sqlURL>
      </properties>

  2. Agrega los filtros de recursos obligatorios a pom.xml:

    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>

  3. Crea un archivo llamado config.properties que contenga la siguiente línea:

    sqlUrl=${sqlURL}

    Este archivo depende de los filtros de recursos configurados en pom.xml.

  4. Agrega una biblioteca de JDBC y la fábrica de sockets de JDBC de Cloud SQL a tu aplicación. Para ello, agrega la dependencia a pom.xml:

    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>42.2.6</version>
    </dependency>
    
    <dependency>
      <groupId>com.google.cloud.sql</groupId>
      <artifactId>postgres-socket-factory</artifactId>
      <version>1.0.14</version>
    </dependency>

Cómo ejecutar el código de muestra

La muestra siguiente realiza operaciones de escritura sobre la información de las visitas en Cloud SQL y, luego, lee y muestra las últimas diez visitas:
@SuppressWarnings("serial")
@WebServlet(name = "postgresql", value = "")
public class PostgresSqlServlet extends HttpServlet {
  Connection conn;

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException,
      ServletException {

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

    String path = req.getRequestURI();
    if (path.startsWith("/favicon.ico")) {
      return; // ignore the request for favicon.ico
    }

    PrintWriter out = resp.getWriter();
    resp.setContentType("text/plain");

    // 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)) + ".*.*";
    }

    Stopwatch stopwatch = Stopwatch.createStarted();
    try (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()) {
        stopwatch.stop();
        out.print("Last 10 visits:\n");
        while (rs.next()) {
          String savedIp = rs.getString("user_ip");
          String timeStamp = rs.getString("ts");
          out.println("Time: " + timeStamp + " Addr: " + savedIp);
        }
        out.println("Elapsed: " + stopwatch.elapsed(TimeUnit.MILLISECONDS));
      }
    } catch (SQLException e) {
      throw new ServletException("SQL error", e);
    }
  }

  @Override
  public void init() throws ServletException {
    String url;

    Properties properties = new Properties();
    try {
      properties.load(
          getServletContext().getResourceAsStream("/WEB-INF/classes/config.properties"));
      url = properties.getProperty("sqlUrl");
    } catch (IOException e) {
      log("no property", e);  // Servlet Init should never fail.
      return;
    }

    log("connecting to: " + url);
    try {
      Class.forName("org.postgresql.Driver");
      conn = DriverManager.getConnection(url);
    } catch (ClassNotFoundException e) {
      throw new ServletException("Error loading JDBC Driver", e);
    } catch (SQLException e) {
      throw new ServletException("Unable to connect to PostGre", e);
    } finally {
      // Nothing really to do here.
    }
  }
}

Ejecuta pruebas y realiza la implementación

  1. Para realizar pruebas en tu aplicación de manera local, sigue estos pasos:

    mvn clean jetty:run
    
  2. Después de la prueba local, implementa tu aplicación en App Engine:

    mvn clean appengine:deploy
    

  3. Ejecuta el siguiente comando para iniciar el navegador y ver la aplicación en http://[YOUR_PROJECT_ID].appspot.com:

    gcloud app browse
    

Ejecuta Cloud SQL y App Engine en proyectos diferentes

Si la aplicación de App Engine y la instancia de Cloud SQL se encuentran en distintos proyectos de Google Cloud Platform, debes usar una cuenta de servicio para permitir el acceso de la aplicación de App Engine a Cloud SQL.

Esta cuenta de servicio representa a tu aplicación de App Engine y se crea de forma predeterminada cuando creas un proyecto de Google Cloud Platform.

  1. Si tu aplicación de App Engine se encuentra en el mismo proyecto que tu instancia de Cloud SQL, puedes omitir esta sección y acceder a Cómo configurar strings de conexión y agregar una biblioteca. De lo contrario, continúa con el paso siguiente.
  2. Identifica la cuenta de servicio asociada a tu aplicación de App Engine. A la cuenta de servicio de App Engine predeterminada se le asigna el nombre [PROJECT-ID]@appspot.gserviceaccount.com.

    Puedes verificar la cuenta de servicio de App Engine en la página Permisos de IAM. Asegúrate de seleccionar el proyecto para tu aplicación de App Engine, no tu instancia de Cloud SQL.

    Ir a la página Permisos de IAM

  3. Ve a la página IAM y proyectos del administrador en Google Cloud Platform Console.

    Ir a la página IAM y proyectos del administrador

  4. Selecciona el proyecto que contiene la instancia de Cloud SQL.
  5. Busca el nombre de la cuenta de servicio.
  6. Si la cuenta de servicio ya existe y tiene una función que incluye el permiso cloudsql.instances.connect, puedes continuar con la sección configura strings de conexión y agrega una biblioteca.

    Las funciones Cloud SQL Client, Cloud SQL Editor y Cloud SQL Admin, y las funciones del proyecto heredadas Editor y Owner otorgan los permisos necesarios.

  7. De lo contrario, haz clic en Agregar para incluir la cuenta de servicio.
  8. En el cuadro de diálogo Agregar miembros, ingresa el nombre de la cuenta de servicio y selecciona una función que incluya el permiso cloudsql.instances.connect (cualquier función predefinida de Cloud SQL funcionará, excepto la de Visualizador).

    O bien, puedes seleccionar Proyecto > Editor para usar la función básica de editor, pero esta incluye permisos en Google Cloud Platform.

    Si no ves estas funciones, es posible que tu usuario de Google Cloud Platform no tenga el permiso resourcemanager.projects.setIamPolicy. Puedes verificar tus permisos en la página IAM, en Google Cloud Platform Console, y buscar tu ID de usuario.

  9. Haz clic en Agregar.

    Ahora deberías ver que la cuenta de servicio aparece con la función especificada.

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Entorno flexible de App Engine para documentos de Java