Como usar o Cloud SQL para PostgreSQL

Nesta página você aprende como se conectar a uma instância do Cloud SQL para PostgreSQL a partir de um aplicativo do App Engine e como fazer leituras e gravações no Cloud SQL. O Cloud SQL é um banco de dados SQL que reside na nuvem do Google.

Para saber mais, consulte a documentação do Cloud SQL. Para informações sobre preços e limites do Cloud SQL, consulte a página de preços do Cloud SQL. Os aplicativos do App Engine também estão sujeitos às cotas dessa plataforma.

Antes de começar

  1. Crie ou selecione um projeto do GCP no Console do GCP e verifique se o projeto inclui um aplicativo do App Engine e se o faturamento está ativado:
    Acessar o App Engine

    O Painel será aberto se houver um aplicativo do App Engine no projeto e se o faturamento estiver ativado. Caso contrário, siga as instruções para escolher uma região e ativar o faturamento.

  2. Ativar Cloud SQL API.

    Ativar a API

  3. Para implantar um app Java no App Engine, primeiro é necessário configurar o ambiente. Consulte os detalhes em Como usar o Apache Maven e o plug-in do App Engine.

Como configurar a instância do Cloud SQL

Para criar e configurar uma instância do Cloud SQL, siga as seguintes etapas:

  1. Crie uma instância do Cloud SQL para PostgreSQL.
  2. Defina a senha do usuário padrão na instância do Cloud SQL, caso ainda não tenha feito isso:
    gcloud sql users set-password postgres no-host --instance [INSTANCE_NAME] --password [PASSWORD]
    
  3. Se não quiser usar o usuário padrão para se conectar, crie um usuário.
  4. Registre o nome da conexão da instância:
    gcloud sql instances describe [INSTANCE_NAME]
    

    Exemplo:

    connectionName: project1:us-central1:instance1
    

    Você também encontra esse valor na página de Detalhes da instância no Console do Google Cloud Platform.

  5. Neste exemplo, crie um banco de dados na instância do Cloud SQL chamada sqldemo.
    gcloud sql databases create sqldemo --instance=[INSTANCE_NAME]
    
    Para ver mais informações sobre como criar e gerenciar bancos de dados, consulte a documentação do Cloud SQL.

Como configurar strings de conexão e adicionar uma biblioteca

Use a biblioteca de soquetes JDBC Socket Factory do Cloud SQL (em inglês) a fim de se conectar à instância do Cloud SQL para testes locais e em implantação.

  1. Atualize pom.xml com o nome de conexão, o nome de usuário e a senha:

      <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. Adicione a filtragem de recursos obrigatória a pom.xml:

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

  3. Crie um arquivo chamado config.properties com a seguinte linha:

    sqlUrl=${sqlURL}

    Este arquivo depende da filtragem de recursos configurada em pom.xml.

  4. Para adicionar uma biblioteca JDBC e o Cloud SQL JDBC Socket Factory ao aplicativo, inclua a dependência em 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>

Como executar o código de amostra

A amostra abaixo grava as informações de visita no Cloud SQL. Em seguida, ela as lê e retorna as últimas dez 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.
    }
  }
}

Como testar e implantar

  1. Para testar seu aplicativo localmente:

    mvn clean jetty:run
    
  2. Após os testes locais, implante seu aplicativo no App Engine:

    mvn clean appengine:deploy
    

  3. Para iniciar o navegador e ver o aplicativo em http://[YOUR_PROJECT_ID].appspot.com, execute o seguinte comando:

    gcloud app browse
    

Como executar o Cloud SQL e o App Engine em projetos separados

Use uma conta de serviço para permitir o acesso do aplicativo do App Engine ao Cloud SQL caso ele e a instância do Cloud SQL estejam em projetos diferentes do Google Cloud Platform.

Essa conta de serviço representa o aplicativo do App Engine. Ela é gerada por padrão quando você cria um projeto do Google Cloud Platform.

  1. Se o aplicativo do Google App Engine estiver no mesmo projeto da instância do Cloud SQL, você poderá ignorar esta seção e ir para Como configurar strings de conexão e adicionar uma biblioteca. Caso contrário, prossiga para a próxima etapa.
  2. Identifique a conta de serviço associada ao aplicativo do App Engine. A conta padrão é denominada [PROJECT-ID]@appspot.gserviceaccount.com.

    É possível verificar a conta de serviço do App Engine na página Permissões de IAM. Lembre-se de selecionar o projeto do aplicativo do App Engine, e não a instância do Cloud SQL.

    Acessar a página "Permissões de IAM"

  3. Acesse a página Projetos do IAM e do administrador no Console do Google Cloud Platform.

    Acessar a página "Projetos do IAM e do administrador"

  4. Selecione o projeto que contém a instância do Cloud SQL.
  5. Procure o nome da conta de serviço.
  6. Caso a conta de serviço já exista e tenha um papel que inclua a permissão cloudsql.instances.connect, prossiga para Como configurar strings de conexão e adicionar uma biblioteca.

    Os papéis Cloud SQL Client, Cloud SQL Editor e Cloud SQL Admin fornecem a permissão necessária, assim como os papéis legados Editor e Owner do projeto.

  7. Caso contrário, clique em Adicionar para incluir a conta.
  8. Na caixa de diálogo Adicionar membros, forneça o nome da conta de serviço e selecione um papel que inclua a permissão cloudsql.instances.connect. Qualquer papel predefinido do Cloud SQL funcionará, exceto leitor.

    Também é possível usar o papel primário de Editor ao selecionar Projeto > Editor. No entanto, ele inclui permissões em todo o Google Cloud Platform.

    Se esses papéis não estiverem sendo exibidos, é provável que seu usuário do Google Cloud Platform não tenha a permissão resourcemanager.projects.setIamPolicy. Para verificar suas permissões, acesse a página "IAM" no Console do Google Cloud Platform e procure seu código de usuário.

  9. Clique em Adicionar.

    Você verá a conta de serviço listada com o papel especificado.

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Ambiente flexível do App Engine para documentos Java