Note:

Aloje aplicaciones backend de varios niveles en Oracle Cloud Infrastructure Functions

Introducción

Oracle Cloud Infrastructure Functions (OCI Functions) es una plataforma de funciones como servicio totalmente gestionada, multi-inquilino y altamente escalable. Se basa en Oracle Cloud Infrastructure (OCI) de nivel empresarial y en el motor de código abierto Fn Project. Utiliza OCI Functions cuando quieras centrarte en la escritura de código para satisfacer las necesidades empresariales. La arquitectura sin servidor y elástica de OCI Functions significa que no tiene que realizar la administración de la infraestructura ni del software. No aprovisiona ni mantiene instancias informáticas, y los parches y actualizaciones de software del sistema operativo se aplican automáticamente. OCI Functions simplemente garantiza que la aplicación tenga una alta disponibilidad, escalable, segura y supervisada. Con OCI Functions, puede escribir código en Java, Python, Node, Go, Ruby y C# (y para casos de uso avanzados, puede traer su propio archivo Docker y Graal VM). A continuación, puede desplegar su código, llamarlo directamente o dispararlo en respuesta a eventos y facturar solo los recursos utilizados durante la ejecución.

Al trabajar en OCI o en cualquier otra nube, puede haber un requisito para alojar el código de backend de sus aplicaciones en una arquitectura sin servidor y OCI Functions se puede utilizar para ello. Por ejemplo, supongamos que su aplicación tiene varios componentes de backend desarrollados por varios equipos. Un equipo desarrolla sus componentes en Java mientras que otro utiliza Python. Puede mover estos varios componentes de aplicación a OCI Functions y, a continuación, llamarlos mediante puntos finales de API.

Objetivos

Requisitos

Tarea 1: Creación de políticas y grupos dinámicos necesarios

  1. Vaya a la consola de OCI, vaya a Identidad y seguridad, Identidad, Grupo dinámico y haga clic en Crear grupo dinámico.

    Crear Grupo Dinámico

  2. Introduzca detalles como Nombre, Descripción y Reglas de coincidencia para el grupo dinámico. Agregue cuidadosamente los detalles de las reglas, ya que definirán qué recurso obtendrá el acceso en qué compartimento.

    Detalles de grupo dinámico

  3. Guarde los detalles del grupo dinámico y espere a que se cree el grupo dinámico con los detalles en la consola de OCI. Una vez creado el grupo dinámico, continúe creando las políticas de IAM para este grupo dinámico recién creado.

  4. Vaya a Identidad y seguridad, Identidad, Políticas y haga clic en Crear política.

    Crear política

  5. Introduzca detalles como Nombre, Descripción y Compartimentos para el grupo dinámico. Agregue cuidadosamente los detalles de la política, ya que definirán a qué otro recurso puede acceder la función en qué compartimento.

    Detalles de Política

    Política creada

  6. Guarde los detalles de las políticas y espere a que se creen las políticas con los detalles de la consola de OCI. Una vez creada la política, continúe para crear la aplicación y la función.

Tarea 2: Creación de aplicaciones y funciones con varios lenguajes de programación

  1. Vaya a la consola de OCI, vaya a Developer Services, Functions, Applications y haga clic en Create application.

    Crear aplicación

  2. Introduzca detalles como Nombre, VCN, Subred y Unidad para la aplicación. Seleccione la VCN y la subred teniendo en cuenta las redes, ya que harán que la aplicación esté disponible para que se llame dentro de las redes permitidas.

    Detalles de las Aplicaciones

  3. Guarde los detalles de la aplicación y espere a que se cree la aplicación con los detalles de la consola de OCI. Una vez creada la aplicación, continúe para crear las funciones en ella.

    Aplicación Creada

  4. Vaya a Recursos y haga clic en Aplicaciones. Encontrará todos los comandos que necesita para conectarse a la aplicación creada y crear la función. Puede seleccionar cualquier opción de Configuración de Cloud Shell o Configuración local, seleccione Configuración de Cloud Shell para este tutorial.

    Introducción a la función

  5. Para verificar que se ha conectado a OCI Functions, debe poder conectarse y disparar el siguiente comando.

    fn list apps
    

    Lista de Funciones

  6. Cree un par de funciones en varios lenguajes de programación, como Java y Python, y agregue el código según los requisitos de su negocio.

    fn init --runtime python getStreamData
    fn init --runtime java pushObjectStorageFile
    fn init --runtime java getADWSecret
    fn init --runtime python pushADWData
    
  7. Hemos creado cuatro funciones diferentes, dos en Java y dos en Python. Asegúrese de que ha desplegado el código y ha verificado que funciona como se esperaba llamándolo 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
    

El flujo de esta aplicación backend es nuestra aplicación principal, que producirá algunos datos en el flujo, y los datos los consumirá la función getStreamData escrita en Python. A continuación, transferiremos los datos a OCI Object Storage como archivo y obtendremos la contraseña secreta para Autonomous Data Warehouse. A continuación, enviaremos los datos a Autonomous Data Warehouse para un mayor procesamiento y análisis.

En la tarea 3, veremos cómo podemos agregar la llamada de función basada en Java y Python a nuestra aplicación y código de función para crear un flujo.

Tarea 3: Agregar código para llamar a una función desde otra función

Puede llamar o llamar a una función desde otra función mediante los SDK de OCI. Los fragmentos de ejemplo se escriben en Java y Python y se pueden utilizar según la lógica de negocio.

  1. Agregue el siguiente fragmento de código para Java Software Development Kit (SDK).

    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. Agregue el siguiente fragmento de código para el SDK de Python.

    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")
    

Agradecimientos

Más recursos de aprendizaje

Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de aprendizaje gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en Oracle Learning Explorer.

Para obtener documentación sobre el producto, visite Oracle Help Center.