Observação:

Hospede Aplicativos de Backend de Várias Camadas no Oracle Cloud Infrastructure Functions

Introdução

O Oracle Cloud Infrastructure Functions (OCI Functions) é uma plataforma Functions-as-a-Service totalmente gerenciada, multi-tenant, altamente escalável, sob demanda. Ela foi criada no OCI (Oracle Cloud Infrastructure) de nível empresarial e desenvolvida pelo mecanismo de código-fonte aberto Fn Project. Use o OCI Functions quando quiser se concentrar na gravação de código para atender às necessidades do negócio. A arquitetura sem servidor e elástica do OCI Functions significa que não há administração de infraestrutura ou administração de software para você executar. Você não provisiona nem mantém instâncias de computação, e patches e atualizações de software do sistema operacional são aplicados automaticamente. O OCI Functions simplesmente garante que seu aplicativo esteja altamente disponível, escalável, seguro e monitorado. Com o OCI Functions, você pode escrever código em Java, Python, Node, Go, Ruby e C# (e para casos de uso avançados, trazer seu próprio arquivo Docker e Graal VM). Em seguida, você poderá implantar o código, chamá-lo diretamente ou acioná-lo em resposta a eventos e será faturado somente pelos recursos consumidos durante a execução.

Enquanto trabalha na OCI ou em qualquer outra nuvem, pode haver um requisito para hospedar o código de backend de seus aplicativos em uma arquitetura sem servidor e o OCI Functions pode ser usado para ele. Por exemplo, vamos supor que seu aplicativo tenha vários componentes de backend desenvolvidos por várias equipes. Uma equipe desenvolve seus componentes em Java, enquanto outra usa Python. Você pode mover esses vários componentes de aplicativo para o OCI Functions e chamá-los usando pontos finais de API.

Objetivos

Pré-requisitos

Tarefa 1: Criar Grupos Dinâmicos e Políticas obrigatórios

  1. Vá para a Console do OCI, navegue até Identidade e Segurança, Identidade, Grupo Dinâmico e clique em Criar Grupo Dinâmico.

    Criar Grupo Dinâmico

  2. Informe detalhes como Nome, Descrição e Regras de Correspondência para seu Grupo Dinâmico. Adicione detalhes de regras com cuidado, pois elas definirão qual recurso obterá o acesso em qual compartimento.

    Detalhes do Grupo Dinâmico

  3. Salve os detalhes do Grupo Dinâmico e aguarde o momento em que o Grupo Dinâmico for criado com os detalhes na console do OCI. Depois que o Grupo Dinâmico for criado, avance com a criação das políticas de IAM para esse Grupo Dinâmico recém-criado.

  4. Navegue até Identidade e Segurança, Identidade, Políticas e clique em Criar Política.

    Criar Política

  5. Informe detalhes como Nome, Descrição e Compartimentos para seu Grupo Dinâmico. Adicione detalhes da política com cuidado, pois eles definirão qual outro recurso sua função pode acessar em qual compartimento.

    Detalhes da Política

    Política Criada

  6. Salve os detalhes das Políticas e aguarde o momento em que elas são criadas com os detalhes na console do OCI. Depois que a Política for criada, avance para criar o aplicativo e a função.

Tarefa 2: Criar Aplicativo e Funções com várias linguagens de programação

  1. Vá para a Console do OCI, navegue até Developer Services, Functions, Applications e clique em Create application.

    Criar Aplicativo

  2. Informe detalhes como Nome, VCN, Sub-rede e Forma do seu aplicativo. Selecione a VCN e a Sub-rede levando em consideração a rede, pois eles disponibilizarão seu aplicativo para ser chamado nas redes permitidas.

    Detalhes do Aplicativo

  3. Salve os detalhes do Aplicativo e aguarde o momento em que o Aplicativo é criado com os detalhes na console do OCI. Depois que o Aplicativo for criado, avance para criar as funções nele.

    Aplicativo Criado

  4. Navegue até Recursos e clique em Aplicativos. Você encontrará todos os comandos necessários para se conectar ao aplicativo criado e criar a função. Você pode selecionar qualquer opção em Configuração do Cloud Shell ou Configuração Local; selecione Configuração do Cloud Shell para este tutorial.

    Introdução à Função

  5. Para verificar se você se conectou ao OCI Functions, poderá conectar e acionar o comando a seguir.

    fn list apps
    

    Lista de Funções

  6. Crie algumas funções em várias linguagens de programação, como Java e Python, e adicione o código de acordo com seus requisitos de negócios.

    fn init --runtime python getStreamData
    fn init --runtime java pushObjectStorageFile
    fn init --runtime java getADWSecret
    fn init --runtime python pushADWData
    
  7. Criamos quatro funções diferentes, duas em Java e duas em Python. Certifique-se de implantar o código e verificar se ele está funcionando conforme esperado, chamando-o manualmente.

    cd getStreamData
    fn -v deploy --app oci-app-demo
    fn invoke oci-app-demo getStreamData
    
    cd pushObjectStorageFile
    fn -v deploy --app oci-app-demo
    fn invoke oci-app-demo pushObjectStorageFile
    
    cd getADWSecret
    fn -v deploy --app oci-app-demo
    fn invoke oci-app-demo getADWSecret
    
    cd pushADWData
    fn -v deploy --app oci-app-demo
    fn invoke oci-app-demo pushADWData
    

O fluxo desse aplicativo de backend é nosso aplicativo principal que produzirá alguns dados no streaming e os dados serão consumidos pela função getStreamData gravada em Python. Em seguida, enviaremos os dados para o OCI Object Storage como um arquivo e obteremos a senha secreta do Autonomous Data Warehouse. Em seguida, enviaremos os dados para o Autonomous Data Warehouse para processamento e análise adicionais.

Na Tarefa 3, veremos como podemos adicionar a chamada de função baseada em Java e Python em nosso aplicativo e código de função para que possamos criar um fluxo.

Tarefa 3: Adicionar código para chamar uma função de outra

Você pode chamar ou chamar uma função de outra função usando SDKs do OCI. Os exemplos de snippets são escritos em Java e Python e podem ser usados de acordo com sua lógica de negócios.

  1. Adicione o trecho de código a seguir para o SDK (Java Software Development Kit).

    package com.example.fn;
    
    import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider;
    import com.oracle.bmc.objectstorage.ObjectStorage;
    import com.oracle.bmc.objectstorage.ObjectStorageClient;
    import com.oracle.bmc.objectstorage.requests.GetObjectRequest;
    import com.oracle.bmc.objectstorage.responses.GetObjectResponse;
    import com.oracle.bmc.Region;
    import com.oracle.bmc.functions.FunctionsInvokeClient;
    import com.oracle.bmc.functions.FunctionsManagementClient;
    import com.oracle.bmc.functions.model.FunctionSummary;
    import com.oracle.bmc.functions.model.ApplicationSummary;
    import com.oracle.bmc.functions.requests.ListApplicationsRequest;
    import com.oracle.bmc.functions.responses.ListApplicationsResponse;
    import com.oracle.bmc.functions.requests.ListFunctionsRequest;
    import com.oracle.bmc.functions.responses.ListFunctionsResponse;
    import com.oracle.bmc.functions.requests.InvokeFunctionRequest;
    import com.oracle.bmc.functions.responses.InvokeFunctionResponse;
    import com.oracle.bmc.util.StreamUtils;
    
    import java.nio.charset.StandardCharsets;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.stream.Collectors;
    
    public class HelloFunction {
    
       private ObjectStorage objStoreClient = null;
       final ResourcePrincipalAuthenticationDetailsProvider provider
                = ResourcePrincipalAuthenticationDetailsProvider.builder().build();
    
       public HelloFunction() {
          try {
                objStoreClient = new ObjectStorageClient(provider);
          } catch (Throwable ex) {
                System.err.println("Failed to instantiate ObjectStorage client - " + ex.getMessage());
          }
       }
       public static class GetObjectInfo {
    
          private String bucketName;
          private String name;
    
          public String getBucketName() {
                return bucketName;
          }
    
          public void setBucketName(String bucketName) {
                this.bucketName = bucketName;
          }
    
          public String getName() {
                return name;
          }
    
          public void setName(String name) {
                this.name = name;
          }
    
       }
       public String handleRequest(GetObjectInfo objectInfo) {
    
          String result = "FAILED";
          final ResourcePrincipalAuthenticationDetailsProvider provider = ResourcePrincipalAuthenticationDetailsProvider.builder().build();
          final Region region = Region.US_PHOENIX_1;
          final String compartmentId = "ocid1.compartment.oc1..<your_compartment_ocid>";
          final String name = "oci-java-sdk-function";
          final String payload = "Hii";
    
          if (objStoreClient == null) {
                System.err.println("There was a problem creating the ObjectStorage Client object. Please check logs");
                return result;
          }
          try {
    
                String nameSpace = System.getenv().get("NAMESPACE");
    
                GetObjectRequest gor = GetObjectRequest.builder()
                      .namespaceName(nameSpace)
                      .bucketName(objectInfo.getBucketName())
                      .objectName(objectInfo.getName())
                      .build();
                System.err.println("Getting content for object " + objectInfo.getName() + " from bucket " + objectInfo.getBucketName());
    
                GetObjectResponse response = objStoreClient.getObject(gor);
                result = new BufferedReader(new InputStreamReader(response.getInputStream()))
                      .lines().collect(Collectors.joining("\n"));
    
                System.err.println("Finished reading content for object " + objectInfo.getName());
                invokeFunction(provider, region, compartmentId, name, payload);
    
          } catch (Throwable e) {
                System.err.println("Error fetching object " + e.getMessage());
                result = "Error fetching object " + e.getMessage();
          }
    
          //invokeFunction(provider, region, compartmentId, name, payload);
    
          return result;
    
       }
    
       public static FunctionSummary getUniqueFunctionByName(
                final FunctionsManagementClient fnManagementClient,
                final String compartmentId,
                final String applicationDisplayName,
                final String functionDisplayName)
                throws Exception {
          final ApplicationSummary application =
                   getUniqueApplicationByName(
                            fnManagementClient, compartmentId, applicationDisplayName);
          return getUniqueFunctionByName(
                   fnManagementClient, application.getId(), functionDisplayName);
       }
    
       public static FunctionSummary getUniqueFunctionByName(
                final FunctionsManagementClient fnManagementClient,
                final String applicationId,
                final String functionDisplayName)
                throws Exception {
    
          final ListFunctionsRequest listFunctionsRequest =
                   ListFunctionsRequest.builder()
                            .applicationId(applicationId)
                            .displayName(functionDisplayName)
                            .build();
    
          final ListFunctionsResponse listFunctionsResponse =
                   fnManagementClient.listFunctions(listFunctionsRequest);
    
          if (listFunctionsResponse.getItems().size() != 1) {
                throw new Exception(
                      "Could not find function with name "
                               + functionDisplayName
                               + " in application "
                               + applicationId);
          }
    
          return listFunctionsResponse.getItems().get(0);
       }
    
       public static ApplicationSummary getUniqueApplicationByName(
                final FunctionsManagementClient fnManagementClient,
                final String compartmentId,
                final String applicationDisplayName)
                throws Exception {
          final ListApplicationsRequest listApplicationsRequest =
                   ListApplicationsRequest.builder()
                            .displayName(applicationDisplayName)
                            .compartmentId(compartmentId)
                            .build();
    
          final ListApplicationsResponse resp =
                   fnManagementClient.listApplications(listApplicationsRequest);
    
          if (resp.getItems().size() != 1) {
                throw new Exception(
                      "Could not find unique application with name "
                               + applicationDisplayName
                               + " in compartment "
                               + compartmentId);
          }
    
          final ApplicationSummary application = resp.getItems().get(0);
          return application;
       }
    
       private static String invokeFunction(
                final FunctionsInvokeClient fnInvokeClient,
                final FunctionSummary function,
                final String payload)
                throws Exception {
          String response;
          try {
                System.err.println("Invoking function endpoint - " + function.getInvokeEndpoint());
    
                fnInvokeClient.setEndpoint(function.getInvokeEndpoint());
                final InvokeFunctionRequest invokeFunctionRequest =
                      InvokeFunctionRequest.builder()
                               .functionId(function.getId())
                               .invokeFunctionBody(
                                        StreamUtils.createByteArrayInputStream(payload.getBytes()))
                               .build();
    
                final InvokeFunctionResponse invokeFunctionResponse =
                      fnInvokeClient.invokeFunction(invokeFunctionRequest);
    
                response = "Done executing func1...";
                      //StreamUtils.toString(
                               //invokeFunctionResponse.getInputStream(), StandardCharsets.UTF_8);
    
          } catch (final Exception e) {
                e.printStackTrace();
                System.err.println("Failed to invoke function: " + e);
                throw e;
          }
    
          return response;
       }
    
       public static void invokeFunction(
          final ResourcePrincipalAuthenticationDetailsProvider provider,
          final Region region,
          final String compartmentId,
          final String name,
          final String payload)
          throws Exception {
    
          final FunctionsManagementClient fnManagementClient =
                   FunctionsManagementClient.builder().region(region).build(provider);
    
          final FunctionsInvokeClient fnInvokeClient =
                   FunctionsInvokeClient.builder().build(provider);
    
          try {
             final String appName = "e2e-function-demo";
             final String fnName = "java_func2";
             final FunctionSummary fn =
                      getUniqueFunctionByName(fnManagementClient, compartmentId, appName, fnName);
    
             final String response = invokeFunction(fnInvokeClient, fn, payload);
             if (response != null) {
                   System.out.println("Response from function:  " + response);
             }
          } finally {
             fnInvokeClient.close();
             fnManagementClient.close();
          }
       }
    }
    
    
  2. Adicione o trecho de código a seguir para o Python SDK.

    def trigger_function():
       logging.getLogger().info("Reached python function func1...")
       function_endpoint = "https://932jksmn9.us-ashburn-1.functions.oci.oraclecloud.com"
       function_ocid = "ocid1.fnfunc.oc1.iad.your_function_ocid"
       function_body = "Hii"
       signer = oci.auth.signers.get_resource_principals_signer()
       client = oci.functions.FunctionsInvokeClient(config={}, signer=signer, service_endpoint=function_endpoint)
       resp = client.invoke_function(function_id=function_ocid, invoke_function_body=function_body)
       logging.getLogger().info("Completed calling func2")
    

Agradecimentos

Mais Recursos de Aprendizagem

Explore outros laboratórios em docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal Oracle Learning YouTube. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.

Para obter a documentação do produto, visite o Oracle Help Center.