Com uma função remota do Spanner, é possível implementar sua função em linguagens diferentes do SQL. As funções precisam ser hospedadas no Cloud Run functions ou no Cloud Run. Hospedar funções dessa maneira permite que uma lógica de negócios complexa seja dividida em funções remotas separadas.
Uma implantação de função remota típica tem as seguintes etapas:
Crie um endpoint HTTPS nas funções do Cloud Run ou no Cloud Run.
- Se você não conhece as funções remotas, recomendamos usar as funções do Cloud Run.
Crie uma função remota no Spanner apontando para esse endpoint HTTPS.
Use a função remota em uma consulta.
Funções exigidas
Para garantir que sua conta de serviço do agente do Spanner (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) tenha as permissões
necessárias para usar funções remotas do Spanner,
peça ao administrador para conceder à sua conta de serviço do agente do Spanner (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) o
papel do IAM de agente de serviço da API Spanner (roles/spanner.serviceAgent)
no projeto.
Seu administrador também pode conceder à conta de serviço do agente do Spanner (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) as permissões necessárias com papéis personalizados ou outros papéis predefinidos.
Tipos compatíveis
As funções remotas são compatíveis com os seguintes tipos de dados como argumentos ou tipos de retorno:
ARRAY(de qualquer um dos seguintes tipos compatíveis)BOOLEANBYTESDATEJSONINTEGERNUMERICSTRINGTIMESTAMP
Limitações
Não é possível criar funções remotas com valor de tabela.
As funções remotas não são compatíveis com expressões de coluna geradas.
É possível ter solicitações repetidas com os mesmos dados para o endpoint, às vezes mesmo após respostas bem-sucedidas, devido a erros transitórios de rede ou reinicializações internas do Spanner.
Não é possível executar funções remotas em instâncias fracionárias do Spanner.
As funções remotas não são compatíveis com o Cloud Run functions em domínios personalizados.
As funções remotas não são compatíveis com o dialeto PostgreSQL.
Crie um endpoint
A lógica de negócios precisa ser implementada como uma função do Cloud Run ou do Cloud Run. O endpoint precisa processar um lote de linhas em uma única solicitação HTTPS POST e retornar o resultado em lote como uma resposta HTTPS.
Se você criou funções remotas para o BigQuery, poderá reutilizá-las no Spanner.
Consulte o tutorial do Cloud Run functions e outras documentações do Cloud Run functions sobre como escrever, implantar, testar e manter uma função do Cloud Run.
Consulte o guia de início rápido do Cloud Run e outras documentações do Cloud Run sobre como escrever, implantar, testar e manter um serviço do Cloud Run.
Recomendamos manter a autenticação padrão para sua função ou serviço do Cloud Run. Evite configurar o serviço para permitir invocações não autenticadas.
Formato da entrada
O Spanner envia solicitações HTTPS POST com corpos JSON no seguinte formato:
| Nome do campo | Descrição | Tipo de campo |
|---|---|---|
requestId
|
Identificador da solicitação. Exclusivo em várias solicitações enviadas ao endpoint em uma consulta GoogleSQL. | Sempre fornecido. String. |
calls
|
Um lote de dados de entrada. | Sempre fornecido. Uma matriz JSON.
Cada elemento é uma matriz JSON que representa uma lista de argumentos codificada em JSON para uma única chamada de função remota. |
Exemplo de solicitação:
// Sample request to a Cloud Run functions to calculate sum of two numbers. This request
// has two calls batched together into a single request.
{
"requestId": "124ab1c",
"calls": [
[1, 2],
[3, 4]
]
}
Formato da saída
O Spanner espera que o endpoint retorne uma resposta HTTPS no formato a seguir. Caso contrário, o Spanner não poderá consumir a resposta e a consulta vai falhar ao chamar a função remota.
| Nome do campo | Descrição | Intervalo de valor |
replies
|
Um lote de valores de retorno. | Matriz JSON.
Cada elemento corresponde a um valor de retorno codificado em JSON da função externa. O tamanho da matriz precisa ser igual ao tamanho da matriz JSON decalls na solicitação HTTPS. Por exemplo, se a matriz JSON em calls tiver quatro elementos, esta matriz JSON precisará ter quatro elementos. Obrigatório para uma resposta bem-sucedida.
|
errorMessage
|
Mensagem de erro quando o código de resposta HTTPS diferente de 200 é retornado. Para erros que não podem ser repetidos, o Spanner retorna essa mensagem de erro ao usuário. Obrigatório em respostas com falha. Normalmente menos de 1 KB. | String. |
Exemplo de resposta bem-sucedida:
// Sample response from the Cloud Run functions which has the sum of the two numbers. Note
// that the order of the values within `replies` field matches the `calls` field from
// the request.
{
"replies": [
3, // 1 + 2 = 3
7 // 3 + 4 = 7
]
}
Exemplo de resposta com falha:
{
// The error message returned by your Cloud Run functions to indicate an error.
// In this sample, the error message states that an overflow occurred when summing two numbers.
"errorMessage": "Overflow detected when calculating sum of two numbers."
}
Código de resposta HTTPS
Seu endpoint retorna um código HTTPS 200 para uma resposta bem-sucedida. Quando o Spanner recebe qualquer outro valor, ele considera a resposta uma falha e tenta novamente quando o código de resposta HTTPS é 408, 429, 500, 503 ou 504 até atingir um limite interno.
Código de amostra
Função do Cloud Run
O exemplo de código Python a seguir implementa a adição de todos os argumentos inteiros da função remota. Ele processa uma solicitação com os argumentos para invocações em lote e retorna todos os resultados em uma resposta.
"""
Python script which uses Flask framework to spin up a HTTP server to take
integers and return their sum. In case of overflow, it returns the error
as part of the response.
"""
import functions_framework
from flask import jsonify
# Max INT64 value encoded as a number in JSON by TO_JSON_STRING. Larger values are encoded as
# strings.
_MAX_LOSSLESS=9007199254740992
@functions_framework.http
def batch_add(request):
try:
return_value = []
request_json = request.get_json()
calls = request_json['calls']
for call in calls:
return_value.append(sum([int(x) if isinstance(x, str) else x for x in call if x is not None]))
replies = [str(x) if x > _MAX_LOSSLESS or x < -_MAX_LOSSLESS else x for x in return_value]
return_json = jsonify( { "replies": replies } )
return return_json
except Exception as e:
return jsonify( { "errorMessage": str(e) } ), 400
Supondo que a função seja implantada no projeto PROJECT_ID
na região us-east1 como o nome da função remote_add, ela pode
ser acessada usando o endpoint
https://us-east1-PROJECT_ID.cloudfunctions.net/remote_add.
Cloud Run
O exemplo de código Python a seguir implementa um serviço da Web, que pode ser criado e implantado no Cloud Run para a mesma funcionalidade.
"""
Python script which uses Flask framework to spin up a HTTP server to take
integers and return their sum. In case of overflow, it returns the error
as part of the response.
"""
import os
from flask import Flask, request, jsonify
# Max INT64 value encoded as a number in JSON by TO_JSON_STRING. Larger values are encoded as
# strings.
_MAX_LOSSLESS=9007199254740992
app = Flask(__name__)
@app.route("/", methods=['POST'])
def batch_add():
try:
return_value = []
request_json = request.get_json()
calls = request_json['calls']
for call in calls:
return_value.append(sum([int(x) if isinstance(x, str) else x for x in call if x is not None]))
replies = [str(x) if x > _MAX_LOSSLESS or x < -_MAX_LOSSLESS else x for x in return_value]
return jsonify( { "replies" : replies } )
except Exception as e:
return jsonify( { "errorMessage": str(e) } ), 400
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Para criar e implantar o código, consulte Guia de início rápido: criar e implantar um app da Web em Python (Flask) no Cloud Run.
Supondo que o serviço do Cloud Run seja implantado no
projeto PROJECT_ID na região us-east1 como o
nome do serviço remote_add, ele pode ser acessado usando o endpoint
https://remote_add-<project_id_hash>-ue.a.run.app.
Criar uma função remota
Para criar uma função remota:
SQL
Execute a seguinte instrução CREATE FUNCTION no Spanner:
CREATE FUNCTION REMOTE_FUNCTION_NAME(x INT64, y INT64) RETURNS INT64 NOT DETERMINISTIC LANGUAGE REMOTE OPTIONS (
endpoint = `ENDPOINT_URL`,
max_batching_rows = MAX_BATCHING_ROWS
);
Substitua:
REMOTE_FUNCTION_NAME: o nome da sua função remota. Por exemplo,sum_func.ENDPOINT_URL: as funções do Cloud Run ou o endpoint do Cloud Run criado na etapa anterior.MAX_BATCHING_ROWS(opcional): o número máximo de linhas a serem enviadas como parte de uma solicitação. Se não for especificado, o Spanner vai determinar o tamanho do lote automaticamente.
Usar uma função remota em uma consulta
Para chamar a função remota da etapa anterior em uma consulta, use o exemplo a seguir:
SELECT REMOTE_FUNCTION_NAME(1, 2); -- 1 + 2 = 3
Preços
São aplicados os preços padrão do Spanner.
O Spanner cobra pelos bytes enviados e recebidos do Cloud Run functions ou do Cloud Run.
Esse recurso pode gerar custos do Cloud Run functions e do Cloud Run. Consulte as páginas de preços do Cloud Run functions e do Cloud Run para mais detalhes.