Ballerina

Cómo crear y desplegar un microservicio fácilmente con Ballerina y Microgateway

13th septiembre 2019

En los tiempos actuales no necesitamos siempre de productos tan robustos y estables como pueden ser el API Manager o el Enterprise Integrator. Sino que podemos estar más enfocados en plataformas ligeras y orientadas a un despliegue sencillo en la nube. 

Teniendo estas características en mente, WSO2 nos ofrece un par de productos ideales para ello:

  • API Microgateway, una herramienta basada en el API Manager, con lo que mantenemos su fiabilidad y experiencia en integraciones.Y con la que además, simplificamos el proceso de creación y despliegue de APIs, manteniendo la posibilidad de realizar operaciones de enrutado, seguridad o análitica. 
  • Ballerina, un nuevo lenguaje de programación y plataforma que nos permite la creación de microservicios. Muy orientado a facilitar el despliegue en la nube. 

 

Cómo desplegar una API con Microgateway

Para ver todo esto vamos a crear por un lado una API a desplegar por el Microgateway. Y un servicio backend asociado a la API, el cual será realizado y desplegado con Ballerina. Como en el artículo nos queremos centrar en la facilidad a la hora de crear y desplegar un microservicio, usaremos como ejemplo un microservicio sin autenticación muy básico que nos permita crear y obtener libros a través de los recursos HTTP GET y POST. 

Aparte de Ballerina y Microgateway, vamos a apoyaremos en otras herramientas: 

  • Microgateway Toolkit, la cual nos ayudará en la creación de la API.
  • Docker, con el cual desplegamos tanto el servicio, como el Microgateway. 

Por tanto, para realizarlo debemos tener Ballerina, Microgateway Toolkit y Docker, correctamente instalado en nuestro equipo. 

Desarrollando el servicio con Ballerina y Microgateway

El proyecto del servicio tendrá una estructura muy simplificada. Constituido por la carpeta raíz, bookService, y el módulo con nuestro código fuente, http. Para inicializar el proyecto deberemos ejecutar el siguiente comando desde la carpeta principal.

ballerina init

Nuestro servicio se denominará HTTPService.bal y será de la siguiente forma.

 

import ballerina/http;
import ballerina/log;
import ballerinax/docker;
@docker:Expose {}
listener http:Listener bookEP = new(9091);
map<json> booksMap = {};
@docker:Config {
    Registry:«com.chakray.example», name:«example», tag:«v1.0»
}
@http:ServiceConfig {
    basePath: «/bookService»
}
service books on bookEP {
    @http:ResourceConfig {
        methods: [«GET»], path: «/book/{bookId}»
    }
    resource function getById(http:Caller caller, http:Request req, string bookId) {
        json? payload = booksMap[bookId];
        http:Response response = new;
        if (payload == null) {
            response.statusCode = 404;
            payload = «Item Not Found»;
        }
        response.setJsonPayload(untaint payload);
        var result = caller->respond(response);
        if (result is error) {
            log:printError(«Error sending response», err = result);
        }
    }

    @http:ResourceConfig {
        methods: [«POST»], path: «/book»
    }
    resource function addBook(http:Caller caller, http:Request req) {
        http:Response response = new;
        var bookReq = req.getJsonPayload();
        if (bookReq is json) {
            string bookId = bookReq.book.id.toString();
            booksMap[bookId] = bookReq;
            response.statusCode = 201;
            response.setHeader(«Location», «http://localhost:9091/bookService/book/» + bookId);
        } else {
            response.statusCode = 400;
            response.setPayload(«Invalid payload received»);
        }
        var result = caller->respond(response);
        if (result is error) {
            log:printError(«Error sending response», err = result);
        }
    }
}

 

Teniendo el código como referencia, fijémonos en las partes claves de este servicio:

  • Importamos las librerías de utilidades de Ballerina: docker, http y log. 
  • Configuramos nuestro servicio para escuchar las peticiones que lleguen al puerto 9091 y con el contexto de la URL /bookService.
  • Asociamos dos recursos al servicio, uno atento al método GET y que espera un identificador en la URL y otro atento al método POST que espera un objeto JSON como mensaje. 
  • El método GET, devolverá el código de respuesta 200 y el objeto asociado al identificador pasado en la URL o 404 si no encuentra dicho objeto. 
  • El método POST, almacenará el objeto JSON en un mapa en la memoria interna, devolverá 201 y una cabecera con la URL de nuestro servicio si queremos recuperar el libro almacenado. 

Cómo desplegar el servicio con Docker

Para poder crear un imagen asociada a nuestro servicio y que sea manejada por docker deberemos tener en cuenta los siguientes aspectos del código anterior: 

  • Hemos indicado cuál es el puerto del servicio a exponer hacia el exterior.
  • Hemos Incluido la configuración de la imagen a crear.

Para crear la imagen, debemos ejecutar el siguiente comando:

ballerina build HTTPService.bal

Y podremos levantar nuestro servicio gracias a Docker a través del siguiente comando:

docker run –name=dockerBookService –net=wso2_nw -d -p 9091:9091 com.chakray.example/example:v1.0 

Desarrollo de la API con Microgateway

A igual que con Ballerina en el paso anterior, Microgateway Toolkit nos permitirá inicializar el proyecto y crear una estructura de proyecto básica. Esto lo podemos hacer con el siguiente comando.

 

micro-gw init bookAPI

 

Este proyecto tendrá la siguiente estructura:

  • api_definitions: carpeta donde incluiremos ficheros de tipo YAML, los cuales contienen la definición de nuestras APIs.
  • conf: carpeta que incluye el fichero con la configuración con Docker o Kubernetes. 
  • extensions: carpeta con extensiones de la funcionalidad del Microgateway. . 
  • interceptors: carpeta con interceptores del Microgateway. Vacía por defecto. 
  • services: carpeta con servicios predefinidos del Microgateway, como los que nos permiten obtener un token o revocarlo, que funcionan como proxy del Key Manager. 
  • policies.yaml: fichero con las políticas de uso, se encuentra predefinido por defecto. 

 

El siguiente paso será crear la definición de la API. Microgateway es compatible con la especificacion OpenAPI 3.0, por tanto realizaremos una API de acuerdo con ella, con la siguiente información. 

 

openapi: 3.0.0
info:
  versión: 1.0.0
  title: Book API
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
tags:
  – name: book
    description: book tag description
x-wso2-basePath: /bookAPI/v1
x-wso2-production-endpoints:
  urls:
    – http://dockerBookService:9091/bookService
paths:
  «/book/{bookId}»:
    get:
      tags:
      – book
      description: Returns a single book
      operationId: getBookById
      x-wso2-disable-security: true
      parameters:
      – name: bookId
        in: path
        description: ID of book to return
        required: true
        schema:
          type: integer
          format: int64
      responses:
        ‘200’:
          description: successful operation
        ‘404’:
          description: Book not found
  «/book»:
    post:
      tags:
      – book
      description: create a book
      operationId: createBook
      consumes:
      – «application/json»
      parameters:
      – in: «body»
        name: «body»
        description: «Book object»
        required: true
      x-wso2-disable-security: true
      responses:
        ‘201’:
          description: created
        ‘400’:
          description: Invalid payload received

 

Como podéis ver, el código es bastante auto explicativo. Pero vamos a hacer hincapié en distintos aspectos:

  • x-wso2-basePath: Extensión para OpenAPI que nos permite indicarle al Microgateway cual es el contexto de la URL asociada a nuestra API. 
  • x-wso2-production-endpoints: Extensión para indicar el backend asociado a nuestra API. 
  • X-wso2-disable-security: Extensión para indicar que no queremos habilitar ningún tipo de seguridad en el recurso donde indicamos las propiedad. 

Microgateway, tiene estas y muchas más extensiones que nos pueden permitir un mayor grado de configuración del que nos ofrece por defecto OpenAPI. 

Para securizar una API, Microgateway permite tokens OAuth2 (opción por defecto), tokens JWT o autenticación Basic. Pero tanto para los tokens JWT como los OAuth2, tendremos que asociar una tercera aplicación que nos provea de estos tokens. Como puede ser el propio Identity Server de WSO2. 

Una vez creada nuestra API como un fichero YAML y almacenado en la carpeta api_definitions, pasaremos a construir el proyecto ejecutando el siguiente comando desde la carpeta que lo contiene.

micro-gw build bookAPI

Cómo desplegar el Docker

Como podemos apreciar, este comando compilara los ficheros en el formato Ballerina. Y es que Microgateway también se basa en esta tecnología para implementar las API.  Despliegue de la API con Docker

Al usar Docker, podremos realizar un despliegue muy rápido, sin necesidad de descargas manuales de binarios o configuración extra. Realizando una aproximación más actual y orientando nuestros servicios al despliegue en la nube.  Para ello, debemos ejecutar el siguiente comando:

 

docker run –net=wso2_nw –name=dockerBookAPI -d -v /temp/bookAPI/target:/home/exec/ -p 9095:9095 -p 9090:9090 -e project=«bookAPI»  wso2/wso2micro-gw:3.0.1

Es importante indicar correctamente la ruta donde se encuentra nuestra API ya compilada y el nombre del proyecto, que es el del fichero compilado. 

Una vez levantadas las dos imágenes, ya solo nos queda comprobar que los dos recursos funcionan correctamente y que tanto el servicio como el Microgateway hacen su trabajo. Podemos realizar esta prueba con los siguientes comandos:

 

curl -X GET http://localhost:9090/bookAPI/v1/book/1

curl -X POST http://localhost:9090/bookAPI/v1/book -H ‘Content-Type: application/json’
  -d ‘{«book»:{«id»:1,»name»:»WSO2 Developer´s Guide»,»author»:»Ramon Garrido, Fidel Prieto»}}’

 

Aquí hemos visto una pequeño ejemplo de lo fácil y sencillo que es crear microservicios con WSO2. Utilizando tecnologías novedosas y facilitando el trabajo de despliegue en la nube. 

Daniel Blanco Chakray