sábado, 31 de julio de 2021

Primeros pasos con Apache Kafka parte 2


Seguimos con Kafka.

Si bien los mensajes son matrices de bytes opacas para el propio Kafka, se recomienda que se imponga una estructura o esquema adicional en el contenido del mensaje para que se pueda entender fácilmente. Hay muchas opciones disponibles para el esquema de mensajes, según las necesidades individuales de su aplicación. Los sistemas simplistas, como Javascript Object Notation (JSON) y Extensible Markup Language (XML), son fáciles de usar y legibles por humanos. Sin embargo, carecen de características como el manejo de tipos robusto y la compatibilidad entre las versiones del esquema. Muchos desarrolladores de Kafka favorecen el uso de Apache Avro, que es un marco de serialización desarrollado originalmente para Hadoop. Avro proporciona un formato de serialización compacto; esquemas que están separados de las cargas útiles del mensaje y que no requieren que se genere código cuando cambian; y datos sólidos tipado y evolución del esquema, con compatibilidad tanto hacia atrás como hacia adelante.

Un formato de datos coherente es importante en Kafka, ya que permite desacoplar la escritura y la lectura de mensajes. Cuando estas tareas están estrechamente vinculadas, las aplicaciones que se suscriben a los mensajes deben actualizarse para manejar el nuevo formato de datos, en paralelo con el formato anterior. Solo entonces se podrán actualizar las aplicaciones que publican los mensajes para utilizar el nuevo formato. Al utilizar esquemas bien definidos y almacenarlos en un repositorio común, los mensajes en Kafka se puedan entender sin coordinación.

Los mensajes de Kafka se clasifican en temas. Las analogías más cercanas para un tema son una tabla de base de datos o una carpeta en un sistema de archivos. Además, los temas se desglosan en un número de particiones. Volviendo a la descripción del "registro de confirmación", una partición es un registro único. Los mensajes se escriben en él de forma de solo anexo y se leen en orden de principio a fin. Tenga en cuenta que, dado que un tema suele tener varias particiones, no hay garantía de que los mensajes se ordenen por tiempo en todo el tema, solo dentro de una única partición. 

Las particiones también son la forma en que Kafka proporciona redundancia y escalabilidad. Cada partición se puede alojar en un servidor diferente, lo que significa que un solo tema se puede escalar horizontalmente en varios servidores para proporcionar un rendimiento mucho más allá de la capacidad de un solo servidor.

El término stream se usa a menudo cuando se habla de datos dentro de sistemas como Kafka. La mayoría de las veces, se considera que una secuencia es un solo tema de datos, independientemente del número de particiones. Esto representa un único flujo de datos que se mueve de los productores a los consumidores. Esta forma de referirse a los mensajes es más común cuando se habla de procesamiento de flujo, que es cuando los frameworks (algunos de los cuales son Kafka Streams, Apache Samza y Storm) operan en los mensajes en tiempo real. Este método de operación se puede comparar con la forma en que los frameworks offline, a saber, Hadoop, están diseñados para trabajar con datos masivos en un momento posterior. 


martes, 27 de julio de 2021

Microsoft CBL-Mariner


Microsoft cambió de rumbo totalmente hace unos años, y empezó a apoyar a toda la comunidad relacionada con Linux. Uno de los grandes pasos que dio fue incluir compatibilidad nativa en el kernel de Windows con Linux para poder ejecutar distros bajo Windows Subsystem for Linux (WSL). De hecho, la compañía hace sus aportaciones al kernel de Linux, y tiene su propio sistema operativo basado en Linux, y ahora lo ha lanzado en GitHub.

Si vamos al repo github vamos a poder leer más o menos lo siguiente: 

CBL-Mariner es una distribución interna de Linux para la infraestructura de nube de Microsoft y los productos y servicios de borde. CBL-Mariner está diseñado para proporcionar una plataforma coherente para estos dispositivos y servicios y mejorará la capacidad de Microsoft para mantenerse al día con las actualizaciones de Linux. Esta iniciativa es parte de la creciente inversión de Microsoft en una amplia gama de tecnologías Linux, como SONiC, Azure Sphere OS y Windows Subsystem para Linux (WSL). CBL-Mariner se comparte públicamente como parte del compromiso de Microsoft con el código abierto y para contribuir a la comunidad de Linux. CBL-Mariner no cambia nuestro enfoque o compromiso con ninguna oferta de distribución de Linux de terceros existente.

CBL-Mariner se ha diseñado con la idea de que un pequeño conjunto de paquetes básicos comunes puede abordar las necesidades universales de los servicios de borde y en la nube de primera, al tiempo que permite a los equipos individuales colocar paquetes adicionales sobre el núcleo común para producir imágenes para sus cargas de trabajo. Esto es posible gracias a un sistema de construcción simple que permite:

Generación de paquetes: esto produce el conjunto deseado de paquetes RPM a partir de archivos SPEC y archivos fuente.

Generación de imágenes: produce los artefactos de imagen deseados, como ISO o VHD, a partir de un conjunto de paquetes determinado.

Ya sea que se implemente como contenedor o como host de contenedor, CBL-Mariner consume recursos limitados de memoria y disco. Las características ligeras de CBL-Mariner también proporcionan tiempos de arranque más rápidos y una superficie de ataque mínima. Al enfocar las funciones de la imagen central en lo que necesitan nuestros clientes de la nube interna, hay menos servicios que cargar y menos vectores de ataque.

Cuando surgen vulnerabilidades de seguridad, CBL-Mariner admite tanto un modelo de actualización basado en paquetes como un modelo de actualización basado en imágenes. Aprovechando el sistema común RPM Package Manager, CBL-Mariner hace que los últimos parches y correcciones de seguridad estén disponibles para descargar con el objetivo de tiempos de respuesta rápidos.

Dejo link: https://github.com/microsoft/CBL-Mariner

Conectarnos con Kafka tool a Kafka.

 El titulo es "Conectarnos con Kafka tool a Kafka." y a donde te vas a conectar a una base de datos oracle. 

Empecemos, bajamos Kafka tool de acá :  https://kafkatool.com/download.html (yo tengo linux así que este post es la instalación en linux) 

Se baja un offsetexplorer.sh y luego lo corremos con : 

sh offsetexplorer.sh 

Luego es similar a cualquier instalación del mundo, next, next ... hasta finish. 

Luego vamos a donde lo instalamos y ejecutamos offsetexplorer

Yo lo voy a conectar al cluster de kafka que hice con docker en este post :

por lo tanto voy a utilizar este puerto : 22181 pero ustedes pueden usar 2181 que es el por defecto. 

A la vez tengo que configurar en avanzado Bootstrats servers, acá esta como debe quedar : 



Si todo salio bien van a ver esto en el árbol de clusters: 

Y listo!!


Instalar Kafka con docker


Vamos a instalar un Kafka broker con docker y con un solo nodo, la idea es tener un Kafka andando para hacer pruebas. 

Antes de empezar tenemos que instalar Zookeper, porque Kafka depende de este, pero lo que podemos hacer es un docker compose que instale todo y listo. 

version: '2'

services:

  zookeeper:

    image: confluentinc/cp-zookeeper:latest

    environment:

      ZOOKEEPER_CLIENT_PORT: 2181

      ZOOKEEPER_TICK_TIME: 2000

    ports:

      - 22181:2181

  

  kafka:

    image: confluentinc/cp-kafka:latest

    depends_on:

      - zookeeper

    ports:

      - 29092:29092

    environment:

      KAFKA_BROKER_ID: 1

      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181

      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092

      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT

      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT

      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1


Como se puede ver tenemos 2 containers, uno para zookeper y otro para kafka. Lo que hacemos es un archivo docker-compose.yml, lo guardamos en un directorio y luego corremos el siguiente comando (en ese directorio) : 

docker-compose up -d

Ahora vemos si esto funciona con el comando grep en el log de kafka : 

docker-compose logs kafka | grep -i started

Si encontramos algunas lineas, estamos. 

Lo proximo a hacer es conectarnos con Kafka tool pero eso es una historia para otro post

domingo, 25 de julio de 2021

¿Por qué Kafka?


Hay muchas opciones para los sistemas de mensajería de publicación/suscripción, entonces, ¿qué hace Apache Kafka es una buena elección?

Múltiples productores

Kafka puede manejar sin problemas a varios productores, ya sea que esos clientes estén usando muchos temas o el mismo tema. Esto hace que el sistema sea ideal para agregar datos de muchos sistemas frontend y hacerlo coherente. Por ejemplo, un sitio que ofrece contenido a los usuarios a través de varios microservicios puede tener un solo tema para las vistas de página en el que todos los servicios pueden escribir utilizando un formato común. Las aplicaciones de consumo pueden recibir un único flujo de vistas de página para todas las aplicaciones del sitio sin tener que coordinar el consumo de varios temas, uno para cada aplicación.

Múltiples consumidores

Además de múltiples productores, Kafka está diseñado para que múltiples consumidores lean cualquier flujo de mensajes sin interferir entre sí. Esto contrasta con muchos sistemas de colas en los que una vez que un cliente consume un mensaje, no disponible para cualquier otro. Múltiples consumidores de Kafka pueden optar por operar como parte de un grupo y compartir un flujo, asegurando que todo el grupo procese un mensaje determinado solo una vez.

Retención basada en disco

Kafka no solo puede manejar varios consumidores, sino que la retención duradera de mensajes significa que los consumidores no siempre necesitan trabajar en tiempo real. Los mensajes se envían al disco y se almacenan con reglas de retención configurables. Estas opciones pueden ser seleccionados por tema, lo que permite que diferentes flujos de mensajes tengan diferentes cantidades de retención según las necesidades del consumidor. La retención duradera significa que si un consumidor se retrasa, ya sea debido a un procesamiento lento o una ráfaga de tráfico, no hay peligro de perder datos. También significa que el mantenimiento se puede realizar en los consumidores, desconectando las aplicaciones durante un corto período de tiempo, sin preocuparse por la copia de seguridad de los mensajes en el productor o por perderse. Se puede detener a los consumidores y los mensajes se conservarán en Kafka. Esto les permite reiniciar y retomar el procesamiento de mensajes donde lo dejaron sin pérdida de datos.

Escalable

La escalabilidad flexible de Kafka facilita el manejo de cualquier cantidad de datos. Los usuarios pueden comenzar con un solo intermediario como prueba de concepto, expandirse a un pequeño grupo de desarrollo de tres intermediarios y pasar a producción con un grupo más grande de decenas o incluso cientos de intermediarios que crece con el tiempo a medida que los datos aumentan. Las expansiones se pueden realizar mientras el clúster está en línea, sin impacto en la disponibilidad del sistema en su conjunto. Esto también significa que un grupo de múltiples corredores puede manejar la falla de un corredor individual y continuar atendiendo a los clientes. Los clústeres que necesitan tolerar más fallas simultáneas se pueden configurar con factores de replicación más altos. 

Alto rendimiento

Todas estas características se combinan para hacer de Apache Kafka un sistema de mensajería de publicación / suscripción con un rendimiento excelente bajo una gran carga. Los productores, consumidores e intermediarios se pueden escalar para manejar flujos de mensajes muy grandes con facilidad. Esto se puede hacer sin dejar de proporcionar una latencia de mensaje de un segundo desde la producción de un mensaje hasta la disponibilidad para los consumidores.

El ecosistema de datos

Muchas aplicaciones participan en los entornos de procesamiento de datos. Tenemos aplicaciones que crean datos o los introducen en el sistema. Sistema de salida que forman métricas, informes y otros productos de datos. Sistemas bucles, con algunos componentes leyendo datos del sistema, transformándolos utilizando datos de otras fuentes y luego volviéndolos a introducir en la infraestructura de datos para usarlos en otros lugares. Esto se hace para numerosos tipos de datos, y cada uno tiene cualidades únicas de contenido, tamaño y uso.

Apache Kafka proporciona el sistema circulatorio para el ecosistema de datos. Transporta mensajes entre los distintos miembros de la infraestructura, proporcionando una interfaz coherente para todos los clientes. Cuando se combina con un sistema para proporcionar esquemas de mensajes, los productores y consumidores ya no requieren un acoplamiento estrecho o conexiones directas de ningún tipo. Los componentes se pueden agregar y eliminar a medida que se crean y se disuelven los casos de negocios, y los productores no necesitan preocuparse por quién está usando los datos o la cantidad de aplicaciones consumidoras.


jueves, 22 de julio de 2021

Primeros pasos con Apache Kafka


Toda empresa funciona con datos. Recibimos información, la analizamos, la manipulamos y creamos más como salida. Cada aplicación crea datos, ya sean mensajes de registro, métricas, actividad del usuario, mensajes salientes u otra cosa. Cada byte de datos tiene un historia para contar, algo de importancia que informará lo siguiente que se debe hacer. Para saber qué es eso, necesitamos obtener los datos desde donde se crean hasta donde se pueden analizar. Vemos esto todos los días en sitios web como Amazon, donde nuestros clics en elementos que nos interesan se convierten en recomendaciones que se nos muestran un poco más tarde.

Cuanto más rápido podamos hacer esto, más ágiles y receptivas podrán ser nuestras organizaciones.

Cuanto menos esfuerzo dediquemos a mover los datos, más podremos concentrarnos en el negocio principal en cuestión. Es por eso que la canalización es un componente crítico en la empresa basada en datos. La forma en que movemos los datos se vuelve casi tan importante como los datos mismos.

Antes de discutir los detalles de Apache Kafka, es importante que comprendamos el concepto de mensajería de publicación/suscripción y por qué es importante. La mensajería de publicación/suscripción es un patrón que se caracteriza porque el remitente (editor) de un dato (mensaje) no lo dirige específicamente a un receptor. En cambio, el editor clasifica el mensaje de alguna manera y ese receptor (suscriptor) se suscribe para recibir ciertas clases de mensajes. Los sistemas Pub/Sub suelen tener un intermediario, un punto central donde se publican los mensajes, para facilitar esto.

Apache Kafka es un sistema de mensajería de publicación/suscripción. A menudo se describe como un "registro de confirmación distribuido" o, más recientemente, como una "plataforma de distribución de transmisión". Un sistema de archivos o un registro de confirmación de la base de datos está diseñado para proporcionar un registro duradero de todas las transacciones, de modo que se puedan reproducir para construir de manera consistente el estado de un sistema. Del mismo modo, los datos de Kafka se almacenan de forma duradera, en orden, y se pueden leer de forma determinista. Además, los datos se pueden distribuir dentro del sistema para proporcionar protecciones adicionales contra fallas, así como oportunidades significativas para escalar el rendimiento.

La unidad de datos dentro de Kafka se llama mensaje. Si lo comparamos con una base de datos, puede pensar en esto como similar a una fila o un registro. Un mensaje es simplemente una matriz de bytes en lo que respecta a Kafka, por lo que los datos que contiene no tienen un formato o significado específico para Kafka. Un mensaje puede tener un bit opcional de metadatos, que se conoce como clave. La clave también es una matriz de bytes y, al igual que con el mensaje, no tiene un significado específico para Kafka. Las claves se utilizan cuando los mensajes deben escribirse en particiones de una manera más controlada. El esquema más simple de este tipo es generar un hash consistente de la clave y luego seleccionar el número de partición para ese mensaje tomando el resultado del módulo hash, el número total de particiones en el tema. Esto asegura que los mensajes con la misma clave siempre se escriban en la misma partición. 

Para mayor eficiencia, los mensajes se escriben en Kafka en lotes. Un lote es solo una colección de mensajes, todos los cuales se producen en el mismo tema y partición. Un viaje de ida y vuelta individual a través de la red para cada mensaje daría como resultado un exceso head, y la recopilación de mensajes en un lote reduce esto. Por supuesto, esta es una compensación entre latencia y rendimiento: cuanto más grandes son los lotes, más mensajes se pueden manejar por unidad de tiempo, pero más tiempo tarda un mensaje individual en propagarse. Los lotes también suelen estar comprimidos, lo que proporciona una transferencia y almacenamiento de datos más eficientes a costa de cierta potencia de procesamiento.

Hasta acá por este post y vamos a seguir en próximos ...

lunes, 19 de julio de 2021

Spinnaker, un servidor de integración continua orientado a la nube.


Creo que todos los lectores del blog ya conocen a Jenkins, un servidor de integración continua muy famoso. Spinnaker es un producto similar hecho por Netfix con la particularidad que fue pensado para la nube. 

Pero tomemonos unos minutos para saber ¿Qué es la integración continua? La integración continua es una practica ligada a la programación extrema que consiste en automatizar el proceso de integración de código para poder realizarlo de la manera más continuada posible. Cuando llega el momento de liberar una nueva versión de una aplicación hay que realizar un proceso de integración de todos los componentes que forman parte de la aplicación. Esto implica realizar varios pasos, como obtener el código fuente, compilarlo, ejecutar los tests, etc.

Jenkins es un producto que corre en la nube y anda muy bien pero Spinnaker fue pensado para la nube, con lo que su configuración es más flexible y esta preparado para entender una orquestación de kubernetes, por ejemplo. 

Dejo link: https://spinnaker.io/

domingo, 18 de julio de 2021

¿Qué es Site Reliability Engineering (SRE)?


SRE es lo que se obtiene cuando trata las operaciones como si fuera un problema de software. La misión de SRE es proteger, proporcionar y hacer progresar el software y los sistemas detrás de todos los servicios con un ojo siempre atento en su disponibilidad, latencia, rendimiento y capacidad.

Google tiene un sitio dedicado a SRE con libros, documentación y un montón de ayuda para las personas que dejan esta área. 

Dejo link: https://sre.google/

sábado, 17 de julio de 2021

Crear una base de datos cassandra con Docker


Antes de empezar tenes que tener docker andando. 

Esto es muy fácil, en dockerhub hay una imagen de cassandra : https://hub.docker.com/_/cassandra

Bueno, en consola ponemos : 

$ docker run --name some-cassandra --network some-network -d cassandra:tag

Donde some-cassandra es el nombre de la base, network es el modo de red que va utilizar y tag es la versión. Yo puse algo así: 

docker run --name demo4-cassandra --network host -d cassandra:4.0

Y listo, cassandra funcionando. 

Ahora tenemos que crear el keyspace, vamos a entrar en el container con el comando: 

docker exec -it some-cassandra bash

Que es similar a lo que ya vimos antes, yo utilice este : 

docker exec -it demo4-cassandra bash

y dentro del container vamos donde esta cassandra : 

cd /opt/cassandra/bin

cqlsh

Y ejecutamos el comando para crear el keyspace : 

cqlsh> CREATE KEYSPACE IF NOT EXISTS demo WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 1 };

cqlsh> use demo;


Y listo!! 

miércoles, 14 de julio de 2021

Libros de Java code geeks

 

Download IT Guides!

 

Groovy Programming Cookbook

Groovy 1.0 was released on January 2, 2007, and Groovy 2.0 in July, 2012. Since version 2, Groovy can also be compiled statically, offering type inference and performance very close to...

 
 

Gradle Build Automation Handbook

Gradle was designed for multi-project builds which can grow to be quite large, and supports incremental builds by intelligently determining which parts of the build tree are up-to-date,...

 
 

Apache Solr Cookbook

Providing distributed search and index replication, Solr is designed for scalability and fault tolerance. Solr is the second-most popular enterprise search engine after Elasticsearch.
...

 
 

Apache Maven Cookbook

An XML file describes the software project being built, its dependencies on other external modules and components, the build order, directories, and required plug-ins. It comes with...

 

domingo, 11 de julio de 2021

Web API en Groovy, Spring boot y H2

Vamos a hacer una web API con Groovy, Spring boot y H2 (como dice el título)

Primero vamos a bajar nuestro proyecto de https://start.spring.io/ bien no sé como indicar lo que hay que seleccionar. Pero creo que es bastante fácil, groovy, h2, etc. Voy a utilizar maven y dejo el link al final del repositorio y pueden ver el pom. 

Para comenzar vamos a hacer nuestras entidades : 

@Entity
@Table(name = 'Demos')
class Demo {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id

@Column
String unTexto

@Column
Boolean isUnCampoBool

@Column
LocalDate unaFecha

@OneToMany(cascade = CascadeType.ALL)
List<DemoItem> items = new ArrayList<>()

}

y

@Entity
@Table(name = 'DemoItems')
class DemoItem {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id

@Column
String unTexto
}

Luego el repositorio : 

@Repository
interface DemoRepository extends JpaRepository<Demo, Integer> {}

Ahora el servicio con su implementación: 

interface DemoService {

List<Demo> findAll()

Optional<Demo> findById(Integer todoId)

Demo insert(Demo demo)

Demo update(Demo demo)

Optional<Demo> delete(Integer id)

}
@Service
class DemoServiceImpl implements DemoService {

@Autowired
DemoRepository repository

@Override
List<Demo> findAll() {
return repository.findAll()
}

@Override
Optional<Demo> findById(Integer id) {
return repository.findById(id)
}

@Override
Demo insert(Demo demo) {
return repository.save(demo)
}

@Override
Demo update(Demo demo) {
return repository.save(demo)
}

@Override
Optional<Demo> delete(Integer id) {
Optional<Demo> demo = repository.findById(id)
if (demo.isPresent()) {
repository.delete(demo.get())
}
return demo
}
}

Y por ultimo el controller : 

@RestController
@RequestMapping('demo')
class DemoController {

@Autowired
DemoService service

@GetMapping
List<Demo> findAll(){
service.findAll()
}

@PostMapping
Demo save(@RequestBody Demo demo){
service.insert(demo)
}

@PutMapping
Demo update(@RequestBody Demo demo){
service.update(demo)
}

@DeleteMapping('/{id}')
delete(@PathVariable Integer id){
Optional<Demo> demo = service.delete(id)
if (!demo.isPresent()) {
throw new NotFoundException<Demo>(id)
}
return demo.get()
}

@GetMapping('/{id}')
Demo getById(@PathVariable Integer id){
Optional<Demo> demo = service.findById(id)
if (!demo.isPresent()) {
throw new NotFoundException<Demo>(id)
}
return demo.get()
}

}

Y el controller lanza una excepción cuando no encuntra elementos que es esta : 

@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "not found")
class NotFoundException<T> extends RuntimeException {

private Long id

NotFoundException() {}

NotFoundException(Long id) {
this.id = id
}

@Override
String getMessage() {
return T + " not found"
}
}

Y listo!!!

Dejo el repositorio Github : https://github.com/emanuelpeg/GroovyWebAPI

jueves, 8 de julio de 2021

EBOOK Gratuito : Real-Time APIs: Design, Operation, and Observation

 


Miren lo que encontré en infoQ : 


EBOOK

Real-Time APIs: Design, Operation, and Observation

Download this free eMagazine from NGINX on effective planning, architecture, and deployment of APIs for reliable flexibility.

DOWNLOAD FOR FREE

Si, se que quedo medio feita las letras, pero bueno...

Dejo link : https://www.nginx.com/resources/library/real-time-api-design-operation-observation/?utm_medium=paid-display&utm_source=infoq&utm_campaign=ww-nx_rtapi&utm_content=eb-sponsoredupdate#download

martes, 6 de julio de 2021

Diferencia entre Null y String vació en C#


Una cadena vacía es una instancia de un objeto System.String que contiene cero caracteres. Las cadenas vacías se utilizan a menudo en varios escenarios de programación para representar un campo de texto en blanco. Puede llamar a métodos en cadenas vacías porque son objetos System.String válidos. Las cadenas vacías se inicializan de la siguiente manera: string s = String.Empty;

Por el contrario, una cadena nula no se refiere a una instancia de un objeto System.String y cualquier intento de llamar a un método en una cadena nula provoca una NullReferenceException. Sin embargo, puede utilizar cadenas nulas en operaciones de concatenación y comparación con otras cadenas. Los siguientes ejemplos ilustran algunos casos en los que una referencia a una cadena nula hace y no provoca que se lance una excepción:


Las operaciones de cadenas en .NET están altamente optimizadas y, en la mayoría de los casos, no afectan significativamente el rendimiento. Sin embargo, en algunos escenarios, como bucles  que se ejecutan cientos o miles de veces, las operaciones de cadenas pueden afectar el rendimiento. La clase StringBuilder crea un búfer de cadenas que ofrece un mejor rendimiento para estos casos. La cadena StringBuilder también le permite reasignar caracteres individuales, algo que el tipo de datos de cadena incorporado no admite. 

Web API en F# y .net 5

Vamos a hacer una web Api con F# y Entity Framework. 

Primero hacer la web Api e instalar Entity Framework. 

dotnet new webapi --language "F#"

dotnet add package Swashbuckle.AspNetCore --version 5.6.3

dotnet new tool-manifest

dotnet tool install dotnet-ef

dotnet tool install paket

dotnet paket convert-from-nuget

dotnet paket add Microsoft.EntityFrameworkCore.Sqlite

dotnet paket add EntityFrameworkCore.FSharp

code  .


Ahora creamos el modelo: 

Hice un archivo Prueba.fs : 

namespace webAPIFsharp

open System

[<CLIMutable>]
type Prueba =
{ Id: int
Name : string
Summary: string }

Y hacemos el dbcontext : 

namespace webAPIFsharp

open System.ComponentModel.DataAnnotations
open Microsoft.EntityFrameworkCore
open EntityFrameworkCore.FSharp.Extensions

type ApiDbContext() =
inherit DbContext()

[<DefaultValue>]
val mutable pruebas : DbSet<Prueba>

member public this.Pruebas with get() = this.pruebas
and set p = this.pruebas <- p

override _.OnModelCreating builder =
builder.RegisterOptionTypes() // enables option values for all entities

override __.OnConfiguring(options: DbContextOptionsBuilder) : unit =
options.UseSqlite("Data Source=base.db") |> ignore

Ahora debemos indicar que compile estas clases agregando estas entradas en el fsproj : 

<Compile Include="Prueba.fs" />
<Compile Include="ApiDbContext.fs" />

Luego compilamos 

dotnet build

Si funciona debemos hacer la migración : 

dotnet ef migrations add Initial

Y ahora agregamos la migración a fsproj :

<Compile Include="Migrations/*.fs" />

Y ahora creamos la base : 

dotnet ef database update

Y ahora agregamos el context a el Startup.fs : 

// Configure EF
services.AddDbContext<ApiDbContext>() |> ignore

Y luego hacemos el controler : 

namespace webAPIFsharp.Controllers

open System
open System.Collections.Generic
open System.Linq
open System.Threading.Tasks
open Microsoft.EntityFrameworkCore
open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.Logging
open webAPIFsharp

[<ApiController>]
[<Route("[controller]")>]
type PruebaController (logger : ILogger<PruebaController>,
dbContext : ApiDbContext) =
inherit ControllerBase()


[<HttpGet>]
member _.Get() = ActionResult<IEnumerable<Prueba>>(dbContext.Pruebas)

[<HttpPost>]
member _.PostSync(prueba:Prueba) =
dbContext.Pruebas.Add prueba |> ignore
dbContext.SavedChanges |> ignore


[<HttpPost("async")>]
member _.PostAsync(entity: Prueba) =
async {
dbContext.Pruebas.AddAsync(entity) |> ignore
let! _ = dbContext.SaveChangesAsync true |> Async.AwaitTask
return entity
}

[<HttpGet("{id}")>]
member _.getById id =
dbContext.Pruebas
|> Seq.tryFind (fun f -> f.Id = id)

Y listo! 

dotnet run

Yo agregue swagger para mayor detalles dejo link de github: 

https://github.com/emanuelpeg/FsharpWebApiExample


sábado, 3 de julio de 2021

Clases y métodos genéricos en C#


Generics introduce el concepto de parámetros de tipo en .NET, lo que hace posible diseñar clases y métodos que difieren la especificación de uno o más tipos hasta que la clase o método sea declarado e instanciado por el código del cliente. Veamos un ejemplo: 


Las clases y métodos genéricos combinan la reutilización, la seguridad de tipos y la eficiencia de una manera que sus contrapartes no genéricas no pueden. Los genéricos se utilizan con mayor frecuencia con las colecciones y los métodos que operan en ellas. El espacio de nombres System.Collections.Generic contiene varias clases de colección basadas en genéricos. Las colecciones no genéricas, como ArrayList, no se recomiendan y se mantienen por motivos de compatibilidad.

Veamos un ejemplo: 



Un método declarado con los parámetros de tipo para su tipo o parámetros de retorno se denomina método genérico.



Los métodos AddorUpdate () y GetData () son métodos genéricos. El tipo de datos real del parámetro del elemento se especificará en el momento de instanciar la clase DataStore <T>, como se muestra a continuación.


Una clase no genérica puede incluir métodos genéricos especificando un parámetro de tipo entre paréntesis angulares con el nombre del método, como se muestra a continuación.


viernes, 2 de julio de 2021

DateTime en C# parte 2


 Seguimos con: https://emanuelpeg.blogspot.com/2021/07/datetime-en-c.html

La estructura DateTime incluye los siguientes métodos para convertir una fecha y hora en una cadena.

Método

Descripción

ToString

Convierte un valor DateTime en una cadena en el formato especificado de la referencia cultural actual. Permite pasar el formato de fecha por parámetros.

ToShortDateString

formato M/d/yyyy

ToShortTimeString

formato h:mm:ss

ToLongDateString

formato dddd, MMMM d, yyyy

ToLongTimeString

formato h:mm:ss tt




Veamos un ejemplo: 



Una cadena de fecha y hora válida se puede convertir en un objeto DateTime usando los métodos Parse (), ParseExact (), TryParse () y TryParseExact ().

Los métodos Parse () y ParseExact () generarán una excepción si la cadena especificada no es una representación válida de una fecha y hora. Por lo tanto, se recomienda usar el método TryParse () o TryParseExact () porque devuelven falso si una cadena no es válida. 

Veamos un ejemplo: 




jueves, 1 de julio de 2021

The Complete NGINX Cookbook

Ma llego este mail con un libro gratuito : 

NGINX Cookbook

Level up on NGINX with this free O'Reilly eBook, updated for 2021. Get sample configurations for the most popular NGINX deployments: load balancing, caching, security, cloud deployment, automation, containers and microservices, high availability, performance tuning, and more.

In this ebook you will learn:

  • Solutions for more than 100 real‑world application delivery use cases, presented as easy-to-follow recipes
  • How to protect your applications with NGINX App Protect, plus configurations for mitigating DDoS attacks, stopping Layer 7 attacks, and enabling single sign‑on with OpenID Connect
  • How to configure NGINX for features like gRPC, microservices and containers, API gateways, and more
  • About using NGINX Controller to optimize your NGINX deployment