Gonzalo Fernández Rodríguez

Gonzalo Fernández Rodríguez

CTO Cybersecurity - Telefónica Tech
Cloud
¿Qué significa que mi aplicación sea Cloud Native?
El término Cloud Native es algo que va más allá de mover las aplicaciones alojadas en un data center a una infraestructura proporcionada por un proveedor Cloud, sea Cloud pública o privada. Esto, que se conoce como “lift & shift” de aplicaciones a la nube, no es más que un proceso en el que nuestras aplicaciones dejan de correr en la infraestructura on-premises de nuestro data center para pasar a ejecutarse en una infraestructura Cloud, aunque en muchas ocasiones esto sucede sin ningún tipo de rediseño en la arquitectura de dichas aplicaciones, ni en las prácticas de construcción, despliegue y operación de las mismas. Obviamente, incluso en ese caso, podremos aprovechar unos beneficios básicos “out of the box” al usar una infraestructura que tiene una mayor redundancia, facilidades para realizar backups, o que se mantiene actualizada con los últimos parches de seguridad, entre otras ventajas. Pero tenemos que tener en cuenta que nuestra aplicación no se va a convertir en una aplicación Cloud Native por el hecho de desplegarla en la nube: si tienes un sistema que es una castaña y lo despliegas en un cluster EKS de kubernetes de AWS... tendrás una castaña 'kubernetizada'. Nuestra aplicación no se va a convertir en una aplicación Cloud Native solo por el hecho de desplegarla en una infraestructura Cloud. Cloud ha cambiado las reglas del juego No hace tanto era necesario hacer un buen estudio de las capacidades (potencia de computación, conectividad, almacenamiento...) que necesitaríamos para que nuestro desarrollo ofreciera un servicio con garantías. Al menos de entrada, porque después, periódicamente, había que evaluar el crecimiento del sistema y comprar más hardware si no queríamos que nuestros clientes nos abandonaran cuando aquello dejara de funcionar. Hoy en día es posible hacer todo esto con un par de clics en una consola de administración. O mejor aún, con una llamada a una API (Application Program Interface) que nos permite además automatizar este proceso. La tecnología Cloud pone a nuestra disposición las capacidades de cómputo, red, almacenamiento así como otros servicios más avanzados (bases de datos, sistemas de colas de mensajes, analítica de datos, etc.) como abstracciones definidas por software dando lugar a lo que se conoce como Cloud Computing. Cloud Computing viene a ser, en definitiva, esos recursos de computación que necesitamos para construir nuestros sistemas (CPU, almacenamiento, red, etc.) pero disponibles en la red. Además, los podemos ir consumiendo bajo demanda, ofreciendo una eficiencia en costes y una escalabilidad nunca vistas antes. Cloud Native es consecuencia de la necesidad de escalar Está claro entonces que Cloud ha cambiado la tecnología sobre la cual construimos y desplegamos nuestros sistemas. Pero, ¿por qué motivo? Dar un único motivo quizás sería un poco arriesgado, aunque lo que sí podemos afirmar es que Cloud Computing resuelve un problema de escalabilidad. En los últimos años, las soluciones digitales —plataformas de gaming, streaming de video, música, redes sociales, etc.— se consumen cada vez más desde distintos dispositivos. No solo desde ordenadores, también desde teléfonos móviles, tablets, smart TV e, incluso, dispositivos IoT (Internet of Things) que han ido creado diferentes escenarios de acceso a nuestros sistemas. El objetivo de las aplicaciones Cloud Native es aprovechar las ventajas de la nube para mejorar la escalabilidad, el rendimiento y la eficiencia Escenarios donde el número de peticiones y el volumen de datos va cambiando. Es decir, escenarios que requieren que nuestro sistema siga funcionando correctamente ante cambios de demanda de recursos, en definitiva, escenarios que requieren que nuestro sistema sea “escalable”. Sin embargo, esto no es gratis: la gestión de esta escalabilidad en nuestros servicios se vuelve más compleja, los métodos tradicionales ya no sirven, necesitamos otra forma de hacer las cosas. Al igual que en su día surgieron los PC —y con ellos las arquitecturas cliente/servidor necesarias para aprovechar su capacidad de cómputo— descargando así a los viejos “mainframes” de hacer todo el trabajo de nuestros sistemas. Aparejado a este cambio tecnológico que llamamos Cloud Computing, y para dar respuesta a la gestión de esa escalabilidad, surgen nuevos patrones de arquitectura y también nuevas prácticas para operar nuestros sistemas dando lugar al término Cloud Native. "Los sistemas Cloud Native están diseñados con la capacidad de crecer o decrecer de forma dinámica." Por eso, cuando decimos que un sistema o una aplicación es Cloud Native, realmente no nos estamos refiriendo a si se ejecuta en Cloud. Sino a cómo ha sido diseñado para ejecutarse y operarse de forma correcta sobre tecnología Cloud Computing, beneficiándose además de las ventajas de dicha tecnología. Los sistemas Cloud Native se diseñan de tal forma que tengan la capacidad de crecer/decrecer de forma dinámica y de que se puedan actualizar. Y todo ello sin pérdida de servicio, lo que se conoce como "zero downtime". Zero downtime no significa un uptime perfecto, sino cumplir un objetivo por el cual no se percibe interrupción del servicio a lo largo del funcionamiento de una aplicación[1]. Cloud Native según la CNCF (Cloud Native Computing Foundation) Hoy en día los usuarios no tenemos la misma paciencia que hace años, cuando veíamos totalmente normal que una página web tardase unos segundos en cargar o que un vídeo en streaming tuviera cierta latencia e incluso que se detuviera de vez en cuando. Cada día los servicios son más sofisticados y los usuarios demandan sistemas que funcionen con una percepción excelente. Ya no son tan pacientes. El nivel de escalabilidad proporcionado por la tecnología Cloud hace posible que aplicaciones de redes sociales, mensajería instantánea, streaming de vídeo o de audio permitan que millones de usuarios puedan conversar, subir fotos, vídeos, ver películas o escuchar música incluso al mismo tiempo. Los usuarios no quieren fallos y demandan que los servicios estén funcionado bien continuamente. Y esto es complicado en un entorno tan cambiante como es el de Cloud. La CNCF habla del término Cloud Native como un conjunto de tecnologías que nos permite construir y ejecutar aplicaciones escalables en entornos modernos y dinámicos como plataformas Cloud públicas, privadas e híbridas y multicloud. También nos dice que los sistemas resultantes son débilmente acoplados, resilientes, administrables, observables y que, además, con una buena automatización van a permitir que podamos introducir cambios de forma frecuente y predecible con poco esfuerzo. Cloud Cloud Computing como factor clave para un futuro más sostenible 14 de diciembre de 2022 Atributos de Cloud Native para construir sistemas fiables y resilientes En un entorno tan cambiante como es Cloud, va a ser necesario que diseñemos nuestros sistemas para que sean capaces de reaccionar ante posibles errores. Si conseguimos que nuestros sistemas tengan estos atributos que define la CNCF para las aplicaciones Cloud Native (escalables, débilmente acoplados, resilientes, maleables y observables), seremos capaces de mantener a nuestros clientes satisfechos al proporcionarles sistemas que funcionan de forma continua. Si consideramos cada uno de estos atributos podremos ver cómo nos ayudan a conseguir que nuestros sistemas sean fiables y funcionen prácticamente sin interrupciones: Escalabilidad: si diseñamos nuestros sistemas para que sean capaces de funcionar sin estado, conseguiremos que nuestros sistemas sean escalables y por tanto serán capaces de adaptarse ante un crecimiento inesperado de demanda de recursos, es una forma de “prevenir fallos”. Acoplamiento débil: que nuestros sistemas estén débilmente acoplados evitando compartir dependencias como podría ocurrirnos cuando diseñamos un sistema basado en microservicios y terminamos generando un monolito distribuido (donde cambios en un microservicio no pueden ser hechos sin cambios en otros), permitirá que puedan evolucionar y escalar aquellos componentes o servicios (o microservicios) que se necesiten de forma independiente y, además, también logrará prevenir fallos derivados de los cambios necesarios en múltiples componentes si estuvieran acoplados. Resiliencia: mediante la redundancia de componentes o la aplicación de ciertos patrones que eviten la propagación en cascada de fallos podemos hacer que nuestros sistemas sean más resilientes y por tanto puedan seguir funcionando aún cuando ocurran ciertos fallos, es decir, conseguiremos que nuestro sistema sea tolerante a fallos. Administrable: si diseñamos nuestros sistemas de modo que puedan ser fácilmente configurables, conseguiremos poder cambiar ciertos comportamientos del mismo sin necesidad de desplegar una nueva versión del mismo, incluso podríamos eliminar posibles errores que hayan surgido. Observable: por último, deberíamos de tomar medidas (métricas) de distintos indicadores de nuestros sistemas que podamos observar continuamente para poder predecir errores o comportamientos no deseados y actuar antes de que ocurran. Cloud Native permite gestionar toda la complejidad que supone tener esa capacidad casi ilimitada que proporciona Cloud Computing. Mediante la aplicación de patrones de diseño y prácticas de operación, conseguimos que nuestros sistemas sean incluso más fiables que la infraestructura Cloud sobre la que se ejecutan (por ejemplo un failover entre dos regiones de una Cloud) al mismo tiempo que el usuario tenga una confianza plena en el funcionamiento de nuestro sistema. * * * [1] Sobre la capacidad de planificar en base a la percepción de calidad del servicio por parte del usuario, existen una serie de libros escritos por ingenieros de Google —conocidos como SRE o Ingenieros de Resiliencia del Servicio— que extienden el concepto de SLA y al mismo tiempo que añaden nuevos como SLI o SLO. Fotografía principal: Shahadat Rahman / Unsplash
24 de enero de 2023
Cloud
Manageability: la importancia de un sistema maleable en un mundo Cloud Native
Hace poco publicamos el post Castañas en la nube o que significa que mi software sea cloud native en el que tratábamos de explicar qué significaba el término Cloud Native y qué atributos tendrían que tener nuestras aplicaciones/sistemas para que realmente pudieran ser considerados como Cloud Native. Comentamos la necesidad de escalar que tienen las aplicaciones de ahora derivada de la fuerte demanda de recursos de las actuales aplicaciones, necesidad a la que daba respuesta la tecnología Cloud Computing ofreciendo bajo demanda los recursos necesarios (casi infinitos), de forma instantánea y pagando solo por su uso. Sin embargo, cualquier aplicación/sistema distribuido lleva asociado una complejidad, en parte heredada de la dependencia que tienen entre sí los diferentes subsistemas que lo componen (almacenamiento, red, cómputo, bases de datos, servicios/microservicios de negocio, etc.). Inevitablemente el hardware fallará alguna vez, la red sufrirá cortes, los servicios podrán bloquearse y no responder, etc. Con este panorama no basta con mover las aplicaciones desde los entornos “on-prem” a los entornos “cloud” para convertirlas en aplicaciones Cloud Native, tienen que ser capaces de sobrevivir en entornos de este tipo, recuperarse y seguir funcionando sin que los usuarios perciban esos problemas. Por tanto, han de ser diseñadas para soportar fallos y, en definitiva, ser más fiables que la infraestructura sobre la que se ejecutan, es decir, tienen que ser resilientes. Además de estos posibles fallos (hardware, red, servicios, etc.), existen otros elementos como son los posibles cambios en el negocio, una fluctuación de demanda de nuestros servicios o la ejecución de los mismos en distintos entornos que hacen que tengamos que actuar sobre nuestras aplicaciones para que incorporen nuevas funcionalidades o para que sigan funcionando correctamente y sin interrupciones como desean los usuarios. El cómo de fácil o difícil sea para nuestras aplicaciones poder cambiar su comportamiento, bien sea para activar/desactivar alguna funcionalidad, bien para desplegar/replegar más nodos del servicio sin downtime[1], o para hacer un failover[2] desde uno o más recursos que han dejado de funcionar hacia otros que aún están disponibles es de lo que vamos a hablar hoy en este post. ¿A qué nos referimos cuando decimos que nuestra aplicación es maleable? En nuestro anterior artículo decíamos que uno de los atributos de una aplicación Cloud Native, según la CNCF, era “manageable”. Nosotros hablamos de administrable, pero probablemente el término maleable sea más acertado. Cuando decimos que un material es maleable nos referimos a que podemos cambiar su forma sin romperlo, y sin ningún proceso de fundición, fusión, o cualquier otro proceso industrial o químico que se nos pueda ocurrir. Buscando una analogía en el mundo software, podríamos decir que una aplicación es maleable cuando podemos modificar su comportamiento desde fuera, sin necesidad de tocar su código y sin necesidad de detener la aplicación, es decir “sin romperla”, sin que ningún usuario perciba que algo ha dejado de funcionar aunque sea momentáneamente. Es importante destacar la diferencia entre que nuestra aplicación sea maleable o “manageable” con que nuestra aplicación sea mantenible, en cuyo caso haríamos referencia a la facilidad con la que podríamos cambiar el comportamiento o evolucionar nuestra aplicación desde dentro, es decir, haciendo cambios en el código, algo que es igualmente muy importante, pero que no es objeto de este artículo. Para poder entender mejor lo que queremos decir, imaginemos que tenemos una aplicación o sistema en ejecución que se encuentra proporcionando un determinado servicio a N clientes, el cual necesitamos modificar por algún motivo, como por ejemplo: Hay una demanda creciente/decreciente de clientes, y necesitamos incrementar/decrementar el número de ciertos recursos del sistema. Ojo, no estamos hablando de cómo resolver la escalabilidad (supongamos que nuestro servicio ha sido diseñado sin estado y está preparado para escalar horizontalmente[3 sin problemas). Hemos desarrollado una nueva versión de nuestra aplicación, la hemos probado en nuestros entornos de pruebas y queremos ejecutarla en un entorno productivo donde el código es exactamente el mismo, pero los recursos como la red, las BBDD, el almacenamiento, etc. son otros. Hemos detectado un problema en la configuración de un componente que hace que el servicio se comporte de forma errónea y necesitamos modificar esa configuración. La clave para conseguir esto no está en mover nuestras aplicaciones a un entorno cloud como hemos comentado anteriormente, la clave está en seguir una serie de prácticas en el diseño de la arquitectura de nuestras aplicaciones para conseguir que no sólo podamos modificar su comportamiento sino que se pueda hacer de una forma sencilla y ágil haciendo que los usuarios perciban que el sistema funciona correctamente en todo momento. ¿Pero cómo conseguimos que nuestra aplicación sea maleable? Observable Bien, si esto va de hacer cambios en un sistema que está dando servicio en un entorno productivo, primero de todo hemos de enterarnos cuando es necesario hacer esos cambios. En el post Observability qué es, qué ofrece, nuestro compañero Dani Pous nos hizo una introducción a la importancia de que nuestras aplicaciones sean observables, ya que gracias a ello sabremos lo que está ocurriendo en todo momento y podremos tomar decisiones basadas en esa información que recogen nuestras métricas, logs y trazas. Si queremos que nuestra aplicación sea maleable, es fundamental que sepamos cuándo tomar esas decisiones, para ello es necesario que dediquemos tiempo a diseñar alarmas que activen los mecanismos automáticos correspondientes que cambien el comportamiento de nuestro sistema (por ejemplo detectar un cluster de BD que no responde para poder hacer un failover automático otro), y también los dashboards que nos den información necesaria para hacer un cambio manual en la configuración y que nuestra aplicación se actualice sin necesidad de reiniciarse (por ejemplo, incrementar un timeout en un fichero de configuración para evitar rechazar peticiones de cliente). Configurable En segundo lugar, es necesario que nuestra aplicación tenga algún mecanismo para que de forma externa podamos cambiar su comportamiento. Tenemos que tratar de identificar qué partes de nuestra aplicación han de ser parametrizables (cadenas de conexión a BD, URLs para la invocación de servicios web, threads, memoria o CPUs activas para el performance, etc.). Esta configuración o parametrización es algo que puede cambiar entre distintos entornos (development, integration, production, etc.). La mayoría de los lectores habrán oído hablar de The Twelve-Factor App, para los que no lo conozcan, es una metodología que crearon en su momento varios desarrolladores de Heroku y que establece doce principios que ayudan a crear aplicaciones en la cloud aportando beneficios como portabilidad, paridad[4] entre los entornos de desarrollo y los de producción o mayor facilidad para escalar entre otros. Variables de Entorno Uno de estos doce principios hace referencia a la configuración de las aplicaciones y nos indica que el código de las aplicaciones se mantiene entre los distintos entornos en los que se ejecuta. Sin embargo, la configuración varía, y por eso es importante que la configuración se mantenga separada del código. Añadimos también la importancia de que esa configuración se encuentre versionada en un sistema de control de versiones para facilitar la restauración de una configuración específica en caso de que fuera necesario. Las variables de entorno tienen la ventaja de que son fáciles de implementar y de cambiar entre despliegues sin cambiar el código, además son soportadas por cualquier lenguaje y cualquier sistema operativo. Pero no todo son ventajas en el uso de variables de entorno. Las variables de entorno definen un estado global y están compartidas con otras muchas variables, con lo cual hemos de tener cuidado a la hora de definirlas para que no se pisen, además tampoco pueden gestionar configuración más compleja que una cadena de texto. En todo caso para representar configuración a nivel de entornos (Development, Staging, Production, etc.) son una solución muy adecuada. Argumentos en Línea de Comandos Otra opción utilizada para la configuración de aplicaciones simples, que además no requiere de ningún fichero, son los argumentos en línea de comandos. Este tipo de configuración, que se proporciona en la línea de comandos cuando arrancamos una aplicación, está indicado para cuando interactuamos con scripts. Sin embargo cuando las opciones de configuración se complican, los argumentos en línea de comandos no son una opción manejable, se complican en exceso y además tienen un formato inflexible Ficheros de Configuración Los ficheros de configuración por otra parte ofrecen también muchas ventajas, especialmente cuando tenemos aplicaciones verdaderamente complejas, entre otras cosas porque permiten representar estructuras más complejas que pueden agrupar lógica de nuestra aplicación que está relacionada. No obstante, cuando usamos ficheros de configuración puede ser complicado mantener la integridad de la configuración en todo momento de los nodos de un cluster, ya que tendremos que distribuir esta configuración a cada uno de los nodos. Este problema puede mejorarse mediante la incorporación de una solución tipo etcd o consul que nos ofrecen un sistema de almacenamiento (clave, valor) de forma distribuida. Despliegues y reconfiguraciones sin parada de servicio Por último, y no menos importante, necesitamos contar con un sistema de despliegue automatizado que permita entre otras cosas: Actualizar todos los nodos necesarios de un sistema a la nueva configuración. Los tiempos en los que una persona del equipo de operaciones actualizaba la configuración de los diferentes nodos que daban servicio a un sistema o componente del mismo han pasado a la historia. Hoy en día hay servicios que soportan millones de usuarios y tiene miles de nodos activos. ¿Alguien se imagina cómo actualizar miles de nodos si no es de forma automática? Gestionar el escalado/desescalado de los componentes de un sistema/aplicación de forma progresiva sin necesidad de detener el servicio. Esto incluye tareas como el despliegue de la infraestructura, despliegue del software, configuración de balanceadores, etc. Afortunadamente, el uso extendido de contenedores y orquestadores como Kubernetes en las aplicaciones Cloud Native, hace que el problema de distribución de la configuración disminuya en gran medida, ya que estas plataformas ofrecen mecanismos especializados para esto, como por ejemplo el “ConfigMap” de Kubernetes, que permite también gestionar tanto variables de entorno, como parámetros en línea de comandos y ficheros de configuración. Asimismo, Kubernetes facilita el despliegue de nuevas versiones mediante la aplicación de lo que se conoce como “Rolling Updates”, este técnica permite ir actualizando las distintas instancias de nuestras aplicaciones de forma progresiva, alojando las nuevas versiones en nodos con recursos disponibles, al tiempo que va eliminando las instancias de la versión anterior, consiguiendo de esta forma un despliegue con el ansiado “Zero Downtime”. En todos los casos hemos de trabajar siempre con el concepto de inmutabilidad, en el cual las imágenes de los contenedores desplegados en nuestra aplicación así como los objetos de configuración son inmutables. De este modo, una vez desplegadas las aplicaciones, cualquier cambio requerirá la sustitución del contenedor por una nueva imagen o del fichero de configuración u objeto (si por ejemplo tenemos un ConfigMap de Kubernetes) por el de la nueva versión. Conclusión Las aplicaciones Cloud Native usan arquitecturas basadas en microservicios, esto facilita que las aplicaciones se puedan desarrollar y evolucionar más fácilmente (equipos independientes, desacoplamiento funcional, independencia de tecnologías, etc.). El uso de contenedores para el despliegue de los microservicios (e.g: Docker) y los orquestadores de contenedores (e.g: K8s) cada vez más extendidos facilitan el escalado, desescalado de las aplicaciones y la gestión de miles de nodos dentro de una aplicación/servicio. Sin embargo, todas estas facilidades no vienen exentas de problemas, la gran cantidad de nodos que pueden estar dando servicio en una aplicación Cloud Native hace que se multiplique el número de posibles fallos y por tanto es necesario que diseñemos nuestros sistemas con la mente puesta en que van a fallar. Adicionalmente, hemos de ser capaces de distribuir las nuevas versiones (tanto de código como de configuración) a través de un enorme número de instancias y sin que los usuarios perciban una pérdida del servicio. La cantidad enorme de máquinas, servicios, etc. manejados dentro de nuestras aplicaciones hace inviable que estos cambios puedan ser manuales y exige además que trabajemos con el concepto de inmutabilidad para garantizar que cada cambio está asociado a una versión que puede ser restaurada en cualquier momento. Referencias https://livebook.manning.com/book/cloud-native-spring-in-action/chapter-1/v-1/87 https://docs.microsoft.com/en-us/dotnet/architecture/cloud-native/definition https://12factor.net/config [1] Tiempo de indisponibilidad de una máquina o un servicio [2] Procedimiento mediante el cual un sistema transfiere el control a otro (duplicado) cuando se detecta un fallo en el primero. [3] Estrategia de crecimiento para que un servicio tenga mayor capacidad basada en el aumento del número de instancias que responden a las peticiones de los clientes. [4] Se refiere a la importancia que tiene el que los entornos de desarrollo y productivos sean lo más similares posibles con el objetivo de reducir el tiempo entre que el código está listo y es llevado a producción.
14 de septiembre de 2021
Ciberseguridad
Creación de un proxy de alto rendimiento basado en paquetes para una Telco
Durante hoy y mañana está teniendo lugar el Golab 2018 en Florencia, la conferencia más importante de desarrollo en Golang de Italia donde se están impartiendo una gran variedad de conferencias relacionadas con el desarrollo software, patrones, arquitecturas y workshops. Además, participan más de 450 developers de distintos países. ElevenPaths también está presente, nos han aprobado un paper y nuestro compañero Jorge Lorenzo del equipo de CTO impartirá hoy la conferencia “Building a packet-based high-performance proxy for a telco”. Durante esta ponencia, contará cómo en ElevenPaths hemos sido capaces de crear con nuestra “propia tecnología” un Safe Proxy que puede desplegarse en el core de la red de un operador telco, y es capaz de proteger el tráfico web de sus clientes (malware, control parental, privacidad y bloqueo de publicidad). El paper describe la ventaja de usar un approach basado en Deep Packet Inspection versus un proxy tradicional orientado a conexiones, y la facilidad de construir un sistema de estas características utilizando las capacidades nativas que ofrece el kernel de Linux, así como la productividad y eficiencia que ofrece el lenguaje de programación Go. El SafeProxy permite aplicar una configuración personalizada para cada usuario de la red del operador, en la que podrá activar/desactivar las siguientes funcionalidades: Protección web (antiMalware y antiPhishing) Control parental Anti-Tracking Ad-blocking Por ejemplo, podríamos activar la protección web y el control parental a los usuarios infantiles para evitar que accedan a contenidos inadecuados o peligrosos. ¿Cómo funciona? Nuestro SafeProxy analiza el tráfico de los siguientes protocolos: HTTP, HTTPS, DNS y QUIC, soportando IPV4 e IPV6 en la capa de red. El SafeProxy obtiene el dominio al que se conecta el usuario y lo clasifica en una de las categorías anteriores (Protección Web, Control Parental, Anti-Tracking y Ad-Blocking), y en función de lo que tenga configurado el usuario en su perfil bloqueará o no el tráfico. El dominio se consigue inspeccionando la capa de aplicación de los paquetes que depende del protocolo (e.g. en HTTP se obtiene de la cabecera Host pero en HTTPS se obtiene del SNI en la negociación SSL). El SafeProxy implementa un DPI sobre las capacidades que proporciona el netfilter del kernel de Linux. En concreto, utilizamos el protocolo nfqueue para encolar aquellos paquetes TCP/IP que puedan ser de interés para extraer el dominio del tráfico del usuario, delegando la decisión de bloquear o cursar el paquete al SafeProxy (ejecutado en el espacio de usuario del sistema operativo). Esta solución simplifica la implementación, proporciona un alto rendimiento y resiliencia (e.g. si se cae el SafeProxy no se perdería ningún paquete porque nfqueue cursaría el tráfico si SafeProxy no lo resuelve en un tiempo determinado). Proxy Orientado a Paquetes vs Proxy Orientado a Conexiones La siguiente tabla muestra una comparación de nuestro SafeProxy orientado a paquetes frente a una solución orientada a conexiones también desarrollada en ElevenPaths en el lenguaje C++. Conclusiones Esta experiencia nos ha demostrado que el uso de la tecnología Go para la creación de un sistema de alto rendimiento para el procesamiento de tráfico masivo en tiempo real ha sido altamente satisfactoria: La sencillez del lenguaje, su inmensa librería nativa incorporada en el runtime así como el modelo de concurrencia nativo que incorpora el lenguaje hace que este sea altamente productivo, poco propenso a errores y tenga un rendimiento muy alto, cercano a lenguajes como el C ó C++. Si bien hemos de reconocer que Go no ofrece un performance al mismo nivel de C ó de C++, el cambio de paradigma hecho en el SafeProxy ha dado unos resultados espectaculares en nuestro benchmark como se puede ver en la tabla anterior dónde se ha reducido el consumo de CPU en más de un 75 % al mismo tiempo que el número de transacciones por segundo (TPS) crece un orden de magnitud con tiempos de respuesta que se reducen en más de un 90 %. Gonzalo Fernández Rodriguez CTO- ElevenPaths Cybersecurity Manager gonzalo.fernandezrodriguez@telefonica.com
23 de octubre de 2018