tag:blogger.com,1999:blog-92913352024-03-07T20:29:18.627+01:00Raticos tecnológicosReflexiones, artículos, opiniones, recomendaciones, noticias... sobre la tecnología.Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comBlogger755125tag:blogger.com,1999:blog-9291335.post-68743804437132956112023-06-02T20:43:00.004+02:002023-06-24T19:48:41.882+02:00Desarrollo seguro: Protección de datos<p> La seguridad de los datos debe estar amparada bajo los siguientes preceptos:</p><p></p><ul style="text-align: left;"><li><b>Autenticación.</b> Se verifica la identidad del usuario para poder acceder al dato.</li><li><b>Autorización. </b>El usuario solo puede realizar las operaciones que le permite los privilegios otorgados a sus roles sobre los datos a los que tiene permiso.</li><li><b>Confidencialidad.</b> Cuando los datos se almacenan o están en tránsito deben estar protegidos contra la observación o divulgación no autorizada.</li><li><b>Integridad. </b>Los datos deben estar protegidos contra manipulaciones por parte de posibles atacantes.</li><li><b>Disponibilidad. </b>Los datos siempre han de estar disponibles para los usuarios autorizados. Esto incluye también las políticas de copias de respaldo.</li></ul><div><br /></div><h2 style="text-align: left;">Posibles riesgos</h2><div>A continuación se describen algunos de los posibles riesgos relativos a la protección de datos:</div><div><ul style="text-align: left;"><li><b>Incumplimiento de normas y leyes</b> relativas al tratamiento de datos personales, lo que supone sanciones legales.</li><li><b>Pérdida de información sensible.</b></li><li><b>Pérdida de información sensible de terceros.</b> Esto puede originar acciones legales y sanciones.</li><li><b>Pérdida de reputación</b> de la organización.</li><li><b>Pérdida de certificaciones.</b></li></ul><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj20u7IUAfv5zK4eYdz5k0yTRREGWrf25zbraX3-YzWbx13Dk7RisxbeQ_GgjjS3I-oMT34FOzAEhbEm3apkUzDLhAzmfwR--PGrCB1tNw-xKP4pNdPKHLWxHZpQoaDaas6ed4UG7gCgKiqLpey5TIG3Ny5h7AmgCotjDVIvMp3u404K2yYzA/s1920/electronic-security.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1216" data-original-width="1920" height="406" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj20u7IUAfv5zK4eYdz5k0yTRREGWrf25zbraX3-YzWbx13Dk7RisxbeQ_GgjjS3I-oMT34FOzAEhbEm3apkUzDLhAzmfwR--PGrCB1tNw-xKP4pNdPKHLWxHZpQoaDaas6ed4UG7gCgKiqLpey5TIG3Ny5h7AmgCotjDVIvMp3u404K2yYzA/w640-h406/electronic-security.jpg" width="640" /></a></div><div style="text-align: center;"><i>Imagen: <a href="https://www.publicdomainpictures.net/en/view-image.php?image=208970&picture=electronic-security" target="_blank">public domain pictures</a> </i></div></div><div><br /></div><h2 style="text-align: left;">Mejores prácticas</h2><div>He aquí algunas recomendaciones para elevar la seguridad en la protección de datos:</div><div><ul style="text-align: left;"><li>Identificar toda la información relativa a datos personales y aplicar las políticas de tratamiento de datos personales (acceso, procesamiento, almacenamiento, etc), acorde a las leyes y legislaciones del país.</li><li>Los datos confidenciales no pueden viajar en los parámetros de las urls. Deben hacerlo en el cuerpo o en las cabeceras HTTP.</li><li>Los canales de comunicación en los que se transmiten los datos deben utilizar cifrado robusto.</li><li>Los datos confidenciales deben cifrarse de forma segura antes de su almacenamiento.</li><li>Evitar que los datos confidenciales se almacenen en la caché de los navegadores.</li><li>Sobreescribir la memoria con ceros cuando la información confidencial ya no se utilice.</li><li>Aplicar una política de borrado seguro para los datos que alcanzan el final de su ciclo de vida.</li></ul><div><br /></div></div><div><h3>Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div></div><div><br /></div><div><br /></div><p></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-25429135199149043852023-06-02T20:37:00.006+02:002023-06-02T20:37:36.702+02:00Desarrollo seguro: comunicaciones<p>La transmisión de información en las aplicaciones es un punto clave de seguridad, por lo que es esencial asegurar la confidencialidad, la integridad y la disponibilidad de las comunicaciones.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI9M1PG6rKoKqyT3lKuZAbe3hzN17sDXloBgpxrKCP3slCw8Sz-jEK8l5rqXPCJUHHCdEhQlNoh1p6xfzmIKqAtX4B6jm9BRkBW5yJdC9Naohx3CC-OEyGlu37mtFgU9zJPUkX7d7PCjC58tcGrSpN4fblGGD99YmD8SNx1ftmNyQAaeTatQ/s1920/netzwerk-total-004.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI9M1PG6rKoKqyT3lKuZAbe3hzN17sDXloBgpxrKCP3slCw8Sz-jEK8l5rqXPCJUHHCdEhQlNoh1p6xfzmIKqAtX4B6jm9BRkBW5yJdC9Naohx3CC-OEyGlu37mtFgU9zJPUkX7d7PCjC58tcGrSpN4fblGGD99YmD8SNx1ftmNyQAaeTatQ/w640-h360/netzwerk-total-004.jpg" width="640" /></a></div><p style="text-align: center;"><i>Imagen: <a href="https://www.publicdomainpictures.net/en/view-image.php?image=266335&picture=network-totally-004" target="_blank">public domain pictures</a></i></p><p><br /></p><h2 style="text-align: left;">Posibles riesgos</h2><p>A continuación se describen algunos de los posibles riesgos relativos a las comunicaciones:</p><p></p><ul style="text-align: left;"><li>Robo de información confidencial.</li><li>Interrupción del servicio.</li><li>Suplantación de identidad.</li><li>Alteración o destrucción de datos.</li><li>Propagación de software malicioso.</li></ul><p></p><p><br /></p><h2 style="text-align: left;">Mejores prácticas</h2><p>He aquí algunas recomendaciones para elevar la seguridad en las comunicaciones:</p><p></p><ul style="text-align: left;"><li>Utilizar siempre canales de comunicación cifrados mediante TLS o WebSocket.</li><li>Usar criptografía robusta. </li><li>Utilizar protocolos seguros, como HTTPS o FTPS</li></ul><div><br /></div><p></p><h3>Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-42090226152703832802023-06-02T13:24:00.004+02:002023-06-02T13:24:42.496+02:00Desarrollo seguro: transacciones<p>Las transacciones son operaciones críticas de negocio, como pagos o actividades financieras. Debido a su especial sensibilidad requieren fuertes medidas de seguridad, tales como:</p><p></p><ul style="text-align: left;"><li><b>Autenticación. </b>Uso de contraseñas seguras y MFA para autorizar el acceso a las transacciones.</li><li><b>Criptografía.</b> Asegurar la confidencialidad de las transacciones.</li><li>Validación. Aseguramiento de la legitimidad de las transacciones, evitando ataques y fraudes.</li><li>Monitorización. Permite detectar y prevenir de ataques y fraudes en tiempo real.</li><li>Copias de seguridad. Permite recuperar la disponibilidad de los datos en caso de ataques, caídas del sistema o pérdidas de datos.</li></ul><div>Las transacciones deben cumplir las propiedades ACID: Atomicity, Consistency, Isolation y Durability.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzcEYkoX8OsrlcZxFpOpSkvIbRS0zEZmmZvrAsK7KfzN4t8y_PRhNiJbsYo3j2EqhrSsvGx_9PDOP4vuw7KP_TAYkVoMicfObfuEdbB7SMha5ZGr0r43sRx_CScz4KZpVscglpGfWWyRC489zNCGHxhJQjT1f1tCHPD8N5He-kFAUgys5fRg/s700/payment.webp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="359" data-original-width="700" height="328" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzcEYkoX8OsrlcZxFpOpSkvIbRS0zEZmmZvrAsK7KfzN4t8y_PRhNiJbsYo3j2EqhrSsvGx_9PDOP4vuw7KP_TAYkVoMicfObfuEdbB7SMha5ZGr0r43sRx_CScz4KZpVscglpGfWWyRC489zNCGHxhJQjT1f1tCHPD8N5He-kFAUgys5fRg/w640-h328/payment.webp" width="640" /></a></div><br /><div style="text-align: center;"><i>Imagen: <a href="https://www.linnworks.com/blog/online-payment-methods" target="_blank">linnworks</a></i></div><div><br /></div><h3 style="text-align: left;">Posibles riesgos</h3><div>A continuación se describen algunos de los posibles riesgos relativos a las transacciones:</div><div><ul style="text-align: left;"><li><b>Payment Bypass.</b> Vulnerabilidad de configuración que permite a un atacante manipular, en un sistema de pago, los parámetros y la respuesta entre cliente y servidor para eludir el sistema de pago.</li><li><b>Fraude.</b> El atacante se beneficia de forma ilícita, manipulando las transacciones o usando información falsa.</li><li><b>Robo de información confidencial.</b> Para ser usada en futuros ataques.</li><li><b>Interrupción de las transacciones. </b>Con ataques DoS/DDoS.</li><li><b>Pérdida de datos. </b>Puede afectar a la confidencialidad y a la integridad de la información.</li></ul><div><br /></div></div><h3 style="text-align: left;">Mejores prácticas</h3><div>He aquí algunas recomendaciones para elevar la seguridad en las transacciones:</div><div><ul style="text-align: left;"><li>Evitar un Payment Bypass:</li><ul><li>Toda compra ha de autorizarse y confirmarse en el servidor.</li><li>Validar la autenticidad de las firmas durante la comunicación con la pasarela de pago.</li><li>Verificar el precio correcto en el servidor.</li><li>Asegurar que los pagos no se reutilizan.</li><li>Comprobar la fase actual de la transacción en el servidor de pago.</li></ul><li>Para cada transacción, configurar un tiempo corto de expiración.</li><li>Llevar una trazabilidad fehaciente de las transacciones.</li><li>Utilizar comunicaciones con cifrado asimétrico.</li><li>Registrar el detalle de cada operación, anonimizando los datos sensibles.</li></ul><div><br /></div></div><div><br /></div><p></p><h3>Referencias</h3><div><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><div><br /></div></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-44900345412818586202023-06-02T13:18:00.007+02:002023-06-02T13:18:52.889+02:00Desarrollo seguro: gestión de archivos<p>Los archivos son activos esenciales en la seguridad de un sistema de información, pues contiene y persiste gran parte de la información. Por ello, la gestión de archivos debe contemplarse desde la fase de diseño, identificando los archivos internos, los archivos que se cargan, su ubicación, el control de acceso, la copia de seguridad, el flujo de la información, los datos que contiene, etc.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinBna5oucphdIF0KJ03M9Tvk2Lq9_uwCUh1KKvPyZlSQMfvpSKZz6Lq-cAtVJfX5-wdu_iLbm36XzFf2MKuqfuzMSyPsWyIGEPoIo1wZ9rXZfyJxVG03i7JgfGfqSwN2-n8DJtvtAktNE2pE9xkjbYRZyxLtTjNFgscRQGOsMF7Veqf-BiFA/s600/files.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinBna5oucphdIF0KJ03M9Tvk2Lq9_uwCUh1KKvPyZlSQMfvpSKZz6Lq-cAtVJfX5-wdu_iLbm36XzFf2MKuqfuzMSyPsWyIGEPoIo1wZ9rXZfyJxVG03i7JgfGfqSwN2-n8DJtvtAktNE2pE9xkjbYRZyxLtTjNFgscRQGOsMF7Veqf-BiFA/w640-h426/files.jpeg" width="640" /></a></div><p style="text-align: center;"><i>Imagen: <a href="https://www.imageapi.com/blog/what-is-a-digital-document" target="_blank">imageapi</a></i></p><p><br /></p><h3 style="text-align: left;">Posibles riesgos</h3><p>A continuación se describen algunos de los posibles riesgos relativos a la gestión de archivos:</p><p></p><ul style="text-align: left;"><li><b>Acceso no autorizado.</b> Implicaría la revelación, manipulación, pérdida o borrado de datos.</li><li><b>Carga de archivos maliciosos.</b> Podría ejecutar archivos de forma remota, provocar una infección de malware o realizar un ataque de denegación de servicio.</li><li><b>Carencia de copias de seguridad.</b> Provocaría la pérdida de datos a la organización, la pérdida de datos de usuario o la falta de disponibilidad del servicio. </li></ul><p></p><p><br /></p><h3 style="text-align: left;">Mejores prácticas</h3><p>He aquí algunas recomendaciones para elevar la seguridad en la gestión de archivos:</p><p></p><ul style="text-align: left;"><li>Exigir la autenticación y la autorización de cada usuario al acceder a un archivo.</li><li>El nombrado de archivos y directorios no puede ser realizado con entradas de usuario.</li><li>Validar el tipo de contenido por encima de la extensión del archivo.</li><li>Verificar el tipo MIME del archivo.</li><li>Impedir la subida de archivos ejecutables.</li><li>Para evitar problemas de disponibilidad y de impacto en el servidor, limitar el tamaño del archivo.</li><li>Procesar los archivos mediante un antivirus y antimalwares.</li><li>En el directorio de subida de archivos de usuarios, desactivar los privilegios de ejecución.</li><li>Al proporcionar un enlace de descarga a un usuario, no facilita rutas absolutas (canonización de path).</li><li>Evitar el nombrado secuencial de archivos.</li><li>En el nombre de un archivo, no utilizar datos sensibles.</li><li>El acceso al archivo debe ser de sólo lectura.</li><li>Poner límite al número de archivos que puede subir un usuario.</li><li>Para asegurar su integridad, almacenar los hashes de cada archivo subido.</li></ul><div><br /></div><p></p><h3>Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-76598762936610121382023-06-02T13:12:00.006+02:002023-06-02T13:12:40.579+02:00Desarrollo seguro: criptografía<p> La criptografía protege la información, garantizando la:</p><p></p><ul style="text-align: left;"><li><b>Autenticidad. </b> Se verifica la identidad de las personas y sistemas que acceden a la información.</li><li><b>Confidencialidad. </b>Solamente las personas autorizadas pueden acceder a la información.</li><li><b>Integridad.</b> Solamente las personas autorizadas podrán alterar la información.</li></ul><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghhUkG1jc7UWZJIIyAoZdBRKoGQlubTGF0NCmInK0AhMpmMF0gGBJmKvVfpOqb-Ovo_AlIWsGQmMe_ZBhhIJwBtsnhPEsKnnQHiNBM7cmXCGotWjJ4lEDha9EJRO3EM9tr8J4bVeF4oqTy9YwteibYMo2GDYP-wjPpxWCMebKUEwWVrmh7TQ/s1280/Usos-de-Criptografia.webp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1280" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghhUkG1jc7UWZJIIyAoZdBRKoGQlubTGF0NCmInK0AhMpmMF0gGBJmKvVfpOqb-Ovo_AlIWsGQmMe_ZBhhIJwBtsnhPEsKnnQHiNBM7cmXCGotWjJ4lEDha9EJRO3EM9tr8J4bVeF4oqTy9YwteibYMo2GDYP-wjPpxWCMebKUEwWVrmh7TQ/w640-h360/Usos-de-Criptografia.webp" width="640" /></a></div><br /><div style="text-align: center;"><i>Imagen: <a href="https://criptotendencia.com/2019/06/06/que-otros-usos-tiene-la-criptografia-a-parte-de-las-criptomonedas/" target="_blank">Cripto Tendencia</a></i></div><div><br /></div><div>La criptografía se puede usar para generar firmas digitales que aseguren la integridad de los datos, o también para cifrar datos sensibles.</div><div><br /></div><div><br /></div><h3 style="text-align: left;">Cifrado</h3><h4 style="text-align: left;">Funciones hash</h4><div>Un hash se obtiene a través de una función matemática, dando como resultado un resumen de datos de una cantidad siempre fija, independientemente del número de datos de entrada. La probabilidad de que se genere el mismo hash con diferentes datos de entrada (colisión) es muy improbable, lo que ofrece un alto nivel de seguridad. </div><div><br /></div><div>Un hash concreto solamente puede obtenerse con la misma función, los mismos datos de entrada y en el mismo orden, lo que es idóneo para almacenar contraseñas o para verificar la integridad (no alteración) de los datos. </div><div><br /></div><div><br /></div><h4 style="text-align: left;">Cifrado simétrico</h4><div>En este tipo de cifrado protege la confidencialidad en la transmisión y el almacenamiento de los datos, utilizando la misma clave para cifrar y descifrar la información. La ventaja es que fácil y rápido de implementar, pero, por contra, tanto el emisor como el receptor deben compartir la clave, lo que se convierte en un punto débil, especialmente en entornos distribuidos.</div><div><br /></div><div><br /></div><h4 style="text-align: left;">Cifrado asimétrico</h4><div>Este cifrado requiere dos claves diferentes. La clave pública es compartida públicamente y se utiliza para cifrar la información, mientras que la clave privada se mantiene en secreto, y solo puede ser usada para descifrar.</div><div><br /></div><div>La ventaja de este cifrado es que no es necesario compartir la clave privada para establecer una comunicación segura. La desventaja es que es más lento y difícil de implementar que el cifrado simétrico.</div><div><br /></div><div><br /></div><h3 style="text-align: left;">Posibles riesgos</h3><div>A continuación se describen algunos de los posibles riesgos relativos al uso de información que no esté suficientemente encriptada:</div><div><ul style="text-align: left;"><li><b>Exposición de información sensible. </b>Disponibilidad de esta información para usuarios no autorizados.</li><li><b>Robo de credenciales y suplantación de identidad. </b>El acceso a contraseñas permitirían a un atacante suplantar a un usuario.</li><li><b>Fuga de datos personales. </b>El robo de datos personales son punibles y sancionables según las regulaciones de cada país.</li><li><b>Ataques Man in the Middle (MitM). </b>Se pueden interceptar comunicaciones poco aseguradas y descubrir el flujo de datos que lleve a información útil y valiosa para realizar ataques.</li><li><b>Reputación para la organización</b>.</li></ul></div><div><br /></div><h3 style="text-align: left;">Mejores prácticas</h3><div>He aquí algunas recomendaciones para elevar la seguridad en la criptografía:</div><div><ul style="text-align: left;"><li>Evitar el uso de algoritmos criptográficos antiguos u obsoletos, como DES, MD5 o SHA-1.</li><li>Usar librerías criptográficas reputadas.</li><li>Toda información sensible y confidencial debe estar fuertemente cifrada para asegurar la confidencialidad.</li><li>Los números aleatorios utilizados en ids, códigos, nombres de archivos y cadenas se generan a través de un generador de números aleatorios disponible en una librería criptográfica reputada.</li><li>Los números aleatorios se deben generar con un nivel entropía adecuado.</li><li>Aplicar políticas de gestión de claves criptográficas para la generación, distribución, revocación y desactualización.</li><li>Para evitar ataques de volcado de memoria, sobreescribir con ceros la información crítica que deje de utilizarse.</li></ul></div><div><br /></div><div><br /></div><div><h3>Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-69603531794483361682023-06-02T13:06:00.001+02:002023-06-02T13:06:09.888+02:00Desarrollo seguro: el registro de seguridad<p>Es imprescindible tener un registro (o log) en un entorno protegido, el cual registre toda actividad o evento del sistema o de las aplicaciones, en lo concerniente a la seguridad. Este registro es vital para un posible análisis forense en un futuro.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIGyJGUpiroO-DqVbXGysAOpw8w8QSy0Yr0mTONnXZjZWeSWGbf_w4unnC7CAY9H7Zo5lKOb2NJEFt_xBSvylkWvWFdcuUUsTRzO4jG81CvLd-U1S-bJR4SqdbjeHGQDBs40kxEaw-5NEasjRzkvtt_TIH1uS1RFEEqOIoYaiDy1gkgamxPQ/s852/security_log.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="852" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIGyJGUpiroO-DqVbXGysAOpw8w8QSy0Yr0mTONnXZjZWeSWGbf_w4unnC7CAY9H7Zo5lKOb2NJEFt_xBSvylkWvWFdcuUUsTRzO4jG81CvLd-U1S-bJR4SqdbjeHGQDBs40kxEaw-5NEasjRzkvtt_TIH1uS1RFEEqOIoYaiDy1gkgamxPQ/w640-h360/security_log.jpg" width="640" /></a></div><div style="text-align: center;"><i>Imagen: <a href="http://goodfreephotos.com">goodfreephotos.com</a></i></div><p>El registro de seguridad ha de cumplir los siguientes requisitos:</p><p></p><ul style="text-align: left;"><li><b>Trazabilidad. </b>Debe tener un formato temporal que facilite la trazabilidad de los eventos.</li><li><b>Auditabilidad.</b> Ha de almacenarse de forma segura y durante un tiempo mínimo de retención, a efectos de auditoría.</li><li><b>Autenticación/autorización.</b> El acceso a este registro sólo estará disponible para personas autenticadas y autorizadas.</li><li><b>Confidencialidad.</b> El registro ha de asegurar que no puede ser accedido por medios distintos a la autenticación y autorización. Los datos sensibles deben ser cifrados.</li><li><b>Integridad. </b>El registro debe asegurar que no hay manipulaciones a nivel de registro ni de entradas. Para ello, se recomienda el uso de firmas de integridad que se actualicen con cada nueva entrada.</li><li><b>Disponibilidad. </b>Su almacenamiento debe ser redundante y contar con copias de respaldo.</li></ul><p></p><p><br /></p><h3 style="text-align: left;">Posibles riesgos</h3><p>A continuación se describen algunos de los posibles riesgos relativos al registro de seguridad:</p><p></p><ul style="text-align: left;"><li><b>Fuga de información.</b> Si hubiera vulnerabilidad en la autorización, un atacante podría acceder a la información sensible del registro.</li><li><b>Falsificación de registros.</b> Una falta de integridad permitiría a un usuario no autorizado a manipular las entradas del registro, con lo que rompería la trazabilidad. Esto también podría llegar a provocar la ejecución de código malicioso.</li><li><b>Eliminación de registros.</b> Un atacante podría eliminar sus propias entradas en el registro, para eliminar su actividad.</li></ul><div><br /></div><h3 style="text-align: left;">Mejores prácticas</h3><div>He aquí algunas recomendaciones para elevar la seguridad en el registro de seguridad:</div><div><ul style="text-align: left;"><li>Evitar registrar datos sensibles (como datos personales, contraseñas, tarjetas de crédito, información financiera, etc). Si se registra, cifrar esta información mediante criptografía, tokens o anonimización.</li><li>Validar los datos antes de registrar la entrada, a fin de garantizar la información y evitar inyecciones.</li><li>Registrar el detalle de cada entrada:</li><ul><li>Intentos de autenticación, sobre todo, los fallidos.</li><li>Accesos concedidos con roles, incluyendo el usuario.</li><li>Acceso a datos sensibles: qué usuario, qué roles, qué acciones se han realizado.</li><li>Errores de validación de las entradas.</li><li>Excepciones del sistema.</li><li>Amenazas e intentos de amenazas detectados.</li></ul><li>Usar funciones hash para verificar la integridad de las entradas.</li><li>Mantener el registro de seguridad en un entorno protegido e independiente de otros registros.</li></ul></div><div><br /></div><p></p><h3>Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><p></p><div><br /></div><div><br /></div><p></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-71052314184339080482023-06-02T12:59:00.000+02:002023-06-02T12:59:53.040+02:00Desarrollo seguro: gestión de errores<p>La gestión de errores se refiere, por una parte, al control de la información que se expone cuando ocurre un error, y, por otra parte, a cómo controlar los errores no controlados en una aplicación.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP9KabF8Fuznz4yf55_4csFJB2mrAmRsSACwgGNayMpm27pwGcpHeO8jpRsSRkisIZhM-cl07QIdUdRN1vQh9YIs6NRddiZl-3F1RZEXGg1YzuO9X4kCy3B-TkprBVHIx1CX4AxuG_leNAom1KsCKQdNV6iu2c_QNgwCQjcoXE1Rr74-P0Uw/s980/error.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="489" data-original-width="980" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP9KabF8Fuznz4yf55_4csFJB2mrAmRsSACwgGNayMpm27pwGcpHeO8jpRsSRkisIZhM-cl07QIdUdRN1vQh9YIs6NRddiZl-3F1RZEXGg1YzuO9X4kCy3B-TkprBVHIx1CX4AxuG_leNAom1KsCKQdNV6iu2c_QNgwCQjcoXE1Rr74-P0Uw/w640-h320/error.jpg" width="640" /></a></div><p><br /></p><h3 style="text-align: left;">Cuidado con la información mostrada</h3><p>Hay que tener especial cuidado a la hora de mostrar la información de un error, pues podemos revelar inconscientemente información que podría ser aprovechada por un atacante. Esta información podría ser, por ejemplo, parte de la configuración de la aplicación, algún estado, mensajes de depuración, datos sensibles o confidenciales, el tiempo que tarda en ejecutarse algunas operaciones, códigos importantes, usuarios y/o contraseñas, ids de sesión, elementos de la infraestructura o de la arquitectura, versiones, etc. Esta información promueve algunos riesgos tales como:</p><p></p><ul style="text-align: left;"><li><b>Fuga de información sensible:</b> estructura de archivos, documentos sensibles, motor de base de datos, versión del servidor, etc.</li><li><b>Denegación de servicio.</b> Ciertos errores forzados podrían provocar la caída del sistema.</li><li><b>Cross-Site Scripting.</b> Un mensaje de error podría revelar parámetros de entrada sin validación de caracteres de escape.</li></ul><br /><h3 style="text-align: left;">Control de errores</h3><p>Es de vital importancia controlar que todas las operaciones prevean y gestionen todas las excepciones posibles, pues una excepción no controlada podría provocar una salida inesperada de la lógica de negocio que exponga vulnerabilidades que puedan ser aprovechadas por un atacante.</p><p>Un punto probable de errores inesperados puede surgir cuando no se cierran correctamente los recursos, por lo que se recomiendo el cierre de estos dentro de un bloque try/catch/finally.</p><p>Algunos posibles riesgos producidos por un deficiente control de errores podrían ser:</p><p></p><ul style="text-align: left;"><li><b>Denegación de servicio.</b> El abuso de ciertas operaciones no controladas podrían causar la caída del sistema.</li><li><b>Saltarse la lógica de negocio.</b> Se podrían forzar excepciones o errores no controlados, los cuales producirían salidas inesperadas de la lógica de negocio.</li></ul><p></p><p><br /></p><h3 style="text-align: left;">Mejores prácticas</h3><p>He aquí algunas recomendaciones para elevar la seguridad en la gestión de errores:</p><p></p><ul style="text-align: left;"><li>Usar mensajes genéricos en los errores, para no dar pistas sobre datos sensibles.</li><li>Usar un control de excepciones centralizado.</li><li>Manejar los errores sin depender de los mensajes de error del servidor mostrados al usuario.</li><li>Por defecto, denegar el acceso en caso de un error en el control de acceso.</li><li>Estudiar en profundidad todas las excepciones de una librería para su correcto tratamiento e implementación.</li><li>Asegurar el cierre de todos los recursos dentro de bloques try/catch/finally.</li><li>Registrar en detalle todas las excepciones en un registro específico dentro de un entorno seguro.</li></ul><p></p><p><br /></p><p></p><h3>Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><p> </p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-19042302318660939472023-06-02T12:15:00.001+02:002023-06-02T12:15:06.987+02:00Desarrollo seguro: validación de datos<p>Lo más crítico en la seguridad de un sistema de información son los datos, por lo que hay que asegurar que el tratamiento de los mismos no exponen vulnerabilidades, y por ello, para evitar ataques, es indispensable una correcta validación, tanto en la entrada como en la salida.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn5QpM3NFFiu91XJMPUt5as4DLRWb1oN8_rcJnv8OyxuH57dm-hFQkhtog17cnTYilU2VFMCfqjVLbccz_oTaj4VIpP1gTkLYfwHbC_GjqeIDBOre-kvc939DVpcGElhfq--5lMtYQVApO_EnpNMvfzygINdvPanWWHV4q9Vm3sL3lveRm7A/s640/validation.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="640" data-original-width="640" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn5QpM3NFFiu91XJMPUt5as4DLRWb1oN8_rcJnv8OyxuH57dm-hFQkhtog17cnTYilU2VFMCfqjVLbccz_oTaj4VIpP1gTkLYfwHbC_GjqeIDBOre-kvc939DVpcGElhfq--5lMtYQVApO_EnpNMvfzygINdvPanWWHV4q9Vm3sL3lveRm7A/w400-h400/validation.jpg" width="400" /></a></div><p style="text-align: center;"><i>Imagen: <a href="https://www.maxpixel.net/Tick-Asterisk-Green-Cross-Yellow-Red-Check-40678" target="_blank">maxpixel</a></i></p><p><br /></p><h3 style="text-align: left;">Técnicas de validación</h3><h4 style="text-align: left;">Sanitización</h4><p>Consiste en normalizar toda posible representación de un dato a un formato único o estándar, reduciendo los problemas de validación y el número de ataques.</p><p>Existen varios métodos de sanitización, algunos de los cuales pueden encontrarse en librerías o paquetes. Los métodos más comunes son:</p><p></p><ul style="text-align: left;"><li><b>Rutas:</b> Se normalizan rutas a directorios (por ejemplo en Unix), lo que evita que un atacante navegue a un directorio sensible y obtenga información no autorizada.</li><li><b>Espacios:</b> Se eliminan espacios, tabulaciones y otros caracteres blancos del dato.</li><li><b>Charset:</b> Se normalizan los caracteres del datos a un charset en concreto, tratando de forma concreta aquellos caracteres que no pertenecen a dicho charset.</li><li><b>Case:</b> Se convierten los caracteres a mayúsculas o minúsculas.</li></ul><div><br /></div><h4 style="text-align: left;">Tipos de datos</h4><div>Se verifica que el dato sea de un tipo concreto. El tipo puede ser simple (entero, decimal, carácter, boolean, string) o complejo (email, nif, código postal, url, etc).</div><div><br /></div><div><br /></div><h4 style="text-align: left;">Formato</h4><div>Dentro de los tipos complejos, permite validar el formato de éstos mediante patrones o expresiones regulares. </div><div><br /></div><div>Importante: Una expresión regular compleja puede ser vulnerable a un ataque ReDoS, por lo que es aconsejable validar previamente la expresión con herramientas como RegEx Testing o RegEx 101.</div><div><br /></div><div><br /></div><h4 style="text-align: left;">Tamaños mínimos y máximos</h4><div>Controlando un umbral de tamaños (longitud) se evitan cuelgues en el procesamiento del dato.</div><div><br /></div><div><br /></div><h4 style="text-align: left;">Valores mínimos y máximos</h4><div>Ejerce un control sobre un umbral de valores para un dato.</div><div><br /></div><div><br /></div><h4 style="text-align: left;">Lista blanca</h4><div>El dato se encuentra dentro de una lista o conjunto de datos prefijados, como una enumeración.</div><div><br /></div><div><br /></div><h4 style="text-align: left;">Lista negra</h4><div>El dato no se debe encontrar dentro de una lista o conjunto de datos prefijados.</div><div><br /></div><div><br /></div><p></p><div><h3>Posibles riesgos</h3></div><div><p>A continuación se describen algunos de los posibles riesgos relativos a la validación de datos:</p></div><p></p><div><ul style="text-align: left;"><li><b>Cross-Site Scripting: </b>Un atacante podría inyectar código a través de un dato, por ejemplo en un navegador web.</li><li><b>Inyección SQL:</b> Un atacante inyectaría código SQL a través de los datos, siendo ejecutado por la base de datos.</li><li><b>Inyección LDAP: </b>Un atacante inyectaría consultas LDAP para obtener más privilegios o para acceder a datos restringidos.</li><li><b>Inyección de Log:</b> Un atacante podría inyectar comandos de ejecución en el sistema usando los logs que registran los datos.</li><li><b>Inyección XEE: </b>Un atacante podría acceder a datos restringidos o la información de la estructura de un árbol XML a través de una inyección XPATH.</li><li><b>Bomba XML:</b> Un atacante podría provocar un ataque de denegación de servicio sobrecargando el XML y agotando los recursos de la memoria de la aplicación.</li><li><b>DoS, DDoS y ReDoS: </b>Un atacante podría provocar una denegación de servicio del sistema o de la aplicación si no hay una validación adecuada de las entradas. </li></ul></div><div><br /></div><h3 style="text-align: left;">Mejores prácticas</h3><div>He aquí algunas recomendaciones para elevar la seguridad en la validación de datos:<br /><ul style="text-align: left;"><li>Las validaciones son siempre obligatorias en el servidor y recomendadas en el cliente.</li><li>Utilizar esquemas de validación de datos y mecanismos estándar que aseguren la validación de datos mediante las técnicas de validación vistas anteriormente.</li><li>Realizar las validaciones utilizando librerías estandarizadas.</li><li>Los datos estructurados han de estar bien tipificados y validados por un esquema definido.</li><li>Los datos no estructurados deben ser sanitizados, utilizando alguna librería de sanitización.</li><li>No mostrar información sensible ante un error de validación.</li><li>En las entradas de datos, solamente aceptar aquellos datos que sean los esperados. Si alguno de los datos de entrada no es el esperado, rechazarlo.</li><li>El servidor debe rechazar cualquier petición en la que exista algún error de validación de entrada.</li><li>Las consultas a bases de datos deben estar parametrizadas, para así evitar la inyección SQL.</li><li>Los frameworks ORM no están exentos de vulnerabilidades de inyección SQL. Consultar la documentación del ORM y utilizar consultas parametrizadas siempre que sea posible.</li><li>Verificar si la aplicación es vulnerable a inyección de comandos.</li><li>Asegurar que las páginas web utilizan plantillas que automaticen las variables dentro del código HTML, para evitar XSS (Cross-Site Scripting)</li><li>Utilizar la configuración más restrictiva posible para el análisis XML, desactivando funciones peligrosas, como la resolución de entidades externas.</li><li>Evitar la deserialización de datos no confiables o protegerse contra éstos.</li></ul><div><br /></div></div><p></p><h3>Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><p></p><div><br /></div><div><br /></div><div><br /></div><div><br /></div><p></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-73986730802147008572023-06-02T08:17:00.004+02:002023-06-02T08:17:28.408+02:00Desarrollo seguro: gestión de sesiones<p>Cuando un usuario se autentica en el sistema y obtiene la autorización en el mismo, se crea una nueva sesión identificada mediante un id, la cual crea una conexión activa usuario-sistema, almacenando información temporal sobre las operaciones y la lógica de negocio exclusivas de ese usuario mientras dure dicha sesión.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCkmVAySkQA8MNyfQ0WPBtwH5ZQ7yfjVWw9Mhl1HL_1PF5QNoCtDNDFuVytqAvMa9qFqCP88D8_U7NoIS8NxXFIU6LAn89c8ByUu5Src3dYcGCLQ3c_PwKCNxiVoj8zp_j8VCX4qS6hwTe5s1Pm7wNLMOQMNcxpdFedtngIkyKYijA8wwQXg/s5616/terminal-hacker-computer-ubuntu.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2641" data-original-width="5616" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCkmVAySkQA8MNyfQ0WPBtwH5ZQ7yfjVWw9Mhl1HL_1PF5QNoCtDNDFuVytqAvMa9qFqCP88D8_U7NoIS8NxXFIU6LAn89c8ByUu5Src3dYcGCLQ3c_PwKCNxiVoj8zp_j8VCX4qS6hwTe5s1Pm7wNLMOQMNcxpdFedtngIkyKYijA8wwQXg/w640-h300/terminal-hacker-computer-ubuntu.jpg" width="640" /></a></div><p style="text-align: center;"><i>Imagen: <a href="https://www.wallpaperflare.com/terminal-hacker-computer-ubuntu-linux-wireless-technology-wallpaper-cndyf/download" target="_blank">Wallpaperflare</a></i></p><p>Una vez establecida la sesión, para poder llevar a cabo las operaciones, el usuario se identificará con el servidor mediante cookies o mediante tokens. En el caso de las cookies, éstas se almacenan en el navegador del cliente, lo que es un sistema poco seguro y no recomendable. Los tokens, sin embargo, se asocian al id de la sesión y viajan en la cabecera de las peticiones, y pueden modificarse por intercambio cada cierto tiempo sin necesidad de cambiar el id de la sesión, la cual permanece en el lado del servidor, lo que es un método mucho más seguro que el de las cookies.</p><p><br /></p><h3 style="text-align: left;">Aspectos de seguridad</h3><h4 style="text-align: left;">Aspectos básicos</h4><p></p><ul style="text-align: left;"><li>Asegurar que la autenticación sólo permite acceder a las personas acreditadas.</li><li>Asegurar las autorizaciones correctas para las personas autenticadas.</li><li>Asegurar la comunicación cliente-servidor mediante cifrado fuerte.</li></ul><div><br /></div><h4 style="text-align: left;">Sesión del lado cliente</h4><div><ul style="text-align: left;"><li>La información persistente del id de sesión del cliente quedará asociada a la pestaña, y si ésta se cierra o desaparece, desaparecerá toda esa información. Esto se logra mediante código en la propia página o mediante el objeto sessionStorage.</li><li>La información persistente de la sesión del cliente se ha de borrar en la pantalla de login y generarse una vez creada la sesión en el servidor.</li><li>En pantallas que puedan necesitar mucho tiempo (por ejemplo, un formulario), permitir que la sesión de cliente realice transacciones vacías contra el servidor, para indicar que la sesión sigue activa y no expire.</li><li>El cliente también debe controlar el tiempo de inactividad, lanzando una petición al servidor para que cierre la sesión, tras lo cual se redirigirá a la pantalla de login.</li><li>La información de la sesión del cliente ha de ser mínima para la lógica de navegación. No debe contener información sensible. A lo sumo, puede contener el token de acceso para no arrastrarlo en todas las peticiones.</li><li>Evitar ataques de fijación de sesión mediante un tiempo de espera de inicio de sesión.</li><li>Capturar los eventos de cierre de pestaña o de la ventana del navegador, a fin de forzar tanto el cierre de la sesión de cliente como del servidor.</li></ul></div><div><br /></div><h4 style="text-align: left;">ID de sesión</h4><div><ul style="text-align: left;"><li>El id de sesión ha de ser único, aleatorio y con una longitud muy grande, como un hash criptográfico seguro.</li><li>El id ha de ser validado por el servidor, verificando su formato y que está presente en una sesión válida y activa.</li><li>En los registros no usar nunca el id de sesión.</li><li>Para evitar ataques de fijación de sesión, cambiar el id de sesión en cada inicio de sesión o en un cambio de privilegios de usuario.</li><li>Al monitorizar y almacenar los ids de sesión activos, asegurarse de que no pueden ser consultados por usuarios no autorizados.</li></ul><div><br /></div></div><h4 style="text-align: left;">Cierre de sesión</h4><div><ul style="text-align: left;"><li>Redirección a la pantalla de login en cada cierre.</li><li>Eliminación de toda la información de la cookie o del token de acceso.</li><li>Eliminación de toda la información de la sesión cliente.</li><li>Registro del cierre (registro de seguridad).</li></ul><div><br /></div></div><h4 style="text-align: left;">Caducidad de la sesión</h4><div><ul style="text-align: left;"><li>Definir un tiempo máximo de vida, para que no esté permanentemente activa.</li><li>Definir un tiempo máximo absoluto de duración para la sesión.</li><li>Toda la información de la sesión debe eliminarse del servidor cuando caduca.</li><li>Registrar (registro de seguridad) cada vez que una sesión expira.</li></ul></div><div>En aplicaciones móviles:</div><div><ul style="text-align: left;"><li>Usar tokens, con el fin de que no sean usados en caso de que el dispositivo se pierda o se sustraiga.</li><li>El token de sesión no puede contener el id del dispositivo.</li><li>La caducidad de la sesión ha de configurarse según la sensibilidad de la app.</li><li>Para utilizar la sesión en varias páginas apoyarse en un repositorio de datos basado en servidor.</li></ul><div><br /></div><h3 style="text-align: left;">Posibles riesgos</h3></div><div><p>A continuación se describen algunos de los posibles riesgos relativos a la gestión de sesiones:</p><p></p><ul></ul></div><div><ul style="text-align: left;"><li><b>Predicción de sesión.</b> El id de sesión podría adivinarse y así evitar la autenticación.</li><li><b>Secuestro de sesión.</b> Aprovecha el mecanismos de control de la sesión web, normalmente mediante un token de sesión.</li><li><b>Fijación de sesión. </b>Mediante la obtención de un id de sesión correcto, permitiría a un usuario autenticarse y secuestrar la sesión.</li><li><b>Suplantación de sesión. </b>Ejemplo: mediante phishing, se engaña a una víctima para entrar en un sitio web malicioso que suplante un sitio legítimo.</li></ul><div><br /></div><h3 style="text-align: left;">Mejores prácticas</h3><div>He aquí algunas recomendaciones para elevar la seguridad en la gestión de sesiones:</div><div><ul style="text-align: left;"><li>El id de sesión nunca debe exponerse bajo tráfico no cifrado.</li><li>Implementar cabeceras seguras, como strict-transport security ó cache-control.</li><li>La sesión ha de expirar pasado un tiempo de inactividad.</li><li>Las páginas que necesiten autenticación han de tener la opción de cierre de sesión.</li><li>El id de sesión nunca debe aparecer en urls, registros o mensajes de error.</li><li>Cada autenticación y re-autenticación ha de destruir la sesión anterior y crear una nueva.</li><li>El id de sesión almacenado en cookies se define mediante los atributos HttpOnly y Secure.</li><li>Para evitar el acceso a otros dominios, configurar el atributo Path de las cookies.</li><li>La aplicación debe realizar seguimiento de las sesiones activas, así como permitir al usuario finalizar éstas de forma selectiva o global desde su cuenta.</li><li>Al cambiar una contraseña, se deben cerrar todas las sesiones activas.</li><li>Asegurarse de que sólo los usuarios autorizados acceden a recursos protegidos: urls, funciones, datos de la aplicación, atributos de usuario y datos de configuración de acceso.</li><li>Registrar (registro de seguridad) todas la actividades (o eventos) de las sesiones, tanto del cliente como del servidor.</li></ul></div> </div><h3>Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><p><br /></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-6651834261185937322023-06-01T09:38:00.004+02:002023-06-01T09:38:43.719+02:00Desarrollo seguro: la autorización<p>La autorización determina qué puede hacer un usuario o un sistema en nuestra aplicación.</p><p>Si la autenticación gestiona el acceso de un usuario, la autorización gestiona los permisos de ese usuario a las diferentes funciones, operaciones y recursos de la aplicación.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4vqIRKu2pdosdq8Fv20d1o5_bD01Q7boi70iIMD0v74i80W0PFSlGbEFieyVeQzSPOxvA_4M0pZtFbTZGjeeaRqUXN0KvUh-v6Y9A10j4cV4e2MQmqCakH3wbYtnz2qjR8tWjzp9AbRZBwCxtERxF52nvYTx3BxSIgep2PB8_lUOXDqPWsA/s1024/authentication-and-authorization.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="587" data-original-width="1024" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4vqIRKu2pdosdq8Fv20d1o5_bD01Q7boi70iIMD0v74i80W0PFSlGbEFieyVeQzSPOxvA_4M0pZtFbTZGjeeaRqUXN0KvUh-v6Y9A10j4cV4e2MQmqCakH3wbYtnz2qjR8tWjzp9AbRZBwCxtERxF52nvYTx3BxSIgep2PB8_lUOXDqPWsA/w640-h366/authentication-and-authorization.jpg" width="640" /></a></div><br /><p style="text-align: center;">Imagen: <a href="https://www.cpomagazine.com/cyber-security/what-is-the-difference-between-authentication-and-authorization/" target="_blank">CPO Magazine</a></p><p><br /></p><h3 style="text-align: left;">Posibles riesgos</h3><p>A continuación se describen algunos de los posibles riesgos relativos a la autorización:</p><p></p><ul style="text-align: left;"><li><b>Acceso no autorizado. </b>Un usuario no autorizado podría acceder a recursos no permitidos.</li><li><b>Escalada vertical de privilegios. </b>Acceso a los recursos de otro usuario con un nivel más alto de permisos.</li><li><b>Escalada horizontal de privilegios.</b> Acceso a los recursos de otro usuario con el mismo nivel de acceso.</li><li><b>Revelación de información sensible.</b> La aplicación podría dar más información de la necesaria, lo cual podría ser usada de forma perniciosa.</li><li><b>Violación de la privacidad. </b>Un atacante accede a datos privados de otros usuarios.</li><li><b>Robo de identidad.</b> Un atacante obtiene la identidad de un usuario y la usa para acceder a la aplicación y realizar acciones con sus permisos.</li><li><b>Robo de datos.</b> Un atacante obtiene datos de forma ilícita.</li><li><b>Disponibilidad del servicio.</b> Un atacante podría interrumpir o dañar el servicio o la ejecución de la aplicación.</li><li><b>Manipulación de datos.</b> Un atacante podría interceptar datos entre cliente y servidor y manipular éstos.</li><li><b>Modificación de registros.</b> Acceso a los registros de la aplicación o del sistema y modificación de éstos alterando su integridad.</li><li><b>Path transversal.</b> Acceso fuera del contexto autorizado en el sistema de archivos del servidor.</li><li><b>Lógica de negocio. </b>Un mal diseño de la aplicación podría permitir a un usuario realizar operaciones no permitidas, debido a que no sigue una lógica de negocio controlada.</li></ul><p></p><p><br /></p><h3 style="text-align: left;">Mejores prácticas</h3><p>He aquí algunas recomendaciones para elevar la seguridad en la autorización:</p><p></p><ul style="text-align: left;"><li>Principio de privilegio mínimo. El usuario solo tiene permitido lo mínimo para realizar su trabajo.</li><li>Roles de aplicación. El usuario solo tiene roles, y los privilegios son tomados de dichos roles.</li><li>El acceso a los registros ha de estar protegido.</li><li>Cada usuario sólo puede acceder a los datos y recursos que le son autorizados.</li><li>Acceso al sistema de archivos esté deshabilitado. Este acceso solo puede ser habilitado de forma excepcional, justificada y expresa.</li><li>Las reglas de control de acceso solamente se han de aplicar en el servidor.</li><li>La gestión de acceso a datos, atributos, información, roles, políticas, etc. de los usuarios no pueden ser manipulados por usuarios no autorizados.</li><li>Uso de un servicio centralizado que proteja el acceso a cada recurso.</li><li>Uso de tokens aleatorios robustos anti-CSRF.</li><li>Registro de todo intento de control de acceso (registro de seguridad).</li><li>Registro específico y detallado (registro de seguridad) de todas las operaciones sobre datos sensibles.</li><li>Uso de captchas en operaciones sensibles.</li></ul><div><br /></div><p></p><h3><br class="Apple-interchange-newline" />Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-32778299585824504032023-05-31T09:45:00.005+02:002023-05-31T13:07:12.953+02:00Desarrollo seguro: la autenticación<p>La autenticación determina el acceso a los recursos de un sistema de información, a través de la verificación de la identidad de un usuario o de un dispositivo. Dada su relevancia, la autenticación debe estar presente en el diseño.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMV6BQfJXoJ0WrPoCjP93rGwALpCY4m7agdm7vi4qZX7TWHOwaTEKZgD8SH5t5tvXz2jOUD1Jx0ljgTsf3TFnt8baBfjojluS2vav7x7weBHIrynzz6WJUxiGsgIsR9hxr1af2Zsn7zgl04kkQoKHpZnEk_SVt9qbMyPy_NubZSzQ75MrJ_w/s2048/Types-of-Authentication.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="908" data-original-width="2048" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMV6BQfJXoJ0WrPoCjP93rGwALpCY4m7agdm7vi4qZX7TWHOwaTEKZgD8SH5t5tvXz2jOUD1Jx0ljgTsf3TFnt8baBfjojluS2vav7x7weBHIrynzz6WJUxiGsgIsR9hxr1af2Zsn7zgl04kkQoKHpZnEk_SVt9qbMyPy_NubZSzQ75MrJ_w/w640-h284/Types-of-Authentication.jpg" width="640" /></a></div><div style="text-align: center;">Fuente: <a href="https://optimalidm.com/resources/blog/types-of-authentication-methods/" target="_blank">OptimalIdm</a></div><p>Existen diferentes tipos de autenticación:</p><p></p><ul style="text-align: left;"><li><b>Autenticación de red:</b> Se utilizan unas credenciales de red (como el usuario+contraseña, un certificado digital, etc.) para acceder al sistema.</li><li><b>Autenticación basada en contraseñas:</b> El usuario debe proporcionar su nombre de usuario y su contraseña.</li><li><b>Autenticación basada en tokens:</b> Un token único permite acceder al sistema. Dicho token puede ser físico o digital.</li><li><b>Autenticación basada en algo poseído:</b> Mediante un soporte que solamente el usuario pueda tener físicamente, como un código QR, una tarjeta de identidad, un smartcard, un USB, un token físico, una tarjeta de coordenadas, etc.</li><li><b>Autenticación de dos o más factores: </b>La identidad es requerida mediante varios métodos de identificación, como por ejemplo la contraseña y un SMS. También se lo conoce como 2FA (2 Factor Authentication) y MFA (Multi-Factor Authentication).</li><li><b>Autenticación biométrica: </b>La identidad se obtiene a partir de características físicas, tales como la huella dactilar, el iris del ojo, la voz, el reconocimiento facial, etc.</li><li><b>Autenticación basada en comportamientos:</b> Uso de patrones de dibujo sobre una pantalla táctil, movimientos de alguna parte del cuerpo, etc.</li><li><b>Autenticación basada en ubicación:</b> Por ejemplo, mediante una IP específica.</li></ul><div><br /></div><h3 style="text-align: left;">Posibles riesgos</h3><div>A continuación se exponen algunas de las amenazas y riesgos posibles relativos a la autenticación:</div><div><ul style="text-align: left;"><li><b>Ataques de diccionario. </b>Pruebas de contraseñas mediante combinaciones comunes y predefinidas de letras y números.</li><li><b>Ataques de fuerza bruta. </b>Pruebas de contraseñas generadas mediante combinaciones de caracteres.</li><li><b>Ataques Man in the Middle (MitM). </b>Interviniendo las comunicaciones se pueden obtener las credenciales de acceso (contraseñas, tokens, tickets de acceso).</li><li><b>Ataques de replay. </b>Si se obtiene un ticket de acceso, éste puede ser reutilizado.</li><li><b>Vulnerabilidades de software. </b>Aplicaciones y sistemas operativos con vulnerabilidades.</li><li><b>Enumeración de usuarios. </b>Es posible encontrar usuarios registrados probando identidades y analizando las respuestas del servidor (mensajes, tiempos de respuesta, etc).</li><li><b>Suplantación de identidad.</b> Se suplanta al servidor de autenticación para engañar al usuario y obtener así sus credenciales.</li><li><b>Robo de identidad. </b>Se obtiene la identidad de un usuario, por ejemplo, robando una cookie.</li></ul><br /></div><h3 style="text-align: left;">Mejores prácticas</h3><div>He aquí algunas recomendaciones para tener un alto nivel de seguridad en la autenticación:</div><div><ul style="text-align: left;"><li>Las contraseñas han de guardarse en un formato no legible, a ser posible, que la operación de obtener la contraseña en plano sea irreversible, como el uso de hashes fuertes.</li><li>Proporcionar opciones y enlaces para la desconexión del usuario en la aplicación.</li><li>Automatizar la desconexión pasado un tiempo de inactividad.</li><li>No exponer las credenciales en las urls.</li><li>Los formularios de petición de credenciales deben usar métodos POST.</li><li>Uso de la autenticación multi-factor en aplicaciones sensibles (múltiples capas de seguridad).</li><li>Uso del doble factor de autenticación en operaciones críticas, como el cambio de contraseña o el acceso a recursos sensibles.</li><li>Implementar el bloqueo de una cuenta tras varios intentos de autenticación fallidos.</li><li>Implementar CAPTCHA para limitar los ataques de fuerza bruta.</li><li>Usar errores genéricos para evitar la enumeración de usuarios. Por ejemplo: "El usuario y/o la contraseña son incorrectos".</li><li>Implementar tiempos de espera aleatorios en respuestas a intentos fallidos de autenticación, con lo que se evita la enumeración de usuarios.</li><li>En la funcionalidad de recuperación de contraseñas, evitar la enumeración de usuarios.</li><li>El campo de contraseña debe tener desactivado la opción de "autocompletar".</li><li>Utilizar una buena política de contraseñas:</li><ul><li>Uso de caracteres alfabéticos, números y caracteres especiales, con distinción de mayúsculas y minúsculas).</li><li>Longitud amplia (por ejemplo, 16 caracteres).</li><li>Una contraseña distinta por cada sitio.</li><li>Establecimiento de una caducidad de contraseña (por ejemplo cada mes). Una vez transcurrido ese tiempo será necesario cambiarla.</li></ul><li>No almacenar la cookie de autenticación en el navegador del cliente.</li><li>Cada vez que el usuario se conecte con éxito, la sesión debe ser diferente.</li><li>Registrar todas las operaciones que afecten a datos sensibles.</li></ul></div><div><br /></div><h3 style="text-align: left;">Tipos de autenticación más comunes</h3><h4 style="text-align: left;">Autenticación basada en claves</h4><div>Una autenticación basada en claves (por ejemplo, mediante nombre de usuario y contraseña), es bastante débil en términos de seguridad, se utilice en texto claro, en base64, cifrado o mediante formularios. Sus principales riesgos son:</div><div><ul style="text-align: left;"><li><b>Ingeniería social. </b></li><li><b>Ataques Man in the Middle (MitM). </b>Un usuario con acceso a la red podría interceptar la información de autenticación.</li><li><b>Reutilización de claves.</b> Si se utiliza la misma clave en varios sitios, si se intercepta en uno, el resto queda comprometido.</li><li><b>Ataque de fuerza bruta o diccionario. </b></li><li><b>Autenticación débil. </b>No permite la implementación de medidas de autenticación más seguras, como el MFA o los certificados digitales.</li></ul></div><div><br /></div><div>Las mejores recomendaciones son las siguientes:</div><div><ul style="text-align: left;"><li><b>Buena política de contraseñas</b></li><li><b>Uso de autenticación multifactor. </b>Por ejemplo, añadir a la contraseña una verificación de código que se envíe por email, SMS o por aplicaciones externas de autenticación, tales como Google Authenticator o oneLogin Protect.</li></ul><div><br /></div><h4 style="text-align: left;">Autenticación implícita</h4></div><div>En este caso, la autenticación no se basa en credenciales proporcionadas por el usuario, si no que la identificación se obtiene automáticamente mediante la dirección IP del usuario, la información de una cookie, un token, etc. Aunque puede ser seguro, existen ciertos riesgos:</div><div><ul style="text-align: left;"><li><b>Acceso no autorizado.</b> Es posible falsificar la ip de un usuario para obtener el acceso. También es posible acceder a la cookie de un usuario y utilizarla para obtener el acceso. </li><li><b>Ataque de fuerza bruta o diccionario. </b>Es vulnerable a este ataque si no usa algoritmos de cifrado robustos.<b> </b></li><li><b>Autenticación débil.</b> No permite la implementación de medidas de autenticación más seguras, como el MFA o los certificados digitales.</li></ul></div><div>La mejor recomendación es utilizar una contraseña basada en un hash criptográfico lo bastante largo y robusto que haga inútil un ataque de fuerza bruta.</div><div><br /></div><div><br /></div><h4 style="text-align: left;">Autenticación de cliente HTTP</h4><div>Este tipo de autenticación utiliza un par de claves criptográficas para verificar la identidad del usuario o del dispositivo: una clave pública (usada para cifrar la información) y una clave privada (usada para descrifrar la información). Este sistema es bastante seguro y se utiliza para comunicaciones HTTPS, pero su implementación es más compleja y costosa, además de existir otro tipo de riesgos:</div><div><ul style="text-align: left;"><li><b>Acceso no autorizado.</b> Si se obtiene la clave privada del usuario, podemos utilizarla para acceder a los recursos de ese usuario. Por otra parte, si se emite un certificado falso con una clave pública falsa, es posible acceder a recursos protegidos de forma no autorizada.</li><li><b>Ataque Man in the Middle (MitM). </b>Es posible interceptar un certificado en tránsito y usarlo para acceder de forma no autorizada.</li><li><b>Manipulación de un certificado SSL.</b> En el caso de implementar certificados auto-firmados o certificados no verificados por una CA (Certification Authority).</li></ul></div><div><br /></div><div><h3><br class="Apple-interchange-newline" />Referencias</h3><div><ul><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div></div><p></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-62597158618705596372023-05-30T16:05:00.002+02:002023-05-31T13:06:12.312+02:00Desarrollo seguro: todo empieza en la arquitectura<p>La arquitectura constituye los cimientos sobre los cuales se erigirán nuestras aplicaciones. </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEiqalHfvWtp9kuSsUdtC1l6hTs-AAsKRBb99gTVmV4s2FbYnkLt3v9yGT1YtE4-AFvJRXzfCXgt7utiBlIQciwcnl3apE7dOmj2I7mahzvDLSCdEDhRbjBhsy2J2RT1fezY3lysYQF7wHkDinmKnES-lgdSqbyiUbX2fj7aRr17VWqbci5Q/s1000/isoc_security.jpg" style="margin-left: 1em; margin-right: 1em;"><img alt="Desarrollo seguro: todo comienza en la arquitectura" border="0" data-original-height="700" data-original-width="1000" height="448" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEiqalHfvWtp9kuSsUdtC1l6hTs-AAsKRBb99gTVmV4s2FbYnkLt3v9yGT1YtE4-AFvJRXzfCXgt7utiBlIQciwcnl3apE7dOmj2I7mahzvDLSCdEDhRbjBhsy2J2RT1fezY3lysYQF7wHkDinmKnES-lgdSqbyiUbX2fj7aRr17VWqbci5Q/w640-h448/isoc_security.jpg" title="Desarrollo seguro: todo comienza en la arquitectura" width="640" /></a></div><p style="text-align: center;">Fuente: <a href="https://open-stand.org/isoc-introduces-new-concept-on-collaborative-security/" target="_blank">open stand</a></p><h3 style="text-align: left;">Posibles riesgos</h3><p>El desarrollo seguro comienza con el diseño y la definición de nuestra arquitectura, teniendo en mente las posibles amenazas que pudieran poner en riesgo nuestro sistema, especialmente aquellas derivadas por el uso de componentes que:</p><ul style="text-align: left;"><li>no estén identificados.</li><li>sean antiguos o incompatibles, que estén obsoletos o hayan dejado de ser soportados.</li><li>posean vulnerabilidades conocidas.</li><li>tengan puertos abiertos no indispensables.</li></ul><div><br /></div><h3 style="text-align: left;">Mejores prácticas</h3><div>A continuación se detallan las mejores prácticas a la hora de diseñar, definir y mantener una arquitectura segura:</div><div><ul style="text-align: left;"><li>Inventario que identifique cada componente de la arquitectura. Todo componente debe estar identificado, o de lo contrario se incurrirá en riesgos de seguridad.</li><li>Revisión del bastionado de componentes:</li><ul><li>Identificación de dependencias internas:</li><ul><li>Módulos.</li><li>Librerías.</li><li>Frameworks.</li><li>Plugins o complementos.</li><li>Servicios.</li><li>Otras.</li></ul><li>Estado de actualización.</li><li>Configuraciones:</li><ul><li>Puertos activados (solo los indispensables).</li><li>Usuarios y contraseñas personalizados (no por defecto).</li><li>Modo de depuración desactivado.</li><li>Otras configuraciones de seguridad (ajustadas a una mayor seguridad).</li></ul></ul><li>Identificación de vulnerabilidades y sus parches de seguridad. En caso de no existir parche:</li><ul><li>analizar el riesgo y su impacto</li><li>proponer y adoptar:</li><ul><li>un plan de vigilancia.</li><li>un plan de contingencias.</li></ul><li>realizar un estudio de viabilidad de componentes alternativos.</li></ul><li>Asegurar la seguridad perimetral lógica mediante la segmentación de red, firewalls, dispositivos IDS, etc.</li><li>Asegurar la protección de datos mediante:</li><ul><li>autorización entre entornos.</li><li>copias de seguridad.</li></ul><li>Proporcionar un entorno virtual como zona de trabajo, a ser posible, por lenguaje de programación.</li><li>Mantener las actualizaciones más recientes de:</li><ul><li>lenguajes de programación</li><li>paquetes instalados</li><li>frameworks y librerías</li><li>herramientas de análisis y seguridad de los IDEs</li></ul><li>En caso de trabajar con DevSecOps, dotar de herramientas de análisis de seguridad a lo largo del ciclo de vida del software, antes del despliegue en cada entorno.</li></ul></div><div><br /></div><h3 style="text-align: left;">Referencias</h3><div><ul style="text-align: left;"><li><a href="https://www.ccn-cert.cni.es/seguridad-al-dia/novedades-ccn-cert/12252-nuevo-informe-de-buenas-practicas-bp-28-recomendaciones-sobre-desarrollo-seguro.html" target="_blank">CCN-CERT BP/28: Recomendaciones sobre desarrollo seguro</a></li></ul></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-16970693857967975292022-10-27T07:55:00.234+02:002022-10-27T11:51:59.739+02:00Entender la Computación cuántica<p> <a href="https://www.privatewallmag.com/wp-content/uploads/Ppal-cuantica.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="400" data-original-width="800" height="320" src="https://www.privatewallmag.com/wp-content/uploads/Ppal-cuantica.jpg" width="640" /></a></p><div class="separator" style="clear: both; text-align: center;"><i>Fuente: <a href="https://www.privatewallmag.com/wp-content/uploads/Ppal-cuantica.jpg" target="_blank">privatewallmag</a></i></div><p>En los últimos años, el interés por la computación cuántica ha ido aumentando gracias a los avances que se están consiguiendo y a las increíbles aplicaciones que promete satisfacer. </p><p>En este artículo vamos a realizar una breve introducción al fascinante mundo de la computación cuántica. Para ello, aprenderemos qué es la computación cuántica, de dónde viene, qué diferencias tiene con respecto a la computación convencional y hacia donde se dirige.</p><p><br /></p><h2 style="text-align: left;">Un poco de historia</h2><p>La computación cuántica no es un concepto nuevo, si no que arranca en la década de 1970, cuando el físico estadounidense <b><a href="https://en.wikipedia.org/wiki/Paul_Benioff" target="_blank">Paul Benioff</a></b> comenzó su investigación sobre la <b><a href="https://es.wikipedia.org/wiki/Informaci%C3%B3n_y_comunicaci%C3%B3n_cu%C3%A1ntica" target="_blank">información cuántica</a></b> y la viabilidad teórica de la computación cuántica. En 1980 describió una máquina de Turing trabajando con algunos de los principios de la mecánica cuántica. A este planteamiento le seguiría la teoría de la información cuántica en ordenadores y robots, aplicando los fundamentos de la física, las matemáticas y la lógica. Su mayor logro fue demostrar que era posible la creación de un modelo reversible de computación cuántica.</p><p>En 1982, el Nobel de física estadounidense <b><a href="https://es.wikipedia.org/wiki/Richard_Feynman" target="_blank">Richard Feynman</a></b>, propuso en una conferencia del <a href="https://web.mit.edu/" target="_blank">MIT</a> sobre Física de la Computación, el uso de fenómenos cuánticos para realizar cálculos complejos mediante un ordenador cuántico.</p><p>En 1985, el físico británico (nacido en Israel) <b><a href="https://es.wikipedia.org/wiki/David_Deutsch" target="_blank">David Deutsch</a></b>, de la <a href="https://www.ox.ac.uk/" target="_blank">Universidad de Oxford</a>, y miembro de la <a href="https://royalsociety.org/" target="_blank">Royal Society</a>, describió el primer ordenador cuántico universal, el cual aplicaría el principio de <a href="https://es.wikipedia.org/wiki/Tesis_de_Church-Turing" target="_blank">Church-Turing</a> ampliado en el que dicho ordenador cuántico podría simular cualquier otro ordenador cuántico. Tras ello, fue el primero en formular un algoritmo cuántico y en exponer la idea de que el ordenador cuántico podría ejecutar este tipo de algoritmos. </p><p>En 1995, el matemático estadounidense <b><a href="https://en.wikipedia.org/wiki/Peter_Shor" target="_blank">Peter Shor</a></b>, diseñó un <a href="https://en.wikipedia.org/wiki/Shor%27s_algorithm" target="_blank">algoritmo cuántico</a> que demostró que un cálculo tan complejo como el de los factores primos es muchísimo más rápido ejecutándose en un ordenador cuántico. Poco después planteó un sistema de de corrección de errores en el cálculo cuántico. Gracias a este algoritmo, se puede reventar los sistemas actuales de criptografía, con lo que descubrió a todo el mundo el increíble potencial de la computación cuántica. </p><p>En 1998, el <a href="https://web.mit.edu/" target="_blank">MIT</a> consiguió el primer medio para el análisis de información en un <i>qubit</i>, al difundir el primer <i>qubit</i> usando una solución de aminoácidos. Al mismo tiempo, la <a href="https://www.berkeley.edu/" target="_blank">Universidad de Berkeley</a> presentó el primer computador de 2 <i>qubits</i>. </p><p>En 2001, se consigue ejecutar el <a href="https://en.wikipedia.org/wiki/Shor%27s_algorithm" target="_blank">algoritmo de Shor</a> en un ordenador cuántico de 7 <i>qubits</i> del <a href="https://lanl.gov/" target="_blank">Laboratorio Nacional de Los Álamos</a>, gracias a <a href="https://www.ibm.com/" target="_blank">IBM</a> y a la <a href="https://www.stanford.edu/" target="_blank">Universidad de Stanford</a>.</p><p>En 2007, investigadores de la <a href="https://www.yale.edu/" target="_blank">Universidad de Yale</a> y del <a href="https://www.nist.gov/" target="_blank">NIST</a> consiguen crear el primer bus cuántico, uniendo componentes cuánticos mediante superconductores. Este bus puede usarse como memoria cuántica para almacenamiento temporal.</p><p>En 2008, la <a href="https://www.nsf.gov/" target="_blank">NSF</a> consigue por vez primera almacenar un <i>qubit</i> en un átomo de fósforo, aumentando el tiempo de persistencia de la información (1,75 segundos).</p><p>En 2009, investigadores de la <a href="https://www.yale.edu/" target="_blank">Universidad de Yale</a> crean el primer procesador cuántido de estado sólido, muy similar a un microprocesador clásico.</p><p>En 2012, <a href="https://www.ibm.com/" target="_blank">IBM</a> creó un chip cuántico estable que podría llegar a empresas y hogares en una década.</p><p>En 2017, <a href="https://www.ibm.com/" target="_blank">IBM</a> presentó un procesador cuántico comercial de 17 <i>qubits</i>. </p><p>En 2019, <a href="https://www.ibm.com/" target="_blank">IBM</a> presentó el primer ordenador cuántico comercial, el <a href="https://es.wikipedia.org/wiki/IBM_Q_System_One" target="_blank">IBM Q System One</a>. También presentó el ordenador cuántico más potente del mundo, compuesto de <i>53 qubits</i>. Google demostró la <a href="https://es.wikipedia.org/wiki/Supremac%C3%ADa_cu%C3%A1ntica" target="_blank">supremacía cuántica</a>, es decir, la demostración de que un ordenador cuántico podría desempeñar una tarea extremadamente compleja en unos pocos segundos, mientras que a un superordenador convencional le costaría miles de años. Por cierto, en el diseño de esta demostración participó el informático y matemático español <a href="https://es.wikipedia.org/wiki/Sergio_Boixo" target="_blank">Sergio Boixo</a>.</p><p>En 2021, IBM consigue el primer procesador de 127 qubits.</p><p>En 2022, investigadores de la <a href="https://www.tudelft.nl/en/" target="_blank">Universidad Tecnológica de Delft </a>(Países Bajos) lograron desarrollar el primer procesador de silicio de 6 <i>qubits</i>. El <a href="https://www.ims.ac.jp/en/" target="_blank">Instituto Japonés de Ciencia Molecular</a> consiguió utilizar una doble compuerta cuántica, lo que permitió el intercambio de energía e información entre dos átomos en tan sólo 6,5 nanosegundos, usando un láser molecular. Un equipo de la <a href="https://www.southwales.ac.uk/" target="_blank">Universidad de Gales del Sur</a> ha diseñado un procesador cuántico a escala atómica que simula el comportamiento de una molécula, tal y como planteó el físico Richard Feynman hace casi 60 años. Científicos de <a href="https://college.harvard.edu/" target="_blank">Harvard</a> y del <a href="https://www.mit.edu/" target="_blank">MIT</a> desarrollan un ordenador cuántico de 256 qubits, dentro del proyecto <a href="https://www.quera.com/" target="_blank">QuEra Computing</a>.</p><p>En este repaso histórico hemos sintetizado unos pocos de los hitos más relevantes, pero ha habido muchos e importantes acontecimientos en la reciente historia de la computación cuántica. </p><p> </p><h2 style="text-align: left;">¿Qué es la computación cuántica?</h2><p>La computación cuántica (también conocida como informática cuántica) aborda la computación desde un paradigma diferente a la que conocemos actualmente, abriendo una nueva puerta a posibilidades que hasta hoy eran inalcanzables o muy difíciles de alcanzar.</p><p><br /></p><h2 style="text-align: left;">Diferencias entre la computación cuántica y la computación clásica</h2><p>La primera diferencia entre la computación cuántica y la computación clásica está basada en la forma de la unidad básica de información. </p><p>La computación básica trata la información en secuencias de unos y ceros (bits), que representan puertas lógicas por las que pasa electricidad (1) o no (0) en un momento determinado. La secuencia combinada de bits conforma la generación de valores numéricos representados de forma binaria. Así, los chips y microprocesadores basan su capacidad de almacenar y realizar cálculos en este formato: 4 bits (nibbles), 8 bits, 16 bits, 32 bits, 64 bits, etc.</p><p>La computación cuántica trata la información mediante <b>qubits</b> (<i><b>qu</b>antum <b>bits</b></i> ó <i>bits cuánticos</i>), los cuales pueden valer, 0, 1 o ambos valores a la vez (lo que se conoce como <b>superposición cuántica</b>). </p><p>Estos valores cuánticos se pueden representar en una <a href="https://es.wikipedia.org/wiki/Esfera_de_Bloch" target="_blank">esfera de Bloch</a>, basada en la mecánica cuántica:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Bloch_sphere.svg/250px-Bloch_sphere.svg.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="266" data-original-width="250" height="266" src="https://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Bloch_sphere.svg/250px-Bloch_sphere.svg.png" width="250" /></a></div><div class="separator" style="clear: both; text-align: center;"><i>Fuente: <a href="https://es.wikipedia.org/wiki/Esfera_de_Bloch" target="_blank">Wikimedia</a></i></div><div><br /></div>Esta característica ofrece nuevas posibilidades lógicas que requieren de nuevos algoritmos para tratar problemas complejos que son inalcanzables para la computación clásica. <div><br /></div><div>Entre algunas de las soluciones que ofrece la computación cuántica se encuentra la posibilidad de generar números aleatorios reales (lo cual es esencial para generar hashes para la blockchain), o resolver en unos segundos cálculos complejos que a un ordenador clásico le llevaría años realizar. Investigadores de Google confirmaron que un cálculo que le hubiera llevado realizar 10.000 (diez mil) años a un superordenador actual, en su ordenador cuántico se realizó en apenas 200 segundos.<br /><div><br /></div><div>Entre muchas de las virtudes de la computación cuántica se encuentra la posibilidad de resolver en apenas unos segundos problemas complejos que le llevaría a la computación clásica decenas o cientos de años, como puede ser el descifrado de información encriptada. <div><br /></div><div>Para entender un poco la magnitud de procesamiento de la computación cuántica, imaginemos un ordenador cuántico de apenas 30 <i>qubits</i>, el cual podría ejecutar 10 billones (10 millones de millones) de FLOPS (operaciones en coma flotante por segundo). Para hacernos una idea, comparado con las videoconsolas más potentes de la actualidad, una XBox One Series X trabaja con 12 TFLOPS, la PlayStation 5 tiene una capacidad de 10,28 FLOPS. Es decir, que este ordenador cuántico tendría la potencia de casi 1 billón de PlayStations 5.</div><div><br /></div><div><br /></div><div><h2>Diferencias entre ordenadores cuánticos y ordenadores clásicos</h2><div>La arquitectura de un ordenador cuántico es más sencilla, ya que solo se limita a un conjunto de <i>qubits</i> para funcionar, por lo que no requiere de memoria ni de procesadores.</div><div><br /></div><div>Sin embargo, los ordenadores cuánticos son muy sensibles ante cambios ambientales. Por ello, requieren que la presión atmosférica sea casi inexistente, que estén aislados del campo magnético terrestre y que la temperatura ambiente sea lo más próxima al cero absoluto (-273º C). Estos ordenadores están sellados y manejados desde ordenadores normales.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi1.wp.com%2Fclipset.com%2Fwp-content%2Fuploads%2F2018%2F01%2Fibm-cuantico4.jpg%3Fresize%3D768%252C1024%26ssl%3D1&f=1&nofb=1&ipt=fad15d78a88f68096d092c6432ea9234ab4891cf9190a35ae224330e4acb3191&ipo=images" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="600" height="800" src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi1.wp.com%2Fclipset.com%2Fwp-content%2Fuploads%2F2018%2F01%2Fibm-cuantico4.jpg%3Fresize%3D768%252C1024%26ssl%3D1&f=1&nofb=1&ipt=fad15d78a88f68096d092c6432ea9234ab4891cf9190a35ae224330e4acb3191&ipo=images" width="600" /></a></div><div class="separator" style="clear: both; text-align: center;"><i>Fuente: <a href="http://clipset.com">clipset.com</a></i></div><div><br /></div>Estas condiciones son extremas, pues si hay interacción con partículas externas se producirían fallos de medición o se borrarían las superposiciones de estados. Los átomos no deben moverse ni colisionar entre sí. Por este motivo, estos ordenadores están funcionando durante intervalos muy cortos de tiempo.<div><br /></div></div><div><h2>¿Sustituirá la computación cuántica a la computación clásica?</h2><div>La computación clásica ha revolucionado la forma en que resolvemos problemas complejos en todos los ámbitos: empresarial, personal, educacional, investigación, comunicaciones, etc. Y seguirá dándonos muchas sorpresas y grandes satisfacciones por mucho (muchísimo) tiempo.</div><div><br /></div><div>La computación cuántica se erige para resolver otro tipo de problemas, concretamente aquellos que la computación clásica no es capaz de afrontar o que sería inviable de resolver. El enfoque de la computación cuántica es explorar nuevas posibilidades de resolver problemas complejos.</div><div><br /></div><div>Por tanto, la computación cuántica complementará a la computación convencional y viceversa. Ante problemas sencillos y poco complejos, la computación clásica seguirá siendo más eficiente y viable que la computación cuántica. Se abre un mundo de oportunidades y posibilidades en que lo mejor de ambas se complementen para afrontar nuevos e interesantes retos.</div></div><div><br /></div><h2 style="text-align: left;">Conceptos básicos de la computación cuántica</h2><div>Durante los últimos años se están logrando muchos e importantes avances en la computación cuántica. Empresas, universidades, institutos y laboratorios de tecnología como el <b>MIT, Universidad de Berkeley, Universidad de Stanford, Universidad de Yale, IBM</b>, <b>Microsoft</b>, <b>Rigetti</b>, <b>D-Wave Systems</b>, <b>Xanadu</b> o <b>QCI</b> están compitiendo en investigación y desarrollo, proponiendo nuevos modelos de hardware y software cada vez más sofisticados y eficientes.</div><div><br /></div><div>No obstante, vamos a hacer una breve revisión de algunos conceptos básicos en los que está basada la computación cuántica.</div><div><br /></div><div><br /></div><h3 style="text-align: left;">Superposición cuántica y la paradoja del gato de Schrödinger</h3><div>Quizá sea está la característica básica más importante y conocida de la computación cuántica. <b>El principio de superposición es una regla de la física cuántica en la que pueden existir, al mismo tiempo, dos estados.</b> </div><div><br /></div><div><b>La paradoja del <a href="https://es.wikipedia.org/wiki/Gato_de_Schr%C3%B6dinger" target="_blank">gato de Schrödinger</a></b> es una representación de dicho principio, propuesto por el físico y premio Nobel austríaco <b><a href="https://es.wikipedia.org/wiki/Erwin_Schr%C3%B6dinger" target="_blank">Erwin Schrödinger</a></b>. Esta paradoja explica la superposición a través de un experimento mental en la que tenemos un gato dentro de una caja opaca, la cual, en su interior, posee un mecanismo que une un detector de electrones a un martillo. Justo debajo del martillo se encuentra un frasco de cristal con un letal veneno. Este mecanismo se activaría si el detector detectase un electrón, con lo que el martillo se desplomaría y rompería el frasco, con el fatal desenlace para el pobre gato.</div><div><br /></div><div>Si abrimos la caja puede que encontremos al gato muerto, o puede que el electrón tome otra dirección y el detector no lo perciba y el gato se salve.</div><div><br /></div><div>Al final del experimento hay un 50% de probabilidades sobre el estado del gato: vivo o muerto.</div><div><br /></div><div>Pero la paradoja de la mecánica cuántica estriba en que un electrón es, al mismo tiempo, onda y partícula. Es decir, que toma caminos distintos a la vez, pero no se excluyen, si no que se superponen, como las ondas de agua en un lago. Por tanto, el electrón tomaría el camino del detector y el camino contrario al mismo tiempo. Ambas probabilidades se cumplen simultáneamente, por lo que el gato acabaría vivo y muerto a la vez. Solamente, al abrir la caja, veremos si el gato está vivo o muerto.</div><div><br /></div><div><br /></div><h3 style="text-align: left;">Entrelazamiento</h3><div>Un conjunto de 2 <i>qubits</i> puede representar, a la vez, la siguiente superposición de valores: 00, 01, 10 y 11. A medida que se incrementa el número de <i>qubits</i>, también se incrementa exponencialmente la capacidad de superposición y aumenta la representación de información. A esto se denomina <b>entrelazamiento</b>, pues los <i>qubits</i> se entrelazan en una correlación cuántica, pudiendo realizar operaciones en paralelo o simultáneamente (lo que se conoce como <b>paralelismo cuántico</b>).</div><div><br /></div><div>En la física, el <a href="https://es.wikipedia.org/wiki/Entrelazamiento_cu%C3%A1ntico" target="_blank">entrelazamiento cuántico</a> ocurre cuando dos partículas están tan conectadas que lo que le ocurre a una le afecta a la otra, sin importar su distancia. Esta es la clave del teletransporte, y fue una propiedad predicha por <a href="https://es.wikipedia.org/wiki/Albert_Einstein" target="_blank">Einstein</a>, <a href="https://es.wikipedia.org/wiki/Bor%C3%ADs_Podolski" target="_blank">Podolsky</a> y <a href="https://es.wikipedia.org/wiki/Nathan_Rosen" target="_blank">Rosen</a> (<a href="https://es.wikipedia.org/wiki/Paradoja_EPR" target="_blank">paradoja EPR</a>).</div><div><br /></div><div><br /></div><h3 style="text-align: left;">La decoherencia cuántica</h3><div><div>El principio de superposición del <i>qubit</i> nos lleva a la posibilidad de obtener simultáneamente múltiples resultados, como consecuencia de la multiplicidad de estados de los <i>qubits</i> implicados en una operación lógica cuántica. Esto se vuelve exponencial a medida que realicemos operaciones con más qubits. </div><div><br /></div><div>La decoherencia cuántica se produce en el momento en que las condiciones requeridas para mantener un estado cuántico entrelazado desaparecen. Básicamente, el sistema deja de comportarse según las reglas de la mecánica cuántica y comienza a comportarse acorde a las reglas de la física convencional. Esto provoca que el estado de los <i>qubits</i> se rompa con facilidad, afectando a la superposición y al entrelazamiento, desapareciendo los efectos cuánticos.</div><div><br /></div><div>Los estados cuánticos se mantienen durante un período de tiempo limitado, durante el cual hay que realizar las operaciones con los <i>qubits</i>. Esto se vuelve más difícil a medida que se añaden más <i>qubits</i>. Pasado este tiempo, la decoherencia de un sistema cuántico producirá errores, ya que los algoritmos no retornarán los resultados esperados. Por este motivo, los ordenadores cuánticos tienen unas características muy especiales para funcionar (tales como su temperatura de trabajo a -273 grados), con el fin de evitar perturbaciones y ruido.</div></div><div><br /></div><h3 style="text-align: left;">Algoritmo cuántico</h3><div>Un algoritmo cuántico difiere bastante de un algoritmo convencional. </div><div><br /></div><div>Un algoritmo cuántico permite la ejecución de una serie de puertas cuánticas sobre entidades (<i>qubits</i> o registros cuánticos), a los que les sigue un punto de medición. </div><div><br /></div><div>Los cómputos se realizan utilizando <i>qubits</i> que operan entre sí a través de puertas cuánticas, manipulando estados. Cuando se enlazan puertas cuánticas es posible calcular funciones complejas.</div><div><br /></div><div>El algoritmo cuántico se suele representar en un circuito formado por puertas cuánticas, en donde se transforma el estado de un conjunto de <i>qubits</i> desde una superposición inicial hasta una superposición final. </div><div class="separator" style="clear: both; text-align: center;"><a href="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fmiro.medium.com%2Fmax%2F810%2F0*6qh01lw6kdaC73KF.png&f=1&nofb=1&ipt=18099f5d54d1a690e9b30a2bd5468595022d322e0e44ab65ea79effa048c8324&ipo=images" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="312" data-original-width="800" height="250" src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fmiro.medium.com%2Fmax%2F810%2F0*6qh01lw6kdaC73KF.png&f=1&nofb=1&ipt=18099f5d54d1a690e9b30a2bd5468595022d322e0e44ab65ea79effa048c8324&ipo=images" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><i>Ejemplo de circuito con un algoritmo cuántico. Fuente: <a href="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fmiro.medium.com%2Fmax%2F810%2F0*6qh01lw6kdaC73KF.png&f=1&nofb=1&ipt=18099f5d54d1a690e9b30a2bd5468595022d322e0e44ab65ea79effa048c8324&ipo=images" target="_blank">Towards Data Science</a></i></div><div><br /></div><div><br /></div><div>Ya se han desarrollado algunos algoritmos importantes, entre los que cabe destacar:</div><div><ul style="text-align: left;"><li><b><a href="https://es.wikipedia.org/wiki/Algoritmo_de_Deutsch-Jozsa" target="_blank">Algoritmo Deutsch-Jozsa (1992)</a></b>: Desarrollado por <a href="https://es.wikipedia.org/wiki/David_Deutsch" target="_blank">David Deutsch</a> y Richard Jozsa. Determina si una función de tipo caja negra es constante o balanceada. </li><li><b><a href="https://es.wikipedia.org/wiki/Algoritmo_de_Shor" target="_blank">Algoritmo de Shor (1995)</a>:</b> Desarrollado por <a href="https://es.wikipedia.org/wiki/Peter_Shor" target="_blank">Peter Shor</a>. Descompone un número N en factores en tiempo y espacio. Se ha convertido en un referente debido a su papel en el desencriptado de datos.</li><li><b><a href="https://es.wikipedia.org/wiki/Algoritmo_de_Grover" target="_blank">Algoritmo de Grover (1996)</a>: </b>Desarrollado por Lov K. Grover. Demuestra que una búsqueda en una base de datos sin ordenación es mucho más rápida usando computación cuántica. </li></ul><div>Existe una multitud de algoritmos cuánticos. Pueden consultarse parte de ellos en el <a href="https://quantumalgorithmzoo.org/" target="_blank">Zoo de Algoritmos Cuánticos</a>.</div><div><br /></div><h2 style="text-align: left;">Campos de aplicación de la computación cuántica</h2><div>La computación cuántica genera grandes expectativas para dar solución a importantes retos y problemas que hoy en día, con la computación y los ordenadores convencionales, serían impensables. Por ejemplo:</div><div><ul style="text-align: left;"><li><b>Ciberseguridad. </b>Al principio comentamos que en pocos segundos se podría desencriptar cualquier dato encriptado con los potentes algoritmos actuales. Pero también da pie a utilizar nuevos algoritmos de encriptación más robustos, como QKD (Quantum Key Distribution). Esto llevará a redefinir la seguridad en internet y el uso de criptografía cuántica.</li><li><b>Medicina y Salud.</b> Ayudará y mejorará la investigación del ADN, y permitirá desarrollar nuevos medicamentos y tratamientos personalizados. Creación y simulación de estructuras moleculares, como las proteínas.</li><li><b>Finanzas. </b>Optimización de los sistemas de detección del fraude, gestión de riesgos, simulaciones de previsiones de "crashes" financieros e inversiones seguras, recomendaciones de inversiones.</li><li><b>Transporte. </b>Mejora de la planificación del tráfico, optimización de rutas, eficiencia de asignación de aviones en aeropuertos o la eficiencia de los aviones.</li><li><b>Industria 4.0.</b> Resolución de problemas logísticos en las cadenas de suministro. Creación de materiales verdes alternativos. Desarrollo de superconductores eficientes. </li><li><b>Química.</b> Investigación de las reacciones químicas (aplicado, por ejemplo, a las baterías). Investigación de estructuras moleculares y simulación de sus reacciones.</li><li><b>Ciencia.</b> Testeo de teorías científicas aún sin validar. Búsqueda de eventos de Higgs y el origen del universo. Investigación en la ciencia cuántica.</li><li><b>Meteorología.</b> Análisis y predicción del clima.</li><li><b>Inteligencia Artificial.</b> Se está avanzando en el campo de la inteligencia artificial cuántica. IBM está produciendo y mejorando un algoritmo de clasificación de aprendizaje automático cuántico. También se está trabajando en el comportamiento hiperrealista de personajes autónomos (no controlados) en videojuegos. También se está avanzando en la inteligencia artificial de vehículos autónomos.</li><li><b>Comunicaciones.</b> Se está trabajando en un Internet cuántico, más rápido, seguro y libre de espionaje. Esto podría ser clave en nuevos servicios, tales como el metaverso. </li><li><b>Blockchain.</b> La computación cuántica será clave para la web3, basada en tecnología Blockchain. Algunos de los factores clave de Blockchain son la generación de hashes, la encriptación y la firma de de las cadenas de bloques, asegurando la inmutabilidad de los mismos. La criptografía postcuántica resolvería este problema y aseguraría la inmutabilidad y la seguridad de la blockchain. </li></ul></div><div><br /></div><h2 style="text-align: left;">Programación en computación cuántica</h2><div>¿Podemos iniciarnos en el apasionante mundo de la computación cuántica sin tener un ordenador cuántico? La respuesta es SI.</div><div><br /></div><div>No es necesario ser miembro de un equipo restringido de investigadores en una prestigiosa universidad, ni trabajar en una de las pocas empresas que construyen ordenadores cuánticos. </div><div><br /></div><div>Afortunadamente, tanto Google, como <a href="https://www.ibm.com/es-es" target="_blank">IBM</a> y <a href="https://www.microsoft.com/es-es/" target="_blank">Microsoft</a> desarrollan software y herramientas para que podamos aprender y construir código y algoritmos, y ponen a nuestra disposición capacidad de cómputo en uno o varios de sus ordenadores cuánticos para testearlo y ejecutarlo.</div><div><br /></div><div>Google proporciona una plataforma muy completa llamada <a href="https://quantumai.google/" target="_blank">Google Quantum AI</a>, en la que ofrecen una librería de <a href="https://www.python.org/" target="_blank">Python</a> llamada <a href="https://quantumai.google/cirq/start/basics" target="_blank">Cirq</a> con la que podemos desarrollar nuestros algoritmos cuánticos. Para testear y ejecutar nuestros algoritmos, Google nos facilita la <a href="https://quantumai.google/quantum-virtual-machine" target="_blank">Quantum Virtual Machine</a>. </div><div><br /></div><div>En el caso de <b>IBM</b>, ofrece un entorno de ejecución llamado <a href="https://qiskit.org/" target="_blank">Qiskit</a>. Mediante sus herramientas podemos, de manera visual, algoritmos cuánticos usando circuitos usando <i>qubits</i>, puertas lógicas y otros recursos esenciales. También podemos generar estos circuitos directamente con código, usando una librería en <a href="https://www.python.org/" target="_blank">Python</a>, que también nos permite visualizar el circuito y simular su ejecución. Adicionalmente, IBM ofrece recursos cuánticos para poder ejecutar estos algoritmos. Podemos elegir uno de estos recursos o máquinas a lo largo del planeta (según la carga y pool que haya), y esperar nuestro turno. IBM también ofrece <a href="https://quantum-computing.ibm.com/services/programs/docs/runtime/manage/systems/" target="_blank">sistemas y simuladores</a> (de pago) para planes empresariales.</div><div><br /></div><div>La solución de <b>Microsoft</b> se llama <a href="https://learn.microsoft.com/es-es/azure/quantum/" target="_blank">Azure Quantum</a>, en donde tenemos a nuestra disposición los servicios y recursos en la nube suficientes para poder usar el potencial de la computación cuántica. Para desarrollar, Microsoft ha desarrollado el <a href="https://learn.microsoft.com/es-es/azure/quantum/user-guide/" target="_blank">lenguaje Q#</a> y el kit de desarrollo Quantum, el cual puede ser utilizado desde <a href="https://visualstudio.microsoft.com/es/" target="_blank">Visual Studio</a> o desde <a href="https://code.visualstudio.com/" target="_blank">Visual Studio Code</a>. Esta herramienta de desarrollo permite utilizar el lenguaje <a href="https://fsharp.org/" target="_blank">F#</a>, Qiskit o Cirq. Al igual que IBM, Microsoft también nos proporciona hardware cuántico y simuladores para poder testear y ejecutar nuestros algoritmos.</div><div><br /></div><div><br /></div><h2 style="text-align: left;">Los retos de la computación cuántica</h2><div>Día a día se logran pequeños avances, y hay algunos objetivos clave para los próximos años.</div><div><br /></div><div>El reto más importante y urgente es conseguir <b><i>qubits</i> de calidad</b>, que mantengan la integridad de los estados cuánticos durante más tiempo, lo que permitirá realizar operaciones y algoritmos cada vez más complejos. Adicionalmente, los sistemas de corrección de errores serán claves para garantizar los resultados.</div><div><br /></div><div>Recientemente, en España, se ha creado el <a href="https://www.cuco.tech/" target="_blank">proyecto CUCO</a>, subvencionado por el <a href="https://www.cdti.es/" target="_blank">CDTI</a> y el <a href="https://www.ciencia.gob.es/" target="_blank">Ministerio de Ciencia e Innovación</a>, y formado por un consorcio de siete empresas. El objetivo de CUCO es la investigación y la implantación de tecnologías basadas en computación cuántica que puedan ser aplicadas a la industria.</div><div><br /></div><div>Para 2024 se prevé establecer un estándar de criptografía postcuántica, lo que abre el camino a desarrollar criptosistemas que se puedan ejecutar en ordenadores clásicos pero que no puedan ser atacados por ordenadores cuánticos. </div><div><br /></div><div>Para 2025, IBM tiene como objetivo lanzar un ordenador cuántico de 4000 <i>qubits</i>, usando múltiples grupos de procesadores escalados modularmente y ejecutándose en paralelo. Esta tecnología mejoraría la mitigación de errores y orquestaría las cargas de trabajo de forma inteligente. </div><div><br /></div><div>Para 2030 se prevé alcanzar el millón de <i>qubits</i>. </div><div><br /></div><div>Para 2040 se prevé romper la criptografía RSA y la curva elíptica.</div><div><br /></div><div>Queda pendiente saber si llegaremos a usar algún día un ordenador personal o un teléfono móvil cuántico. Pero, sin duda alguna, la carrera de la innovación en la computación cuántica no ha hecho más que empezar. Y las sorpresas que nos deparan son apasionantes.</div><div><br /></div><h2 style="text-align: left;">Referencias</h2><div><br /></div><div><b>Noticias sobre Computación cuántica:</b></div><div><ul style="text-align: left;"><li><a href="https://es.wikipedia.org/wiki/Computaci%C3%B3n_cu%C3%A1ntica" target="_blank">Quantum Computing Report</a></li><li><a href="https://www.sciencedaily.com/news/matter_energy/quantum_computing/" target="_blank">Science Daily</a></li><li><a href="https://news.mit.edu/topic/quantum-computing" target="_blank">MIT News</a></li></ul><div><br /></div><div><b>Algoritmos cuánticos:</b></div></div><div><ul style="text-align: left;"><li><a href="https://quantumalgorithmzoo.org/" target="_blank">Zoo de Algoritmos cuánticos</a></li></ul><div><br /></div></div><div><b>Desarrollo con IBM Quantum:</b></div><div><ul style="text-align: left;"><li><a href="https://qiskit.org/" target="_blank">Página oficial de Qiskit</a></li><li><a href="https://qiskit.org/documentation/intro_tutorial1.html" target="_blank">Tutorial básico de Qiskit</a></li><li><a href="https://qiskit.org/documentation/tutorials.html#tutorials" target="_blank">Tutoriales de Qiskit</a></li><li><a href="https://www.ibm.com/quantum/qiskit-runtime" target="_blank">Qiskit runtime</a></li><li><a href="https://quantum-computing.ibm.com/services/programs/docs/runtime/manage/systems/" target="_blank">Recursos cuánticos para Qiskit (sistemas y simuladores)</a></li><li><a href="https://cloud.ibm.com/apidocs/quantum-computing" target="_blank">Documentación de Qiskit</a></li><li><a href="https://www.ibm.com/quantum" target="_blank">IBM Quantum</a></li></ul><div><b><br /></b></div><div><b>Desarrollo con Microsoft Azure Quantum:</b></div><div><ul style="text-align: left;"><li><a href="https://learn.microsoft.com/es-es/azure/quantum/" target="_blank">Documentación de Azure Quantum</a></li><li><a href="https://azure.microsoft.com/es-es/products/quantum/#overview" target="_blank">Página oficial de Azure Quantum</a></li><li><a href="https://learn.microsoft.com/en-us/training/paths/quantum-computing-fundamentals/" target="_blank">Curso gratuito de Quantum computing foundations</a></li><li><a href="https://learn.microsoft.com/es-es/azure/quantum/user-guide/" target="_blank">Guía del lenguaje Q#</a></li><li><a href="https://fsharp.org/" target="_blank">Página oficial del lenguaje F#</a></li><li><a href="https://visualstudio.microsoft.com/es/" target="_blank">Visual Studio</a></li><li><a href="https://code.visualstudio.com/" target="_blank">VSCode</a></li></ul><div><b><br /></b></div><div><b>Desarrollo con Google Quantum AI:</b></div></div><div><ul style="text-align: left;"><li><a href="https://quantumai.google/" target="_blank">Página oficial de Google Quantum AI</a></li><li><a href="https://quantumai.google/quantum-virtual-machine" target="_blank">Quantum Virtual Machine</a></li><li><a href="https://quantumai.google/hardware" target="_blank">Hardware cuántico</a></li><li><a href="https://quantumai.google/cirq" target="_blank">Cirq</a></li><li><a href="https://quantumai.google/cirq/start/start" target="_blank">Hello World con Cirq</a></li><li><a href="https://quantumai.google/education" target="_blank">Recursos de aprendizaje</a></li></ul></div><div><br /></div><div><b>Compañías líderes en computación cuántica:</b></div></div></div></div></div><div><ul style="text-align: left;"><li><a href="https://www.ibm.com/quantum" target="_blank">IBM</a></li><li><a href="https://azure.microsoft.com/es-es/products/quantum/#overview" target="_blank">Microsoft Azure Quantum</a></li><li><a href="https://azure.microsoft.com/es-es/products/quantum/#overview" target="_blank">Google Quantum AI</a></li><li><a href="https://www.xanadu.ai/" target="_blank">Xanadu</a></li><li><a href="https://www.dwavesys.com/" target="_blank">D-Wave Systems</a></li><li><a href="https://quantumcircuits.com/" target="_blank">QCI (Quantum Circuits)</a></li><li><a href="https://www.rigetti.com/" target="_blank">Rigetti</a></li></ul><div><br /></div></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-773598916732720312022-04-14T18:30:00.001+02:002022-04-14T18:34:14.271+02:00Super Windows: Cómo optimizar y acelerar tu Windows (parte 3)<p>Windows es un gran sistema operativo, pero necesita de un mantenimiento para exprimir su potencial y rendimiento. A medida que lo usamos parece ralentizarse y ser muy pesado. Esta motivación me ha llevado a escribir estos artículos para enseñarte cómo optimizar y acelerar tu Windows.</p><div>En esta serie de artículos vamos a aprender cómo podemos acelerar su velocidad y a liberar muchos de sus recursos. Con ello conseguiremos que nuestro ordenador se convierta en un Fórmula 1, entregándonos toda su potencia y su velocidad.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ2x3dRiSCIPZXOr9JAvuBTELBaADfntXqjfBMPKVPzOZRcruAZ4pA1Zu5WkZgw8STlozkghscVlMQJRgJUyX4tzIiA1QnvY9UpeMIYYsmHT1KWjAIfQyIn2q2lYugVxz8pvQUMUA7JuOGoJmgSSPKSa_ZB5CFJBOvV5XfahAorx38Rnc9Vw/s1000/SuperWindows3.jpeg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1000" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ2x3dRiSCIPZXOr9JAvuBTELBaADfntXqjfBMPKVPzOZRcruAZ4pA1Zu5WkZgw8STlozkghscVlMQJRgJUyX4tzIiA1QnvY9UpeMIYYsmHT1KWjAIfQyIn2q2lYugVxz8pvQUMUA7JuOGoJmgSSPKSa_ZB5CFJBOvV5XfahAorx38Rnc9Vw/w640-h384/SuperWindows3.jpeg" width="640" /></a></div><br /><div>En esta tercera parte vamos a abordar otras configuraciones esenciales para optimizar y acelerar nuestro Windows.</div><p>La mayor parte de estas opciones pueden ser accedidas desde las opciones de configuración de Windows, o bien, desde el menú Inicio, escribir el título de la opción para que lo busque y acceda directamente a la opción.</p><p>La relación de opciones aquí presentadas aplican completamente a Windows 11. Algunas de estas opciones pueden ser también aplicables a Windows 10 y anteriores, pero la forma de acceder a ellas puede ser diferente. El porcentaje de opciones comunes va decrementándose cuanto más antigua sea la versión de Windows.</p><p><br /></p><h2 style="text-align: left;"><span style="font-size: large;">Configuración para juegos si no eres Gamer</span></h2><div>Si no eres gamer, o tus necesidades de juego no están alineadas con XBox, podemos cambiar algunas configuraciones de la opción "Juegos" dentro de la configuración de Windows.</div><div><br /></div><div>Si no utilizas tu equipo para jugar con XBox, te conviene desactivar la "XBox Game bar", así como también el "Modo Juego" y las "Capturas de pantalla".</div><div><br /></div><div><br /></div><h2 style="text-align: left;">Configuración para juegos y aplicaciones que exprimen los gráficos</h2><div>Tanto si eres gamer como si eres un grafista, diseñador o un editor de vídeos, esta configuración te interesa.</div><div><br /></div><div>En la Configuración de Windows, accedemos a la opción "Juegos", luego <span style="background-color: white;">"Pantalla"</span> "Modo de juego" y, después, "Gráficos". Aparecerá una lista de aplicaciones que utilizan de forma especializada los gráficos de tu equipo. En la parte superior podemos agregar aplicaciones de forma manual (como juegos) si es que dicha aplicación no aparece en la lista. Para ello, seleccionamos el valor "Aplicación de escritorio" y pulsamos el botón "Examinar", donde buscaremos el archivo ejecutable de la aplicación en el disco.</div><div><br /></div><div>Una vez tengas la aplicación (o el juego) en la lista, se selecciona esta aplicación en la lista y se pulsa el botón "Opciones". Mostrará un cuadro de diálogo, en donde seleccionaremos la opción "Alto Rendimiento".</div><div><br /></div><div><br /></div><h2 style="text-align: left;"><span style="font-size: large;">Privacidad y Seguridad</span></h2><div>Si no damos un uso profesional de nuestro equipo, como pueda ser de programador, conviene deshabilitar todas las opciones de la sección "Seguridad" ("Buscar mi dispositivo" y "Para programadores"), dentro de la opción "Privacidad y Seguridad" en la configuración de Windows, desde la categoría "Ubicación" hasta la categoría "Captura de aplicaciones y pantalla".</div><div><br /></div><div>También es recomendable deshabilitar (si realmente no lo necesitas) todas las configuraciones de las opciones "General", "Voz", "Personalización de entrada manuscrita y escritura", "Diagnóstico y comentarios", "Historial de actividades", etc., así como también todos aquellos permisos que realmente no necesitas o no quieres tener activos (como ubicación, cámara, micrófono, notificaciones, etc). Todas estas opciones están consumiendo recursos en segundo plano y pueden no ser tan necesarias.</div><div><br /></div><div>En general, la mayor parte de estas opciones se pueden deshabilitar. No obstante, es mejor que analices cada una de estas opciones para que decidas qué dejar activo. Por ejemplo, las opciones de cámara y micrófono pueden ser necesarias, especialmente si realizas videoconferencias o si eres músico y realizas grabaciones de audio.</div><div><br /></div><div><br /></div><h2 style="text-align: left;"><span style="font-size: large;">Windows Defender</span></h2><div>Hay una configuración que, por defecto, Microsoft activa para realizar una monitorización exhaustiva de todo lo que Windows Defender está realizando. Esta monitorización es a efectos de información y reporte, más que de diagnóstico y acción.</div><div><br /></div><div>Para ello, accedemos a Windows Defender, y accedemos a la opción "Seguridad del dispositivo", y a la sección "Aislamiento del núcleo" (detalles del aislamiento). Aquí desactivaremos la opción.</div><div><br /></div><div><br /></div><h2 style="text-align: left;"><span style="font-size: large;">Red</span></h2><div>Por defecto, Windows se reserva parte del ancho de banda para uso propio, como, por ejemplo, para las actualizaciones de Windows. Si queremos aprovechar al máximo nuestro ancho de banda realizaremos los siguientes pasos:</div><div>1) <b>Ejecutar</b> <i>regedit</i> <b>como administrador</b> del sistema (pulsa las teclas Windows + R, y escribir "<i>regedit"</i>, o desde el menú Inicio escribir en la búsqueda "<i>regedit</i>")</div><div>2) Buscar la siguiente ruta:</div><div>\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile</div><div><br /></div><div>3) Seleccionar la variable <span style="background-color: white;">NetworkThrottlingIndex</span> y cambiar su valor en modo hexadecimal a "FFFFFFF"</div><div>4) Aceptar el cambio</div><div><br /></div><div>Tras reiniciar el equipo, adoptará esta nueva configuración.</div><div><br /></div><div><br /></div><h2 style="text-align: left;"><span style="font-size: large;">Discos y almacenamiento</span></h2><h4 style="text-align: left;"><span style="font-size: medium;">Configuraciones automáticas sobre almacenamiento</span></h4><div>Dentro de la configuración de Windows, en Sistema, tenemos la opción "Almacenamiento". Una de sus opciones, "Sensor de almacenamiento", permite, de forma automática, detectar aquellos componentes de almacenamiento no son necesarios para su eliminación automática.</div><div><br /></div><div>En la opción "Recomendaciones de limpieza" encontraremos varias configuraciones que nos ayudan a limpiar de forma automática elementos de almacenamiento importantes, como "Instalaciones anteriores de Windows" o la carpeta "Descargas", o "Archivos grandes o sin usar", "Archivos sincronizados a la nube" o "Aplicaciones sin usar".</div><div><br /></div><div>También podemos seleccionar la estadística de "Archivos temporales" y configurar las opciones que más se ajusten a nuestras necesidades o preferencias.</div><div><br /></div><div><br /></div><h4 style="text-align: left;"><span style="font-size: medium;">Eliminar archivos temporales y "prefetch"</span></h4><div>Para eliminar directamente archivos temporales, podemos lanzar el cuadro "Ejecutar" (Windows + R o clic derecho en menú Inicio y opción "Ejecutar", y escribimos %temp%. Con ello aparecerán todos los archivos temporales actuales de aplicaciones de terceros. Basta con seleccionar todos (Ctrl + E) y borrar (Supr). Es posible que algunos archivos no se puedan eliminar (se están utilizando), por lo que seleccionaremos la opción "Omitir".</div><div><br /></div><div>Para eliminar directamente archivos temporales internos (de Windows), realizamos lo mismo que lo indicado arriba, pero en lugar de especificar %temp%, omitimos el símbolo de porcentaje (es decir, especficicamos sólo la palabra temp).</div><div><br /></div><div>Otros archivos que podemos eliminar son los denominados "prefetch", que son generados por Windows durante la gestión de la memoria, y que se van quedando ahí. Para ello, repetimos los pasos anteriores y escribimos "prefetch" en el cuadro "Ejecutar". El resto de pasos son los mismos.</div><div><br /></div><div><br /></div><h4 style="text-align: left;"><span style="font-size: medium;">Liberar espacio de disco</span></h4><div>Otra forma para liberar espacio de almacenamiento es arrancar el Administrador de Archivos (el atajo serían las teclas Windows + E), localizar la unidad de disco que queremos liberar, hacer clic con el botón derecho del ratón y seleccionar la opción "Propiedades, y pulsamos el botón "Liberar espacio". En la ventana de diálogo podemos seleccionar previamente los elementos que queremos eliminar y desmarcar aquellos elementos que queremos conservar.</div><div><br /></div><div><br /></div><h4 style="text-align: left;"><span style="font-size: medium;">Defragmentar unidades de discos</span></h4><div>Una configuración interesante para acelerar el acceso al disco, es su defragmentación. Esta técnica junta la información de los archivos en sectores contiguos de disco, por lo que el acceso a los mismos se acelera al no tener que buscar en diferentes sitios y mover los cabezales. Esta configuración sólo aplica a discos duros mecánicos o rígidos (HDD), no a discos de estado sólido (SSD). </div><div><br /></div><div>Si tienes un disco mecánico, arranca el Administrador de Archivos (el atajo serían las teclas Windows + E), localizar la unidad de disco que queremos liberar, hacer clic con el botón derecho del ratón y seleccionar la opción "Propiedades, y en la sección "Optimizar y defragmentar unidad" pulsamos el botón "Analizar" y, cuando termine, pulsamo la opción "Optimizar". Este proceso lleva un rato, por lo que ten paciencia.</div><div><br /></div><div><br /></div><h4 style="text-align: left;"><span style="font-size: medium;">Optimizar unidades de disco</span></h4><div>En el caso de tener unidades de disco sólido (SSD), siguiendo los pasos de la sección anterior, observaremos que el botón "Analizar" estará deshabilitado. Estará disponible únicamente el botón "Optimizar" para nuestro disco SSD, que nos permitirá una mejora del rendimiento de ese disco.</div><div><br /></div><div><b>Nota: </b><i>En Windows 11 se agregó esta mejora, con lo que no se defragmenta el disco si es SSD. En Windows 10 y anteriores, se recomiendo no utilizarlo. </i></div><div><br /></div><div><br /></div><h4 style="text-align: left;"><span style="font-size: medium;">Papelera de reciclaje</span></h4><div>Como medida de seguridad, Windows envía todos los archivos y elementos que eliminamos a la Papelera de reciclaje, a fin de que, si nos equivocamos o arrepentimos, podamos recuperarlo nuevamente. </div><div><br /></div><div>Básicamente, mueve los archivos de su origen a una carpeta especial, por lo que seguimos ocupando espacio en el disco.</div><div><br /></div><div>Si queremos eliminar definitivamente el contenido de la Papelera, haremos clic derecho sobre ésta y seleccionamos la opción "Vaciar".</div><div><br /></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Visor de Eventos</h2><div><br /></div><div>Todo lo que sucede en Windows es almacenado en el Visor de Eventos. Esta herramienta es útil en el caso de que haya sucedido algún problema que impacte en el funcionamiento de Windows, ya que teniendo un registro de lo que ha ocurrido puede ayudar a diagnosticar los problemas.</div><div><br /></div><div>Con el tiempo, su tamaño puede ser considerable. Si no has tenido problemas críticos en el funcionamiento de Windows, puedes acceder a esta herramienta y eliminar todos los eventos para liberar espacio. Esto se realiza en desde el árbol de la izquierda, en "Registros de Windows".</div><div><br /></div><div><b>Nota:</b> No te preocupes. Windows sigue capturando eventos desde el momento actual de forma constante.</div><div><br /></div><div><br /></div><h2 style="text-align: left;">Puntos de restauración</h2><div>A medida que vamos actualizando Windows vamos generando puntos de restauración. También los generamos de forma manual, a modo de backup. Esto, lógicamente, consume bastante espacio en nuestro equipo. Así pues, podemos configurar y eliminar puntos de eliminación para optimizar este espacio.</div><div><br /></div><div>Para ello, en el Explorador de Archivos, haremos clic sobre "Este Equipo", opción "Mostrar más opciones" y seleccionar "Propiedades". A continuación seleccionamos "Opciones avanzadas del Sistema". Aparece una nueva ventana de diálogo. Seleccionamos la pestaña "Protección del sistema", y en la sección de "Configuración de la protección" pulsamos el botón "Configurar...", en donde tendremos a nuestra disposición las opciones de restauración.</div><div><br /></div><div><br /></div><div><h1>Serie completa</h1><p></p><ul><li><a href="https://rafinguer.blogspot.com/2022/03/super-windows-como-optimizar-y-acelerar.html" target="_blank">Parte 1: Servicios y configuración de aplicaciones</a> </li><li><a href="https://rafinguer.blogspot.com/2022/04/super-windows-como-optimizar-y-acelerar.html" target="_blank">Parte 2: Opciones de energía, personalización, pantalla, CPU, memoria, reconocimiento facial, asistencia de Windows, diagnóstico y notificaciones</a></li><li><a href="https://rafinguer.blogspot.com/2022/04/super-windows-como-optimizar-y-acelerar_14.html" target="_blank">Parte 3: Opciones para juegos, gráficos, privacidad, seguridad, Windows Defender, red, discos, almacenamiento, visor de eventos y puntos de restauración</a></li><li>Parte 4: </li></ul></div><div> </div><div><br /></div><div><br /></div><div> </div><div><br /></div><div><br /></div><div> </div><p></p><p><br /></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-54610053120735590212022-04-14T18:07:00.002+02:002022-04-14T18:34:07.609+02:00Super Windows: Cómo optimizar y acelerar tu Windows (parte 2)<p>Windows es un gran sistema operativo, pero necesita de un mantenimiento para exprimir su potencial y rendimiento. A medida que lo usamos parece ralentizarse y ser muy pesado. Esta motivación me ha llevado a escribir estos artículos para enseñarte cómo optimizar y acelerar tu Windows.</p><div>En esta serie de artículos vamos a aprender cómo podemos acelerar su velocidad y a liberar muchos de sus recursos. Con ello conseguiremos que nuestro ordenador se convierta en un Fórmula 1, entregándonos toda su potencia y su velocidad.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggIhkNFLskVFVK0jb4i3gREbEU7LBXNflYEvlaFaabn5XxyuX_rII3KjSAAv4e5fe4OBKq3lwyxzHvf7AbAIg3fytYAB5ej7pJxj2Ks3_FP89OomtxSgaDV1UkVoW5gOl58Glxaqd7Pt-CG2N7eJkIIJF_PrV2nq6TlhPfB7Bq-ESQ9hwNPA/s1000/SuperWindows2.jpeg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1000" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggIhkNFLskVFVK0jb4i3gREbEU7LBXNflYEvlaFaabn5XxyuX_rII3KjSAAv4e5fe4OBKq3lwyxzHvf7AbAIg3fytYAB5ej7pJxj2Ks3_FP89OomtxSgaDV1UkVoW5gOl58Glxaqd7Pt-CG2N7eJkIIJF_PrV2nq6TlhPfB7Bq-ESQ9hwNPA/w640-h384/SuperWindows2.jpeg" width="640" /></a></div><br /><div>En esta segunda entrega vamos a aprender a modificar algunas configuraciones para extraer el máximo de potencia. </div><p>La mayor parte de estas opciones pueden ser accedidas desde las opciones de configuración de Windows, o bien, desde el menú Inicio, escribir el título de la opción para que lo busque y acceda directamente a la opción.</p><p>La relación de opciones aquí presentadas aplican completamente a Windows 11. Algunas de estas opciones pueden ser también aplicables a Windows 10 y anteriores, pero la forma de acceder a ellas puede ser diferente. El porcentaje de opciones comunes va decrementándose cuanto más antigua sea la versión de Windows.</p><p><br /></p><h2 style="text-align: left;"><span style="font-size: large;">Opciones de Energía</span></h2><p>A través de la configuración de Windows, hay una opción para configurar el modo en que el PC consume la energía, especialmente si tu equipo es un ordenador portátil (laptop). Te recomiendo que uses la opción de "Máximo rendimiento".</p><p>Otra recomendación es cambiar la configuración de "Pantalla y Suspensión", deshabilitando todas las opciones de suspensión (cambiando al valor "Nunca"). A muchos equipos les cuesta mucho salir de una suspención, llegando a bloquearse y a consumir más recursos a la hora de recuperarse.</p><p>En las opciones de "Plan de Energía" (buscar desde el menú Inicio), seleccionar "Cambiar la opción avanzada de energía" y deshabilitar la opción de apagar disco duro (valor "Nunca").</p><p><br /></p><h2 style="text-align: left;"><span style="font-size: large;">Opciones de Personalización</span></h2><p>En esta sección de la configuración se hallan bastantes configuraciones posibles.</p><p><br /></p><h4 style="text-align: left;">Opciones visuales</h4><p>Es muy recomendable utilizar el modo Oscuro (en temas), especialmente en los equipos portátiles, ya que gasta mucha menos energía.</p><p>En la opción "Colores" desactivamos los "Efectos de transparencia". Esto elimina la transparencia en las ventanas, aumentando la velocidad y la fluidez de presentación de gráficos de Windows.</p><p><br /></p><h4 style="text-align: left;">Barra de tareas</h4><p>La opción de "Barra de tareas" en las opciones de personalización nos permite activar o desactivar las aplicaciones disponibles en la barra de tareas. Deja las que te sean realmente necesarias (por ejemplo, podemos desactivar el chat o los widgets).</p><p>En la sección "Desbordamiento de barra de tareas" haremos lo mismo.</p><p>También podemos desactivar algunas de las opciones de "Compartamiento de la barra de tareas" para lograr un mejor rendimiento. Esto es opcional.</p><p><br /></p><h2 style="text-align: left;"><span style="font-size: large;">Opciones de pantalla</span></h2><h4 style="text-align: left;">Incrementar el rendimiento gráfico</h4><p>Desde la opción "Sistema" accedemos a las opciones de pantalla. Después, accedemos a la opción "Gráficos". Por defecto, Microsoft agrega algunas aplicaciones que a menudo no utilizamos y están consumiendo recursos. Te recomiendo que configures el valor "Alto rendimiento" para todas las aplicaciones que realmente no utilices o que uses de forma casual.</p><p>También desde la configuración "Gráficos", accedemos al enlace u opción "Cambiar la configuración de gráficos predeterminada" y activar la opción "Programación de GPU acelerada por hardware". Esto permitirá que, si tienes tarjeta gráfica aceleradora, sea ésta la que procese los gráficos (especialmente el 3D), en lugar de la tarjeta gráfica integrada o la CPU.</p><p>Si en la configuración de la GPU aparece la opción "Frecuencia de actualización variable", es recomendable deshabilitarla para optimizar aún más el procesado de gráficos.</p><p>Con estas opciones, conseguiremos mucho mayor rendimiento, especialmente para la ejecución de juegos.</p><p><br /></p><h4 style="text-align: left;">Animaciones y efectos</h4><p>Otro de los puntos que más recursos consumen son las animaciones y efectos de la interfaz de usuario, tales como las sombras de las ventanas, animaciones en diferentes componentes visuales, etc.</p><p>Para mejorar el rendimiento y reducir el consumo de recursos, vamos a buscar "avanzada" en el menú de Inicio de Windows, para encontrar las opciones avanzadas del Sistema (también se puede encontrar accediendo a la configuración de Windows, Sistema y opciones avanzadas). Una vez aparezca el cuadro de diálogo de opciones avanzadas, seleccionamos la opción "Opciones de rendimiento", donde aparecerán las configuraciones de efectos visuales entre otros. Simplemente desmarcamos las opciones que no queremos. Si eliminamos todas las configuraciones, obtendremos el mayor rendimiento.</p><p>Otra configuración que podemos modificar es la siguiente: accedemos a la configuración de Windows, seleccionamos la categortía de "Accesibilidad" y la opción "Efectos visuales". Aquí podremos deshabilitar directamente los efectos de transparencia o las de animación (entre otras).</p><p><br /></p><h2 style="text-align: left;"><span style="font-size: large;">CPU</span></h2><p>Vamos a asegurarnos de que Windows está usando todos los núcleos del microprocesador. Si nuestra CPU tiene 8 núcleos, y sólo están habilitados 6, estamos desperdiciando mucha potencia de procesamiento. </p><p>Para ello, pulsamos las teclas Windows + R (comando ejecutar), y en el cuadro de diálogo escribimos "msconfig" (sin las comillas), con lo que aparecerá la aplicación "Configuración del Sistema". Seleccionamos la pestaña "Arranque" y pulsamos el botón "Opciones avanzadas...". Nos aseguraremos de que la configuración de "Número de procesadores" está habilitada con el número máximo de núcleos que tiene nuestro ordenador.</p><p><br /></p><h2 style="text-align: left;"><span style="font-size: large;">Memoria</span></h2><h4 style="text-align: left;">Gestión automática de memoria</h4><p>Por defecto, Windows gestiona automáticamente el uso de la memoria de la manera más óptima. De forma opcional, podemos configurar la memoria máxima a utilizar. </p><p>Para ello, pulsamos las teclas Windows + R (comando ejecutar), y en el cuadro de diálogo escribimos "msconfig" (sin las comillas), con lo que aparecerá la aplicación "Configuración del Sistema". Seleccionamos la pestaña "Arranque" y pulsamos el botón "Opciones avanzadas...". Aquí especificaremos la cantidad de memoria en la configuración "Cantidad máxima de memoria".</p><p><br /></p><h4 style="text-align: left;">Memoria virtual</h4><p>Si tu equipo tiene poca memoria (hasta 4GB), podemos conseguir un mayor rendimiento si asignamos memoria virtual. Esto tiene sentido si tienes un disco de estado sólido (SSD), pues es mucho más rápido que un disco duro rígido o mecánico.</p><p>Para asignar memoria virtual, primero hay que acceder a la Configuración del Sistema (podemos acceder desde el Explorador de Windows, seleccionado "Este Equipo", después hacer clic derecho y seleccionar "Propiedades"). En la ventana de diálogo que aparece, seleccionamos el enlace "Configuración avanzada del Sistema", y en la sección "Rendimiento" pulsamos el botón "Configuración". Después, seleccionamos la pestaña "Opciones avanzadas" y, en la sección "Memoria Virtual", pulsamos el botón "Cambiar".</p><p>Por defecto, Windows selecciona automáticamente la memoria virtual, por lo que habrá que desactivar esta opción. A continuación, seleccionamos "Tamaño personalizado". Podemos asignar el tamaño recomendado (parte inferior), pero podemos asignarle un tamaño más óptimo, el cual se basaría en asignar, como mínimo, la misma cantidad de memoria RAM de nuestro equipo, y, como máximo, el doble. Esta cantidad hay que expresarla en MegaBytes, por lo que habrá que multiplicar el número de GigaBytes por 1024 (por ejemplo, si tu equipo tiene 4 GB RAM, como mínimo hay que especificar 4096 MB y como máximo 8192 MB),</p><p><br /></p><h2 style="text-align: left;">Inicio de sesión con reconocimiento facial</h2><p>En la Configuración de Windows, seleccionaremos "Aplicaciones" y "Características opcionales". Entre las posibles características deshabilitaremos "Rostro de Windows Hello". Esta opción permite iniciar la sesión de Windows a través de la cámara del equipo, escaneando tu rostro.</p><p><br /></p><h2>Asistencia rápida de Microsoft</h2><p>En la Configuración de Windows, seleccionaremos "Aplicaciones" y "Características opcionales". Entre las posibles características deshabilitaremos "Asistencia rápida de Microsoft". Este tipo de servicio es muy raro que se utilice para un uso doméstico.</p><p><br /></p><h2 style="text-align: left;">Datos de diagnóstico</h2><p>Toda la actividad que realices manualmente en Windows, toda la actividad automática que realice el propio Windows y todos aquellos eventos que se producen durante una sesión de Windows, es monitorizada y utilizada para estadísticas y para realizar diagnósticos sobre el estado de Windows, lo que puede facilitar la detección de problemas. Esta información se envía a Microsoft para estos propósitos.</p><p>Esta información, una vez enviada, no tiene valor para nosotros, y lo único que hace es ocupar espacio en nuestro equipo. Por tanto, podemos eliminar estos datos y liberar espacio.</p><p>Para conseguir esto accedemos a Configuración de Windows, seleccionamos "Privacidad y Seguridad", después "Diagnóstico y comentarios" y, por último, "Eliminar datos de diagnóstico".</p><p>También podemos deshabilitar la opción "Enviar los datos de diagnóstico opcionales", dentro de la opción "Datos de Diagnóstico".</p><p><br /></p><h2 style="text-align: left;">Notificaciones</h2><p>Las notificaciones, además de distraer y molestar, consumen bastantes recursos, pues constantemente están chequeando nuevas notificaciones para mostrar.</p><p>Podemos deshabilitar total o parcialmente estas notificaciones. </p><p>En Configuración de Windows seleccionamos "Sistema" y después "Notificaciones". Se mostrará una lista de las aplicaciones que pueden enviar notificaciones, por lo que podemos seleccionar qué aplicaciones queremos o no queremos que notifiquen.</p><p>Podemos deshabilitar todas las notificaciones si deshabilitamos la opción "Notificaciones" (primera opción, en la parte superior).</p><p><br /></p><h1 style="text-align: left;">Serie completa</h1><p></p><ul style="text-align: left;"><li><a href="https://rafinguer.blogspot.com/2022/03/super-windows-como-optimizar-y-acelerar.html" target="_blank">Parte 1: Servicios y configuración de aplicaciones</a> </li><li><a href="https://rafinguer.blogspot.com/2022/04/super-windows-como-optimizar-y-acelerar.html" target="_blank">Parte 2: Opciones de energía, personalización, pantalla, CPU, memoria, reconocimiento facial, asistencia de Windows, diagnóstico y notificaciones</a></li><li><a href="https://rafinguer.blogspot.com/2022/04/super-windows-como-optimizar-y-acelerar_14.html" target="_blank">Parte 3: Opciones para juegos, gráficos, privacidad, seguridad, Windows Defender, red, discos, almacenamiento, visor de eventos y puntos de restauración</a></li><li>Parte 4: </li></ul><p></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-44148640768876402612022-03-18T11:43:00.008+01:002022-04-14T18:33:50.354+02:00Super Windows: Cómo optimizar y acelerar tu Windows (parte 1)Windows es un gran sistema operativo, pero necesita de un mantenimiento para exprimir su potencial y rendimiento. A medida que lo usamos parece ralentizarse y ser muy pesado. Esta motivación me ha llevado a escribir estos artículos para enseñarte cómo optimizar y acelerar tu Windows.<div><br /></div><div>En esta serie de artículos vamos a aprender cómo podemos acelerar su velocidad y a liberar muchos de sus recursos. Con ello conseguiremos que nuestro ordenador se convierta en un Fórmula 1, entregándonos toda su potencia y su velocidad.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjFqiObcsuepQNvMX40m-vMMHh8Gve5Bx12paub_HNIx-Xur6IhDy44SI8zmDPLFOT1QdTILVoFEXvgOgX1z4S55RPXrlf2bcw1QMF887bL3gjWZEydvEj9rzPot3RN58O2DvZFxZSEYA0MLHIkYWJytYn_8qyjv0zNqQy1qPAxpfZR0NkSoQ=s1000" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1000" height="384" src="https://blogger.googleusercontent.com/img/a/AVvXsEjFqiObcsuepQNvMX40m-vMMHh8Gve5Bx12paub_HNIx-Xur6IhDy44SI8zmDPLFOT1QdTILVoFEXvgOgX1z4S55RPXrlf2bcw1QMF887bL3gjWZEydvEj9rzPot3RN58O2DvZFxZSEYA0MLHIkYWJytYn_8qyjv0zNqQy1qPAxpfZR0NkSoQ=w640-h384" width="640" /></a></div><br /><div>En esta primera entrega vamos a conocer que Windows, por defecto, viene con unos servicios ya activados por defecto, y los cuales podemos deshabilitar para ayudarle a funcionar mejor.</div><div><br /></div><div>También aprenderemos que Windows instala una serie de aplicaciones de las que podemos prescindir, aumentando el espacio en disco y ganando rendimiento al no usarlas.</div><div><br /></div><div>Estos conocimientos están recopilados sobre Windows 11, aunque gran parte también están presentes en versiones anteriores, especialmente en Windows 10. En versiones anteriores a Windows 10 no existían muchas de estas configuraciones. No obstante, algunas de ellas pueden estar presentes y pueden ayudarte a raspar algo de rendimiento. Es muy posible que no tenga el mismo camino (o pasos) y que el nombre de la opción tenga otro nombre.</div><div><br /></div><h2 style="text-align: left;">Servicios en Windows</h2><div>Para acceder a la configuración de servicios, basta con ir al menú de Inicio y escribir "Servicios" para acceder directamente. Se mostrarán todos los servicios existentes, su estado, su descripción y el tipo de inicio del servicio. También podemos acceder pulsando la tecla Windows + R (Run o Ejecutar) y escribir "services.msc".</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjWIN4DbQo1lJFIY335ctAOAj8McBNnH2N7r_JrJqSBIpaenK6SfC-cCL8prfMoU5lP9SRyEEcv4bFX4jlLO54MtQUYOitrP7zelLhMl3XayYIkXLLF-mHOflVCoLKdxL9T9ZE82_Aj8JhFErqNYTEXNZIpbKKIQnRM0p5d0szoJ1sf5GWWnA=s1200" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="675" data-original-width="1200" height="360" src="https://blogger.googleusercontent.com/img/a/AVvXsEjWIN4DbQo1lJFIY335ctAOAj8McBNnH2N7r_JrJqSBIpaenK6SfC-cCL8prfMoU5lP9SRyEEcv4bFX4jlLO54MtQUYOitrP7zelLhMl3XayYIkXLLF-mHOflVCoLKdxL9T9ZE82_Aj8JhFErqNYTEXNZIpbKKIQnRM0p5d0szoJ1sf5GWWnA=w640-h360" width="640" /></a></div><br /><div><br /></div><div><br /></div><div>Para cambiar la configuración de un servicio, basta con seleccionar el servicio en la lista, hacer clic derecho y seleccionar "Propiedades". Se mostrará una ventana de diálogo en la que podremos cambiar su configuración. De esta manera, podremos modificar su estado (en ejecución, detenido, etc.) y el tipo de inicio (por ejemplo, deshabilitado).</div><div><br /></div><div>La lista que se muestra a continuación es una recomendación personal sobre servicios que se pueden deshabilitar, según tus necesidades. Puedes deshabilitarlos o no. Además, más adelante, puedes volver a habilitar algún servicio si lo necesitas:</div><div><ul style="text-align: left;"><li>Si no estás haciendo uso de dispositivos <b>Bluetooth</b>, conviene deshabilitar todos los servicios relacionados.</li><li>Si no estás usando las capacidades de <b>XBox</b> en tu PC, te recomiendo deshabilitar todos los servicios relacionados.</li><li>Si no haces uso de máquinas virtuales, deshabilita todos aquellos servicios relacionados con <b>Hyper-V o Host HV</b>.</li><li><b>Administrador de mapas descargado. </b>Es utilizado por la aplicación "Mapas", la cual no es utilizada habitualmente.</li><li>Si no usas impresora, deshabilita el servicio <b>"Cola de impresión"</b> y el servicio <b>"Extensiones y notificaciones de impresora".</b></li><li><b>Diagnostic Execution Service. </b>Realiza monitorización y diagnósticos en Windows.</li><li><b>Tarjeta inteligente </b>y servicio de <b>Directiva de extracción de tarjetas inteligentes.</b> Si no utilizas tarjetas inteligentes, deshabilítalo.</li><li><b>Experiencia de Usuario y Telemetrías Asociadas. </b>Monitoriza cómo utilizas la interfaz de usuario, generando telemetrías (o estadísticas) de toda tu actividad.</li><li><b>Control parental. </b></li><li><b>Fax.</b> ¿Quién lo utiliza?</li><li><b>Registro remoto.</b> Esta opción permite a un usuario, desde un equipo remoto, poder modificar el registro de Windows.</li><li>Si no haces uso de sistemas biométricos para desbloquear el equipo (como la huella digital), deshabilita el <b>"Servicio biométrico de Windows"</b>. </li><li>Si no tienes cifrado tu disco duro (lo cual sería muy recomendable por temas de seguridad), deshabilita el servicio <b>"Servicio Cifrado de Unidad Bitlocker"</b>.</li><li><b>Servicio AVCTP.</b> Este servicio se utiliza para conectar dispositivos de audio y micrófono por Bluetooth. Si no utilizas estos dispositivos, desactívalo.</li><li><b>Servicio de Directivas de Diagnóstico. </b>Lo utiliza Windows para recopilar información variada de tu equipo para intentar ofrecerte un diagnóstico en caso de problemas. Raramente lo utilizamos y su resultado no siempre es eficiente.</li><li><b>Servicio de geolocalización. </b>Envía tu localización a diferentes aplicaciones y dispositivos.</li><li><b>Servicio de enrutamiento de mensajes de inserción (WAP).</b> Está relacionado con telemetrías.</li><li><b>Servicio de escritura a mano y teclado táctil. </b>A no ser que uses una tablet con Windows o una Surface, estás malgastando el rendimiento de tu equipo.</li><li><b>Servicio de prueba comercial.</b></li><li><b>Servicio de punto de conexión de Windows Mobile. </b>Si tu dispositivo es móvil y tiene tarjeta SIM telefónica, te permitirá compartir la conexión a internet. Si tienes un PC, deshabilítalo.</li><li><b>Servicio Frameserver de la Cámara de Windows. </b></li><li><b>Servicio informe de errores de Windows. </b>Envía los posibles errores de Windows a Microsoft.</li><li><b>Servicio telefónico.</b></li><li><b>Servicio Volumetric Audio Compositor.</b></li><li><b>Servicio de Windows Insider. </b>Servicio de Microsoft para poder probar próximas versiones de Windows (versiones alpha y beta).</li><li><b>Sysmain.</b> Este servicio mejora el rendimiento del equipo, sólo si éste utiliza disco duro mecánico o rígido, utilizando un defragmentador de disco. Si usas un disco SSD, deshabilita este servicio.</li><li><b>Telefonía.</b></li><li><b>Wallet Service.</b> Si no utilizas compras online en Microsoft Store con tus tarjetas de crédito, deshabilita este servicio.</li><li><b>Windows Mixed Reality OpenXR Service. </b>Si no usas realidad mixta, puedes deshabilitarlo.</li><li><b>Windows Update. </b>Se encarga de actualizar automáticamente Windows. Mientras no haya actualizaciones está corriendo y consumiendo recursos. Se puede actualizar manualmente cuando lo deseemos.</li></ul><div>Algunas aplicaciones de terceros que instales posteriormente a la instalación de Windows, pueden crear servicios adicionales. Conviene revisarlos y elegir si quieres deshabilitarlos o no. Particularmente, suelo deshabilitar todos los servicios de actualización (update), como los de Google, Adobe Acrobat, etc. Si quiero actualizar estas aplicaciones puedo hacerlo manualmente y no tener ejecutando siempre estos servicios.</div></div><div><br /></div><div><br /></div><div><h2><span style="font-size: large;">Aplicaciones</span></h2><h4>Configuraciones para Aplicaciones</h4><p>En la configuración de Windows (menú Inicio y escribir "config"), aparecerá la opción "Aplicaciones". Dentro de esta opción seleccionaremos la opción "Aplicaciones y características". </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjlZiqO4hW9zMBnsuEHK5-Lt7bLpSbL4lU48DY15loUm3dbKsEHXurElhY4LqpLQcpWM5NTCGBG0XHCPwWPwXQ6Uv5BfFbUumh8aS7jaA5mmArIUhcl77hDLpYM1P6UWwmm7drTZDq6zhrRo36FP7D8ts1yOdKY7ZKR7rtueN0dXesJI_4eVg=s1206" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="636" data-original-width="1206" height="338" src="https://blogger.googleusercontent.com/img/a/AVvXsEjlZiqO4hW9zMBnsuEHK5-Lt7bLpSbL4lU48DY15loUm3dbKsEHXurElhY4LqpLQcpWM5NTCGBG0XHCPwWPwXQ6Uv5BfFbUumh8aS7jaA5mmArIUhcl77hDLpYM1P6UWwmm7drTZDq6zhrRo36FP7D8ts1yOdKY7ZKR7rtueN0dXesJI_4eVg=w640-h338" width="640" /></a></div><br /><p>Una de las configuraciones que podemos personalizar será la de "Compartir este dispositivo", la cual deshabilitaremos.</p><p>En la configuración "Más configuraciones":</p><p></p><ul><li>Deshabilitaremos todos los alias de las aplicaciones, ya que ocupan caché y afecta al rendimiento.</li><li>Deshabilitaremos la opción "Archivar aplicaciones" (no suele ser necesario).</li></ul><div><br /></div><h4>Bloatware: Aplicaciones preinstaladas por Windows</h4><div>Denro de la misma ventana de antes, debajo, aparecerá una lista de las aplicaciones que tenemos en Windows. Microsoft preinstala mucho <i><b>Bloatware</b></i>, que son aplicaciones que Windows nos instala sin permiso y que ocupan y consumen recursos (almacenamiento, memoria, red y ciclos de cpu). </div><div><br /></div><div>Siento decir que en este punto el proceso es muy manual, y hay que ir aplicación por aplicación (de aquellas que no necesitemos o queramos), hacer click en el botón que hay situado a la derecha de cada aplicación (con tres puntos verticales), e ir seleccionando la opción de "Desinstalar". Esto funcionará con algunas aplicaciones (como la del tiempo meteorológico), pero no es posible con otras aplicaciones que Microsoft "protege" para que no se desinstalen (como Cortana). </div><div><br /></div><div>Vamos desinstalando todas aquellas aplicaciones preinstaladas que no necesitamos y que no nos interesen. Una forma eficiente para desinstalar aplicaciones (incluyendo algunas que se resisten y no nos dejan, junto con todo su rastro (archivos temporales, entradas de registro, etc)), es utilizar herramientas como <a href="https://www.revouninstaller.com/revo-uninstaller-free-download/" target="_blank">Revo Uninstaller</a> o <a href="https://www.iobit.com/es/advanceduninstaller.php" target="_blank">IOBit Uninstaller</a>.</div><div><br /></div><div>¿Qué aplicaciones preinstaladas podemos desinstalar? Eso ya va en gustos y necesidades. Algunas de estas pueden ser:</div><div><ul><li><b>Microsoft Power Automate. </b>Es una herramienta para automatizar tareas basado en la nube.</li><li><b>Mixed Reality Portal. </b>Es una aplicación que simula una realidad mixta.</li><li><b>Microsoft To-Do. </b>Es una herramienta más usada en equipos empresariales.</li><li><b>Microsoft Teams. </b>Es una aplicación para trabajo en equipo, que raramente se usa en equipos domésticos.</li><li><b>Microsoft OneDrive:</b> Si no utilizas este servicio de almacenamiento en la nube, puedes prescindir de él.</li><li><b>XBox:</b> Si no utilizas el equipo para gaming o no utilizas juegos en la plataforma XBox, también puedes eliminar estas aplicaciones.</li><li><b>Tu teléfono</b></li><li><b>Recomendaciones</b></li><li><b>Obtener ayuda</b></li><li><b>Películas y TV</b></li><li><b>Notas rápidas</b></li><li><b>Microsoft ScreenSketch</b></li><li><b>Microsoft News</b></li><li><b>Microsoft Solitaire Collection</b></li><li><b>Groove Música</b></li><li><b>Mapas</b></li><li><b>Host de la experiencia de Store</b></li><li><b>Instalador de aplicación</b></li><li><b>El tiempo</b></li><li><b>Extensiones de imagen HEIF</b></li><li><b>Extensiones de imagen Webp</b></li><li><b>Extensiones de multimedia web</b></li><li><b>Centro de opiniones</b></li><li><b>Contactos</b></li><li><b>Cortana</b></li><li><b>Cuentas de correo y calendario. </b>Si utilizas estas herramientas vía Web, puedes desinstalarlas.</li><li><b>Cámara. </b>Si no utilizas la cámara para desbloquear el equipo ni para realizar videoconferencias, puedes prescindir de ella.</li></ul></div><div><br /></div><h4>Aplicaciones ejecutándose en segundo plano</h4><div>Por otra parte, algunas de estas aplicaciones se podrían ejecutar en segundo plano. Para deshabilitar este comportamiento, basta con hacer clic en el botón situado a la derecha de la aplicación, seleccionar "Opciones avanzadas" y en "Permisos de aplicaciones en segundo plano", cambiar su valor a "Nunca".</div><div><br /></div><div>Otra forma de quitar aplicaciones que se cargan y se ejecutan en segundo plano es acceder a la configuración de Windows, acceder a "Personalización", accedemos a "Barra de tareas" y a "Desbordamiento de esquinade barra de herramientas". Aquí aparecerán las aplicaciones que se instalan en la barra de herramientas, por lo que procedemos a desactivar todas las aplicaciones que queremos quitar de la barra de herramientas y que se ejecutan en segundo plano. </div><div><br /></div><div><br /></div><h4><span>Aplicaciones al inicio</span></h4><div>Algunas aplicaciones que se instalan se configuran (sin consultarnos) para que se inicien junto con el arranque de Windows. Esto, obviamente, ralentiza el inicio de Windows y además ocupan recursos. </div><div><br /></div><div>Para eliminar este inicio de aplicaciones, iremos al Administrador de Tareas de Windows (Ctrl + Alt + Supr, o bien buscarlo en el menú Inicio) y seleccionar la pestaña "Inicio". Aparecerá la lista de aplicaciones que se inician con Windows. Selecciona, una a una, la aplicación que no quieres y. con el botón derecho, se procede a deshabilitarla o a eliminarla del proceso de inicio.</div><div><br /></div><div>Te recomiendo que dejes únicamente las aplicaciones que realmente necesitas y los drivers que se inician con Windows, como la tarjeta gráfica, el micrófono, la tarjeta de sonido, la placa base, etc.</div></div><div><br /></div><div><br /></div><div><h1>Serie completa</h1><p></p><ul><li><a href="https://rafinguer.blogspot.com/2022/03/super-windows-como-optimizar-y-acelerar.html" target="_blank">Parte 1: Servicios y configuración de aplicaciones</a> </li><li><a href="https://rafinguer.blogspot.com/2022/04/super-windows-como-optimizar-y-acelerar.html" target="_blank">Parte 2: Opciones de energía, personalización, pantalla, CPU, memoria, reconocimiento facial, asistencia de Windows, diagnóstico y notificaciones</a></li><li><a href="https://rafinguer.blogspot.com/2022/04/super-windows-como-optimizar-y-acelerar_14.html" target="_blank">Parte 3: Opciones para juegos, gráficos, privacidad, seguridad, Windows Defender, red, discos, almacenamiento, visor de eventos y puntos de restauración</a></li><li>Parte 4: </li></ul><p></p></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-12064326411171295072021-03-11T16:57:00.001+01:002021-03-11T16:57:18.542+01:00Idempotencia de producer y consumer en Kafka (exactly-once semantics)<p> <b>Kafka</b> trabaja muy bien procesando colas de eventos de forma asíncrona, y es muy eficiente gracias al uso de <b><i>clusters</i></b> y <b><i>brokers</i></b>, por lo que la alta disponibilidad está (casi) asegurada.</p><p>Sin embargo, existen algunas casuísticas por la cuales el flujo de mensajes podría fallar, y eso es imperdonable en un sistema crítico de alto estrés, en el que cada mensaje cuenta. </p><p><b>Nota:</b> <i>La primera parte del artículo expone los problemas y el planteamiento desde el punto de vista teórico. La segunda parte se abordará un ejemplo usando <b>Java</b> y la librería <b>kafka-clients</b>. </i></p><p><br /></p><h2 style="text-align: left;">Problemas</h2><h3 style="text-align: left;">El orden de los mensajes</h3><p>Cuando se envían multitud de mensajes, <b>Kafka</b> va a optimizar la eficiencia de tiempos y el rendimiento. Para ello, balancea la carga de las particiones, enviando cada mensaje a una partición que tenga menos carga de trabajo. Cada partición se ejecuta de forma asíncrona y en paralelo, por lo que el orden natural de los mensajes se diluye, y unos mensajes se ejecutan antes o después que otros, desde el punto de vista del orden.</p><p>En un escenario en que el orden en que se procesen los mensajes no sea relevante, esta es una solución óptima. En un flujo de <b><i>logs</i></b> se podría incluir el <b><i>timestamp</i></b> de origen para poder ordenar posteriormente la secuencia de estos <b><i>logs</i></b>.</p><p>Pero cuando trabajamos en una arquitectura <b>EDA</b> (<b>Event Driven Architecture</b>), el orden de la secuencia de mensajes es primordial, de cara a mantener correctamente el <b>Event-Sourcing</b>, y registrar correctamente la realidad. Este orden es clave para poder mantener y regenerar el estado de los agregados y de las entidades en caso de pérdida.</p><p>Para solucionar este problema, hemos de especificar, de forma explícita, una clave (<b><i>key</i></b> o <b><i>ID</i></b>) a los mensajes. Esto afecta a los mensajes referidos a una entidad en concreto. Por ejemplo, si enviamos mensajes sobre operaciones bancarias, la clave podría ser el número de cuenta bancaria o/y el número de tarjeta de crédito. Con esta clave, <b>Kafka</b> dirige todos los mensajes con la misma clave, siempre a la misma partición, con lo que la secuencia, en principio se mantendría en orden.</p><p>Pero puede ocurrir que, si hay una gran carga de trabajo en la red u ocurre algún problema transitorio, un mensaje no se pueda guardar en ese momento por un <i><b>timeout</b></i>. Para no perderlo, la propiedad <b><span style="font-family: courier;">"retries"</span></b> permite reintentar especificar el número de reintentos para guardar un mensaje fallido más adelante. Por defecto, <b>Kafka</b> lo establece en un valor de 2147483647, por lo que no hay problema si no lo configuramos.</p><p>Pero, por otra parte, <b>Kafka</b> establece un número máximo de peticiones al mismo tiempo, por lo que, si uno de los mensajes falla, aunque luego lo reintente, las otras peticiones procesarán los siguientes mensajes. Cuando en el siguiente reintento se guarde el mensaje que falló, al hacerlo lo hará después de n siguientes mensajes, con lo que el orden se rompe.</p><p>Para solucionar esto podemos restringir el número de peticiones concurrentes mediante la propiedad <b><span style="font-family: courier;">"max.in.flight.requests.per.connection"</span></b>. Por defecto, <b>Kafka</b> establece este valor a 5 conexiones, por lo que, para asegurar el orden en caso de un fallo puntual en algún mensaje, estableceremos este valor a 1. </p><p>Lo anterior asegurará el orden de los mensajes, pero la eficacia tiene el coste del rendimiento, el cual disminuye dependiendo del escenario y de la carga. No obstante, esta bajada de rendimiento no es crítica ni demasiado relevante.</p><p><br /></p><h3 style="text-align: left;">La idempotencia</h3><p>La <b>idempotencia</b> se refiere a la característica de que un mensaje <b>siempre se entrega</b>, y éste se entrega <b>exactamente una vez</b>. Es decir, <b>la idempotencia garantiza la consistencia de datos sin duplicidad</b>.</p><p>Suena obvio, pero en un sistema distribuido esta característica es la más compleja de cumplir. Vamos a tratar de explicarlo en detalle y con claridad.</p><p><br /></p><h4 style="text-align: left;">¿Cómo asegura Kafka la entrega de un mensaje?</h4><p>El flujo de entrega de un mensaje en <b>Kafka</b>, por parte de un <b><i>producer</i></b> (productor o emisor de mensajes), se resume en 3 pasos:</p><p></p><ul style="text-align: left;"><li>El producer envía el mensaje al <i><b>broker</b></i> de <b>Kafka</b></li><li>El <i><b>broker</b></i> guarda el mensaje en el siguiente <i><b>offset</b></i> en la partición correspondiente</li><li>El <i><b>broker</b></i> retorna un <i><b>ack</b></i> (<i>acknwoledgement</i> o reconocimiento) con valor 1, confirmando al <i><b>producer</b></i> de que el mensaje se entregó correctamente. </li></ul><p></p><p> Este flujo se representa fácilmente en el siguiente esquema:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYWHJV9qceHhWddwYL17QL5lht9aJcA1QCLeHk9SC7sTSz4tj3ywspnB2z_qV210fN7GXyGAHRHcz96BO4Cu7qE2LI61DXkne_N22xt-kud8jA8S_IGr2ttsT0tEflVBg4XUb-/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="179" data-original-width="1015" height="112" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYWHJV9qceHhWddwYL17QL5lht9aJcA1QCLeHk9SC7sTSz4tj3ywspnB2z_qV210fN7GXyGAHRHcz96BO4Cu7qE2LI61DXkne_N22xt-kud8jA8S_IGr2ttsT0tEflVBg4XUb-/w640-h112/image.png" width="640" /></a></div><p>Conociendo este flujo, surgen cuatro casuísticas o semánticas.</p><p><br /></p><h4 style="text-align: left;">Semántica "no-guarantee" (sin garantía)</h4><p>El mensaje se puede procesar una vez, varias veces o ninguna. Este escenario no viene establecido por defecto en <b>Kafka</b>, pues no es habitual. </p><p><br /></p><h4 style="text-align: left;">Semántica "at-least-once" (al menos una vez)</h4><p>En este escenario, si se produce algún problema en la entrega del mensaje, el productor realizará reintentos hasta conseguir que la entrega esté confirmada. </p><p>Aparentemente, esta solución suena bien y puede ser correcta para la mayoría de aplicaciones. Pero existe una casuística que puede generar un problema para conseguir la <b>idempotencia</b>. </p><p>Si el <i><b>broker</b></i> guarda correctamente el mensaje en el <i><b>offset</b></i>, pero en el momento de retornar el <i><b>ack</b></i> al <i><b>producer</b></i> se produce alguna incidencia transitoria, el <b><i>producer</i></b> no tendrá la confirmación de entrega del mensaje, aunque en realidad el <i><b>broker</b></i> lo haya guardado. El <i><b>producer</b></i> reintentará enviar el mensaje nuevamente tantas veces como sea necesario hasta que obtenga el <i><b>ack</b></i> de confirmación.</p><p>Este escenario asegura que, al menos una vez, el mensaje haya sido enviado con éxito, pero también puede generar mensajes duplicados en el <b style="font-style: italic;">offset </b>de la partición.</p><p>El siguiente diagrama ilustra esta casuística:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFMzqfGgZ4bJZuIIWpZsjak-ASpqy5TFgc591qyPPWgjvOXNYbddvYCC7RagwUZ7wA9Aw35sYok0dg402gyoPqIzsl2Fh1SsOXYgNGG_4aIXpqji_e0ELOTs2Viy8HFZSHg9mM/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="376" data-original-width="1015" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFMzqfGgZ4bJZuIIWpZsjak-ASpqy5TFgc591qyPPWgjvOXNYbddvYCC7RagwUZ7wA9Aw35sYok0dg402gyoPqIzsl2Fh1SsOXYgNGG_4aIXpqji_e0ELOTs2Viy8HFZSHg9mM/w640-h238/image.png" width="640" /></a></div><p></p><p></p><div><br /></div><p></p><h4 style="text-align: left;">Semántica "at-most-once" (como máximo una vez)</h4><p>El <b><i>offset</i></b> es comprometido (<b><i>committed</i></b>) tan pronto como el lote de mensajes llegue al broker. Si bien este escenario evita las duplicidades, si algo fue mal en el envío, el mensaje se perderá y no podrá ser leído. </p><p>Suele usarse para un enfoque <b><i>fire-and-forget</i></b> (dispara y olvídate), es decir, se envía el mensaje a <b>Kafka</b> sin reintentos, ignorando cualquier respuesta desde el <i><b>broker</b></i>.</p><p>Es recomendable guardar primero el progreso y los datos antes de enviar el mensaje a <b>Kafka</b>, </p><p><br /></p><h4 style="text-align: left;">Semántica "exactly-once" (exactamente una vez)</h4><p>En este escenario, es necesario asegurar que el mensaje sea enviado a <b>Kafka</b> sin pérdida ni duplicidades. Es recomendable que el envío de mensajes se realice dentro de una transacción, a fin de asegurar la llegada de los mensajes, su secuencia y la unicidad de los mensajes, para que el consumidor de <b>Kafka</b> pueda operar correctamente con los <b><i>offsets</i></b>. <br /></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimIgSwJloM_qHo9AGerBuB6MlV0Z3rSPdf1Jnc6a42nTdHPWu4iRzI-hfqsZY5e_MyPe17fAnn-2mkHgBp5Q3qNkmBiejU_5k1AhRcNSzyx-UTbRaA92fmi15VGOfTnKyTQBfG/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="115" data-original-width="700" height="106" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimIgSwJloM_qHo9AGerBuB6MlV0Z3rSPdf1Jnc6a42nTdHPWu4iRzI-hfqsZY5e_MyPe17fAnn-2mkHgBp5Q3qNkmBiejU_5k1AhRcNSzyx-UTbRaA92fmi15VGOfTnKyTQBfG/w640-h106/image.png" width="640" /></a></div><br /><br /><p></p><h2 style="text-align: left;">La idempotencia en el producer</h2><h3 style="text-align: left;">¿Cómo conseguir la idempotencia en el producer?</h3><p style="text-align: left;">Para que se cumpla la <b>idempotencia</b> en el <b><i>producer</i></b>, será tan simple como configurar las siguientes propiedades:</p><p style="text-align: left;"></p><ul style="text-align: left;"><li><b><span style="font-family: courier;">enable.idempotence=true</span></b></li><li><b><span style="font-family: courier;">acks=all</span></b></li><li><b><span style="font-family: courier;">retries>0</span></b></li><li><b><span style="font-family: courier;">max.in.flight.requests.per.connection<=5</span></b></li></ul><p></p><p style="text-align: left;">Con la configuración anterior, ya tenemos nuestro <b><i>producer</i></b> listo para trabajar bajo la semántica de la <b>idempotencia</b>.</p><p style="text-align: left;">Pero si queremos que nuestro <i><b>consumer</b></i> también trabaje de forma <b><i>idempotente</i></b>, debemos ayudarle desde el <b><i>producer</i></b>. </p><p style="text-align: left;">Tal y como lo hemos dejado ahora, el <b><i>consumer</i></b> debería añadir un esfuerzo extra en trabajar en el control y gestión de los <b><i>offsets</i></b> de forma manual para conseguir la <b>idempotencia</b>.</p><p style="text-align: left;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcEdDi8wML1QftcDCFU6noL2Ut5V_Ie51EQ4zw4wOa7PIFCde6oJN1F7SqgYoh0s7t-AsM3SacH2SeoEmZXgR0MZl30HvMMXAjGfmIsx0UTuE2l0z11uc2-2aMumVPVhiYTwl4/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="115" data-original-width="700" height="106" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcEdDi8wML1QftcDCFU6noL2Ut5V_Ie51EQ4zw4wOa7PIFCde6oJN1F7SqgYoh0s7t-AsM3SacH2SeoEmZXgR0MZl30HvMMXAjGfmIsx0UTuE2l0z11uc2-2aMumVPVhiYTwl4/w640-h106/image.png" width="640" /></a></div><br />Para evitar este trabajo, desde el <b><i>producer</i></b> vamos realizar toda la operativa de envíos atómicos de mensajes dentro de una transacción. Para que esta transacción atómica sea más efectiva, definiremos la siguiente propiedad:<p></p><p style="text-align: left;"></p><ul style="text-align: left;"><li><b><span style="font-family: courier;">transactional.id=<id_transaccion></span></b></li></ul><p></p><p style="text-align: left;">Esta propiedad define una parte de la clave que utilizará el algoritmo de transacción para genera el <i><b>id</b></i> de la transacción junto a la secuencia.</p><p style="text-align: left;">La transacción asegurará que todos los mensajes de la transacción sean enviados correctamente, definiendo la secuencia y el <b><i>offset</i></b> preparado para el consumidor. </p><p style="text-align: left;">De forma similar a una base de datos, una transacción prepara y ejecuta múltiples operaciones de escritura. En el caso de que ocurra algún problema, no se generan cambios en el offset y se informa del problema al <i><b>producer</b></i>, para que pueda decidir si volver a intentar la transacción o realizar alguna otra operación. Por tanto, si todo es correcto, la entrega los mensajes está asegurada sin incoherencias. Además, por parte del <b><i>consumer</i></b> podemos especificar que lea del <b><i>offset</i></b> solamente los mensajes una vez finalizada (y asegurada) la transacción, evitando leer mensajes aún en tránsito.</p><p style="text-align: left;"><br /><br /></p><h3 style="text-align: left;">Planteamiento del ejemplo</h3><p>Para el ejemplo, usaremos <b>Java</b> y la librería <b>kafka-clients</b>. Para configurar el <b><span style="font-family: courier;">pom.xml </span></b>de <b>Maven</b>, añadiremos las siguientes dependencias:</p><p><span style="font-family: courier;"><dependencies></span></p><p><span style="font-family: courier;"> <dependency></span></p><p><span style="font-family: courier;"> <groupId><org.apache.kafka/groupId></span></p><p><span style="font-family: courier;"> <artifactId>kafka-clients</artifactId></span></p><p><span style="font-family: courier;"> <version>2.3.0</version></span></p><p><span style="font-family: courier;"> </dependency></span></p><p><span style="font-family: courier;"><br class="Apple-interchange-newline" /> <dependency></span></p><p><span style="font-family: courier;"> <groupId>org.slf4j</groupId></span></p><p><span style="font-family: courier;"> <artifactId>slf4j-simple</artifactId></span></p><p><span style="font-family: courier;"> <version>1.6.1</version></span></p><p><span style="font-family: courier;"> </dependency></span></p><p><span style="font-family: courier;"></dependencies></span></p><p><br /></p><p>En este ejemplo vamos a simular el envío masivo de eventos (mensajes) de varios sensores de temperatura de un motor crítico (por ejemplo, el de un avión o el de un coche de Fórmula 1). Esta simulación enviará mil eventos, eligiendo aleatoriamente un determinado sensor (de entre 10 posibles), con una temperatura aleatoria entre 100 y 300 grados centígrados.</p><p><br /></p><h3 style="text-align: left;">Código del producer</h3><p>El siguiente código pone en práctica los conceptos vistos anteriormente. </p><p><b>Nota:</b> <i>Antes de ejecutarlo, hemos de ejecutar primero el <b>consumer</b>, para que éste escuche los mensajes que genere el <b>producer</b>.</i></p><p><br /></p><p><span style="font-family: courier;">import java.text.SimpleDateFormat;</span></p><p><span style="font-family: courier;">import java.util.Date;</span></p><p><span style="font-family: courier;">import java.util.Properties;</span></p><p><span style="font-family: courier;">import java.util.Random;</span></p><p><span style="font-family: courier;">import java.util.TimeZone;</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;">import org.apache.kafka.clients.producer.KafkaProducer;</span></p><p><span style="font-family: courier;">import org.apache.kafka.clients.producer.Producer;</span></p><p><span style="font-family: courier;">import org.apache.kafka.clients.producer.ProducerRecord;</span></p><p><span style="font-family: courier;">import org.slf4j.Logger;</span></p><p><span style="font-family: courier;">import org.slf4j.LoggerFactory;</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;">/**</span></p><p><span style="font-family: courier;"> * IdempotentProducer example</span></p><p><span style="font-family: courier;"> * @author: Rafael Hernamperez</span></p><p><span style="font-family: courier;"> *</span></p><p><span style="font-family: courier;"> */</span></p><p><span style="font-family: courier;">public class IdempotentProducer {</span></p><p><span style="font-family: courier;"> private static final int numberOfSensors = 10;</span></p><p><span style="font-family: courier;"> private static final int numberOfEvents = 1000;</span></p><p><span style="font-family: courier;"> private static final String eventTopic = "temperature-changed";</span></p><p><span style="font-family: courier;"> private static Logger log = LoggerFactory.getLogger(IdempotentProducer.class) {</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> public static void main(String[] args) {</span></p><p><span style="font-family: courier;"> Random rand = new Random();</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Producer properties</span></p><p><span style="font-family: courier;"> Properties props = new Properties();</span></p><p><span style="font-family: courier;"> props.put("bootstrap.servers", "localhost:9092");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("acks", "all");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("linger.ms", "10");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("retries", "50");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("max.in.flight.requests.per.connection", "1");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("enable.idempotence", "true");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("transacional.id", "temp-changed");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("key.serializer", "org.apache.kafka.common.serialization-StringSerializer");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("value.serializer", "org.apache.kafka.common.serializztion-StringSerializer");</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> try (Producer<Sring, String> producer = new KafkaProducer<>(props)) {</span></p><p><span style="font-family: courier;"> try {</span></p><p><span style="font-family: courier;"> // Start transaction</span></p><p><span style="font-family: courier;"> producer.initTransactions();</span></p><p><span style="font-family: courier;"> producer.beginTransaction();</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Generate messages</span></p><p><span style="font-family: courier;"> for (int event = 0; event < numberOfEvents; event++) {</span></p><p><span style="font-family: courier;"> int sensor = rand.nextInt(numberOfSensors);</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Temperature simulation (from 100º to 300º)</span></p><p><span style="font-family: courier;"> int intTemp = 100 + rand.nextInt(200);</span></p><p><span style="font-family: courier;"> double decTemp = rand.nextDouble() + intTemp;</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Current timestamp in ISO 8601 format</span></p><p><span style="font-family: courier;"> Date date = new Date(System.currentTimeMillis());</span></p><p><span style="font-family: courier;"> SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");</span></p><p><span style="font-family: courier;"> sdf.setTimeZone(TimeZone.getTimeZone("CET"));</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Compose message in CSV format: datetime;sensordId;temperature</span></p><p><span style="font-family: courier;"> String eventValue = String.format("%s;%d;%.1f", sdf.format(date), sensor, decTemp);</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Compose the key using the sensorId</span></p><p><span style="font-family: courier;"> String keyEvent = String.format("tempSensor-%s", sensor);</span></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;"> // Send the event (message)</span></p><p><span style="font-family: courier;"> producer.send(new ProducerRecord<String, String>(eventTopic, keyEvent, valueEvent));</span></p><p><span style="font-family: courier;"> logInfo("Event #" + event + " sent: " + valueEvent);</span></p><p><span style="font-family: courier;"> } // for</span></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;"> // Commit transaction</span></p><p><span style="font-family: courier;"> producer.commitTransaction();</span></p><p><span style="font-family: courier;"> } catch (Exception e) {</span></p><p><span style="font-family: courier;"> log.error("Error in transaction: " + e.getMessage());</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Abort Transaction</span></p><p><span style="font-family: courier;"> producer.abortTransaction();</span></p><p><span style="font-family: courier;"> }</span></p><p><span style="font-family: courier;"> } catch (Exception e) {</span></p><p><span style="font-family: courier;"> log.error("Error sending event: " + e.getMessage());</span></p><p><span style="font-family: courier;"> }</span></p><p><span style="font-family: courier;"> } // main()</span></p><p><span style="font-family: courier;">} // class</span></p><p><br /></p><h2>La idempotencia en el consumer</h2><h3>¿Cómo conseguir la idempotencia en el consumer?</h3><p>Una vez resuelta la <b>idempotencia</b> en el <b><i>producer</i></b>, tal y como hemos desarrollado anteriormente, la parte de la <b>idempotencia</b> en el lado del <b><i>consumer</i></b> es mucho más sencilla.</p><p>Para ello, vamos a establecer las siguientes propiedades clave:</p><p></p><ul style="text-align: left;"><li><span style="font-family: courier;"><b>isolation.level="read_committed"</b></span></li></ul><div><br /></div><div>El nivel de aislamiento establecido como <span style="font-family: courier;"><b>"read_committed"</b></span> indica que el consumer solamente aborde los mensajes cuyo <b><i>offset</i></b> esté comprometido, es decir, que tenga la marca <i><b>committed</b></i>. Esto solamente ocurrirá cuando la transacción haya terminado exitosamente, por lo que solo aplica a los mensajes de la transacción.</div><div><br /></div><div>Además, la transacción habrá generado la secuencia correcta de los mensajes para que el <b><i>consumer</i></b> los procese en el orden correspondiente.</div><p></p><p><br /></p><h3>Planteamiento del código</h3><p>Para el lado del <i><b>consumer</b></i>, vamos a generar una aplicación multihilo que lance en paralelo varios consumers que estén escuchando al mismo tiempo y procesen los mensajes.</p><p>Para ello, habrá dos archivos de código:</p><p></p><ul style="text-align: left;"><li><span style="font-family: courier;"><b>ThreadConsumer.java: </b></span>Contiene el código de cada hilo <i><b>consumer</b></i>.</li><li><b><span style="font-family: courier;">IdempotentConsumer.java:</span></b> Aplicación principal. Prepara el entorno multihilo, instancia cada hilo y lanza los <b><i>consumers</i></b>.</li></ul><p></p><p><br /></p><h3 style="text-align: left;">Código del hilo para consumer</h3><p>El siguiente código corresponde a cada hilo de <i><b>consumer</b></i>. En un entorno multihilo, habrá varios procesos ejecutándose al mismo tiempo. Este es el código de cada uno de estos hilos.</p><p><br /></p><p><span style="font-family: courier;">import java.time.Duration;</span></p><p><span style="font-family: courier;">import java.util.Arrays;</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;">import org.apache.kafka.clients.consumer.ConsumerRecord;</span></p><p><span style="font-family: courier;">import org.apache.kafka.clients.consumer.ConsumerRecords;</span></p><p><span style="font-family: courier;">import org.apache.kafka.clients.consumer.KafkaConsumer;</span></p><p><span style="font-family: courier;">import org.apache.kafka.commons.errors.WakeupException;</span></p><p><span style="font-family: courier;">import org.slf4j.Logger;</span></p><p><span style="font-family: courier;">import org.slf4j.LoggerFactory;</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;">/**</span></p><p><span style="font-family: courier;"> * ThreadConsumer </span></p><p><span style="font-family: courier;"> * @author: Rafael Hernamperez</span></p><p><span style="font-family: courier;"> *</span></p><p><span style="font-family: courier;"> */</span></p><p><span style="font-family: courier;">public class ThreadConsumer extends Thread {</span></p><p><span style="font-family: courier;"> private final KafkaConsumer<String, String> consumer;</span></p><p><span style="font-family: courier;"> private final String eventTopic = "temperature-changed";</span></p><p><span style="font-family: courier;"> private boolean closed = false;</span></p><p><span style="font-family: courier;"> private Logger log = LoggerFactory.getLogger(ThreadConsumer.class);</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Constructor</span></p><p><span style="font-family: courier;"> public ThreadConsumer(KafkaConsumer<String, String> consumer) {</span></p><p><span style="font-family: courier;"> this.consumer = consumer;</span></p><p><span style="font-family: courier;"> }</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Main thread execution</span></p><p><span style="font-family: courier;"> @Override</span></p><p><span style="font-family: courier;"> public void run() {</span></p><p><span style="font-family: courier;"> consumer.subscribe(Arrays.asList(eventTopic));</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> try {</span></p><p><span style="font-family: courier;"> while(!closed) {</span></p><p><span style="font-family: courier;"> ConsumerRecords<String, String> events = consumer.poll(Duration.ofMillis(100));</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> for (ConsumerRecord<String, String> event : events) {</span></p><p><span style="font-family: courier;"> log.info("Partition={}, Offset={}, key={}, value={}",</span></p><p><span style="font-family: courier;"> event.partition(),</span></p><p><span style="font-family: courier;"> event.offset(),</span></p><p><span style="font-family: courier;"> event.key(),</span></p><p><span style="font-family: courier;"> event.value());</span></p><p><span style="font-family: courier;"> } // for</span></p><p><span style="font-family: courier;"> } // while</span></p><p><span style="font-family: courier;"> } catch(WakeupException Exception we) {</span></p><p><span style="font-family: courier;"> if (!closed) {</span></p><p><span style="font-family: courier;"> throw we;</span></p><p><span style="font-family: courier;"> }</span></p><p><span style="font-family: courier;"> } finally {</span></p><p><span style="font-family: courier;"> consumer.close();</span></p><p><span style="font-family: courier;"> }</span></p><p><span style="font-family: courier;"> } // run()</span></p><p><span style="font-family: courier;">} // class</span></p><p><br /></p><h3 style="text-align: left;">Código principal para el consumer</h3><p>El código principal del consumer se encargará de preparar un entorno multihilo, en el que varios <b><i>consumers</i></b> trabajarán al mismo tiempo para escuchar y leer los mensajes que genere el <b><i>producer</i></b>. Al crear un hilo, se le pasará un objeto de tipo <span style="font-family: courier;"><b>KafkaConsumer</b></span>, inicializado con las propiedades de ese <b><i>consumer</i></b>, las cuales ya están preparadas para su funcionamiento con una semántica <b><i>exactly-once</i></b>, lo que facilitará la <b>idempotencia</b>.</p><p><br /></p><p><span style="font-family: courier;">import java.util.Properties;</span></p><p><span style="font-family: courier;">import java.util.concurrent.ExecutorService;</span></p><p><span style="font-family: courier;">import java.util.concurrent.Executors;</span></p><p><span style="font-family: courier;">import org.apache.kafka.clients.consumer.KafkaConsumer;</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;">/**</span></p><p><span style="font-family: courier;"> * IdempotentConsumer example</span></p><p><span style="font-family: courier;"> * @author: Rafael Hernamperez</span></p><p><span style="font-family: courier;"> *</span></p><p><span style="font-family: courier;"> */</span></p><p><span style="font-family: courier;">public class IdempotentProducer {</span></p><p><span style="font-family: courier;"> public static final int numberOfConsumers = 5;</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> public static void main(String[] args) {</span></p><p><span style="font-family: courier;"> // Consumer properties</span></p><p><span style="font-family: courier;"> Properties props = new Properties();</span></p><p><span style="font-family: courier;"> props.put("bootstrap.servers", "localhost:9092");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("group.id", "temp-event-group");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("enable.auto.commit", "false");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("isolation.level", "read_committed");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");</span></p><p><span style="font-family: courier;"> </span><span style="font-family: courier;">props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> ExecutorService executyor = Executors.newFixedThreadPool(numberOfConsumers);</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Generate consumers in a multithread environment</span></p><p><span style="font-family: courier;"> for (int i=0; i<numberOfConsumer; i++) {</span></p><p><span style="font-family: courier;"> ThreadConsumer consumer = new ThreadConsumer(new KafkaConsumer<>(props));</span></p><p><span style="font-family: courier;"> executor.execute(consumer);</span></p><p><span style="font-family: courier;"> }</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> // Execution will alive until last thread is terminated</span></p><p><span style="font-family: courier;"> while(!executor.isTerminated());</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;"> } // main()</span></p><p><span style="font-family: courier;">} // class</span></p><p><br /></p><p><br /></p><h2 style="text-align: left;">Configuraciones clave</h2><p>A continuación se resumen las propiedades y valores clave para cada caso.</p><p><br /></p><h3 style="text-align: left;">Consumer</h3><p></p><ul style="text-align: left;"><li><b>No-guarantee:</b></li><ul><li><b><span style="font-family: courier;">enable.auto.commit = true</span></b></li><li><b><span style="font-family: courier;">auto.commit.interval.ms = <frecuencia_milisegundos></span></b></li></ul><li><b>At-least-once:</b></li><ul><li><span style="font-family: courier;"><b>enable.auto.commit = false</b></span></li><li>O <b><span style="font-family: courier;">enable.auto.commit=true </span></b>con <span style="font-family: courier;"><b>auto.commit.interval.ms</b></span> con valor muy alto.</li><li>Recomendado utilizar <b><span style="font-family: courier;">consumer.commitSync()</span></b> para controlar los <b><i>commits</i></b> en los <b><i>offset</i></b> de los mensajes.</li></ul><li><b>At-most-once:</b></li><ul><li><span style="font-family: courier;"><b>enable.auto.commit = true</b></span></li><li><span style="font-family: courier;"><b>auto.commit.interval.ms = <frecuencia_milisegundos></b></span></li><li>No usar el método <b><span style="font-family: courier;">consumer.commitSync()</span></b></li></ul><li><b>Exactly-once:</b></li><ul><li><span style="font-family: courier;"><b>enable.auto.commit = false</b></span></li><li><span style="font-family: courier;"><b>isolation.level = "read_committed"</b></span></li></ul></ul><div><br /></div><p></p><h3 style="text-align: left;">Producer</h3><p></p><ul style="text-align: left;"><li><b><span style="font-family: courier;">retries > 0</span></b></li><li><b><span style="font-family: courier;">acks = "all"</span></b></li><li><b><span style="font-family: courier;">max.in.flight.requests.per.connection <= 5</span></b></li><li><span style="font-family: courier;"><b>enable.idempotence = true</b></span></li><li><span style="font-family: courier;"><b>transacional.id = <clave_unica_transaccion></b></span></li></ul><p></p><p>Para facilitar la <b>idempotencia</b> real tanto en <i><b>producer</b></i> como en <i><b>consumer</b></i>, realizar el envío de mensajes dentro de una transacción.</p><p><br /></p><h2 style="text-align: left;">Enlaces de referencia</h2><p></p><ul style="text-align: left;"><li>Artículo <a href="https://medium.com/@shesh.soft/kafka-idempotent-producer-and-consumer-25c52402ceb9" target="_blank">"Kafka idempotent producer and consumer"</a></li><li>Artículo <a href="https://medium.com/techwasti/idempotent-kafka-consumer-442f9aec991e" target="_blank">"Kafka idempotent consumer"</a></li><li>Artículo <a href="https://medium.com/@andy.bryant/processing-guarantees-in-kafka-12dd2e30be0e" target="_blank">"Processing guarantees in Kafka"</a></li><li>Artículo <a href="https://www.baeldung.com/kafka-exactly-once" target="_blank">"Exactly-once processing in Kafka with Java"</a></li><li>Artículo <a href="https://dzone.com/articles/exactly-once-semantics-with-apache-kafka-1" target="_blank">"Exactly-once semantics with Apache Kafka"</a></li><li>Artículo <a href="https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how-apache-kafka-does-it/" target="_blank">"Exactly-once semantics are possible: Here's how Apache Kafka does it"</a></li><li>Artículo <a href="https://dzone.com/articles/kafka-clients-at-most-once-at-least-once-exactly-o" target="_blank">"Kafka clients (At-Most-Once, At-Least-Once, Exactly-Once)"</a></li></ul><p></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><br /><br /><p></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-26525972073205673442021-03-08T17:22:00.002+01:002022-03-01T15:30:02.290+01:00Simple Event Processing (Procesamiento Simple de Eventos) y Kafka<p> En una Arquitectura Orientada a Eventos (EDA ó Event Driven Architecture) existen varios enfoques de eventos, dependiendo del tipo de procesamiento.</p><p>En este post analizaremos el tipo de procesamiento más simple: SEP (Simple Event Processing)</p><p><br /></p><h2 style="text-align: left;">¿Qué es un Procesamiento Simple de Eventos?</h2><p>En SEP, cuando se produce un evento, se enruta inmediatamente para realizar una acción posterior, sin aplicar restricciones ni consideraciones. El flujo de trabajo se ejecuta en tiempo real, reduciendo así la latencia entre el momento en que se produce el evento y la acción resultante.</p><p>Un escenario habitual de un patrón SEP es en escenarios donde se producen cambios medibles, tales como un cambio de temperatura, de presión, de humedad, de CO2, etc, en un sensor.</p><p>Pero no debemos limitar un SEP a un ambiente IoT o de sensores, pues también se puede aplicar a diferentes entornos. Por ejemplo, un evento simple se podría producir en un complejo sistema, en donde, al realizar un pedido, cuando se accede al inventario para realizar la reserva del pedido, si supera cierto umbral, se puede lanzar un evento de inventario bajo para el producto que se ha adquirido. De esta forma, dicho evento se propaga como alerta o/y a un buzón para que el responsable de compras adquiera una nueva remesa de productos.</p><p>La clave para entender un SEP, es que procesa un único evento a la vez, sin tener en cuenta otros eventos. En este aspecto, SEP funciona como un "flujo de trabajo humano" o "una cosa a la vez".</p><p>Este tipo de procesamiento se ha tratado típicamente mediante un servicio de mensajería, como AMQ, RabbitMQ o JMS (Java Messaging Service). Los servicios de mensajería publican y consumen una única vez el mensaje, es decir, que cuando el mensaje es leído y procesado por un consumidor, el mensaje desaparece.</p><p>Con Apache Kafka o con Apache Pulsar elevan el concepto de mensajería a otro nivel, utilizando un broker en lugar de una cola de mensajes. Esto significa que un mensaje puede estar publicado durante un tiempo largo y ser consumido por uno o varios consumidores, sin necesidad de eliminarlo del pool de mensajes.</p><p><br /></p><p><br /></p><p><br /></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-75770509788815295222021-03-07T22:46:00.075+01:002021-03-12T07:38:56.203+01:00Las 21 mejores tipografías para programar<div>Cuando programas, ¿te aburre la tipografía por defecto de tu IDE o de tu editor de textos?</div><div><br /></div><div>A continuación comparto una selección de 21 tipografías que te sacarán de la monotonía y te harán disfrutar de la programación.</div><div><br /></div><div>Esta selección es particular, no un ranking universalmente aceptado. Te invito a dejar un comentario con tu opinión y a aportar otras tipografías que te gusten para esta selección.</div><div><br /></div><div><br /></div><h2 style="text-align: left;">CP Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgkOIIZALIqru8misBzdMaetjoBlOlUvkJdPct08EXa3Z1qru0lK1MGlk4SUWz9YjFxTmRALAUQxOF2cX4xI9w6-vZGCW3HhtuAEUMSr6miKxJew9EHaf-GibFS8HxjVLMJHXy/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="123" data-original-width="725" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgkOIIZALIqru8misBzdMaetjoBlOlUvkJdPct08EXa3Z1qru0lK1MGlk4SUWz9YjFxTmRALAUQxOF2cX4xI9w6-vZGCW3HhtuAEUMSr6miKxJew9EHaf-GibFS8HxjVLMJHXy/w640-h108/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://github.com/chrissimpkins/codeface/tree/master/fonts/cp-mono">https://github.com/chrissimpkins/codeface/tree/master/fonts/cp-mono</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Cutive Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaaJv8wkx9CD4ixm9BnnBo5yNGfDFrPn1S4Un32Blh_o6i_b1_ZCdwJ1FmTFjr46fzsLPftvUheBCX-EQlS9v5CAtuJ6TeT0c_kRe4pK55E-pw5IGIFh3dSGxJMgYhHhDY3WlM/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="136" data-original-width="1240" height="70" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaaJv8wkx9CD4ixm9BnnBo5yNGfDFrPn1S4Un32Blh_o6i_b1_ZCdwJ1FmTFjr46fzsLPftvUheBCX-EQlS9v5CAtuJ6TeT0c_kRe4pK55E-pw5IGIFh3dSGxJMgYhHhDY3WlM/w640-h70/image.png" width="640" /></a></div><br /><br /></div><div><b>Descarga:</b> <a href="https://fonts.google.com/specimen/Cutive+Mono">https://fonts.google.com/specimen/Cutive+Mono</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Exo</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4rCBE0srnFiLfHykFvol6b1L6Mq6XGX75cxr4oa8EqP57QLo6rlJ-G3lnlkit5IVZ7JtqmI3GVFFv-fJqT20bDIJOArK9et_TDHijpOML0tBjEd0DqtxEKtW2oMiK2fbkdgkv/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="481" data-original-width="960" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4rCBE0srnFiLfHykFvol6b1L6Mq6XGX75cxr4oa8EqP57QLo6rlJ-G3lnlkit5IVZ7JtqmI3GVFFv-fJqT20bDIJOArK9et_TDHijpOML0tBjEd0DqtxEKtW2oMiK2fbkdgkv/w640-h320/image.png" width="640" /></a></div><br /><br /></div><div><b>Descarga:</b> <a href="https://fonts.google.com/specimen/Exo">https://fonts.google.com/specimen/Exo</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Exo 2</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheGwZFJF6CNCITHecsp2ZqWCfXIt94yTAt6L1DESUFeFaAY9LmAgD0D4WTUtWCf4AmiNd20YHYRssueBEBg7c6tRKTCmYubu4zzgukt6yyzNxes_UiLNYhNpF5KmfH8IP4tDFH/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="465" data-original-width="773" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheGwZFJF6CNCITHecsp2ZqWCfXIt94yTAt6L1DESUFeFaAY9LmAgD0D4WTUtWCf4AmiNd20YHYRssueBEBg7c6tRKTCmYubu4zzgukt6yyzNxes_UiLNYhNpF5KmfH8IP4tDFH/w640-h384/image.png" width="640" /></a></div><br /><br /></div><div><b>Descarga:</b> <a href="https://fonts.google.com/specimen/Exo+2">https://fonts.google.com/specimen/Exo+2</a></div><div><br /></div><h2 style="text-align: left;">Fantasque Sans Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuOCURKBksp6M3lideejgDkEve70ixKXiQX6vFD962IXZ__329XWKubz2N8gOLlXjEv1REpZ8okfsGp-SzF4riE_YbN3YRRzyYismjX2-QNV23FvqkdPoRs0_rTceAzCxYD5UL/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="749" data-original-width="755" height="635" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuOCURKBksp6M3lideejgDkEve70ixKXiQX6vFD962IXZ__329XWKubz2N8gOLlXjEv1REpZ8okfsGp-SzF4riE_YbN3YRRzyYismjX2-QNV23FvqkdPoRs0_rTceAzCxYD5UL/w640-h635/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://www.fontsquirrel.com/fonts/fantasque-sans-mono">https://www.fontsquirrel.com/fonts/fantasque-sans-mono</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">JetBrains Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp3vGP8wYSQ6zBm6Mnry1b_wzum3ohvczgkesMyuaS-ri1UFFBzq5Fx0rDtthA1qqnrjhOjXx35iD3Qvt7UVCZl8iQyNEqhU8Ht4HnHTLQ97y7mEzPm1YDTfG9ZE9ZWDsbs-hm/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="803" data-original-width="762" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp3vGP8wYSQ6zBm6Mnry1b_wzum3ohvczgkesMyuaS-ri1UFFBzq5Fx0rDtthA1qqnrjhOjXx35iD3Qvt7UVCZl8iQyNEqhU8Ht4HnHTLQ97y7mEzPm1YDTfG9ZE9ZWDsbs-hm/w608-h640/image.png" width="608" /></a></div><br /><b>Descarga:</b> <a href="https://www.fontsquirrel.com/fonts/jetbrains-mono">https://www.fontsquirrel.com/fonts/jetbrains-mono</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Jura</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTsXykoszgMLF5OwqKGnz6m0NwR8m6rhlQ7F2nqQFk-pB6l48PKh3FZULascgxcr-17DFzi8jOoJ0owENcCNF9QKRdW7QKy-XmkpKwGJyUGxXRJqQ17yi7tDE3X8d-QBWbqNIz/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="458" data-original-width="1144" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTsXykoszgMLF5OwqKGnz6m0NwR8m6rhlQ7F2nqQFk-pB6l48PKh3FZULascgxcr-17DFzi8jOoJ0owENcCNF9QKRdW7QKy-XmkpKwGJyUGxXRJqQ17yi7tDE3X8d-QBWbqNIz/w640-h256/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://fonts.google.com/specimen/Jura">https://fonts.google.com/specimen/Jura</a></div><div><br /></div><h2 style="text-align: left;">Lekton</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC2oxBJFmP8gEQh6ETi2DfNnIMSY2rgDa-kgNe4tcF2qhDlmR8Z429EFNoPRGr8HO-ePpkro-Sz5UHz7Tq6eLyI7Rxn-04qXBIQBtgH195QmREWDH9gyRc7PlzT5s2IAwRQn2N/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="335" data-original-width="874" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC2oxBJFmP8gEQh6ETi2DfNnIMSY2rgDa-kgNe4tcF2qhDlmR8Z429EFNoPRGr8HO-ePpkro-Sz5UHz7Tq6eLyI7Rxn-04qXBIQBtgH195QmREWDH9gyRc7PlzT5s2IAwRQn2N/w640-h246/image.png" width="640" /></a></div><br /><br /></div><div><b>Descarga:</b> <a href="https://fonts.google.com/specimen/Lekton">https://fonts.google.com/specimen/Lekton</a></div><div><br /></div><h2 style="text-align: left;">Menlo</h2><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRz_7u56sNZV90ZlacHct95YsvpYaopoCdL6Y0p3hyphenhyphen2Yn-z-KHCBLM8l4o5MfJiz9lO7h9A9tRxgtOAjS9HqyFSmJve2uO3ucSHY-xda3LA0IUQA1uIC4xwVIaUgysKSPnMjw/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="759" data-original-width="761" height="637" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRz_7u56sNZV90ZlacHct95YsvpYaopoCdL6Y0p3hyphenhyphen2Yn-z-KHCBLM8l4o5MfJiz9lO7h9A9tRxgtOAjS9HqyFSmJve2uO3ucSHY-xda3LA0IUQA1uIC4xwVIaUgysKSPnMjw/w640-h637/image.png" width="640" /></a></div><b><div><b><br /></b></div>Descarga:</b> <a href="https://www.cufonfonts.com/font/menlo">https://www.cufonfonts.com/font/menlo</a><br /><br /></div><div><br /></div><h2 style="text-align: left;">Monaco</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_f4w4Sd0uBcW68yllNQZWw4P6mhDGJYv9kDdLxrr-gTRoM64-QmZivV_h1emjpLYyKkmc1iUJQwv2sDhyBQ_yCQT9hiTqZsqLnHxHTaYinUHwdHQvowN9wtMVNNDhyphenhyphenQXEkN-g/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="773" data-original-width="750" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_f4w4Sd0uBcW68yllNQZWw4P6mhDGJYv9kDdLxrr-gTRoM64-QmZivV_h1emjpLYyKkmc1iUJQwv2sDhyBQ_yCQT9hiTqZsqLnHxHTaYinUHwdHQvowN9wtMVNNDhyphenhyphenQXEkN-g/w621-h640/image.png" width="621" /></a></div><br /><b>Descarga:</b> <a href="https://www.cufonfonts.com/font/monaco">https://www.cufonfonts.com/font/monaco</a></div><div><br /></div><div><h2>Monoid</h2><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4kp7phV6Y1eTKGmcQ_wunK9ZvHklRNy9kZhg4JlzFNdG-8tis3zvQ_Gx9twZvbyzvXGqIFP2Gozw1Ww-n1x8E-gVPH8GY2-Jo-4qTRnT4y63hgwQTX0CGiqpAiCewN5swThaz/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="762" data-original-width="764" height="637" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4kp7phV6Y1eTKGmcQ_wunK9ZvHklRNy9kZhg4JlzFNdG-8tis3zvQ_Gx9twZvbyzvXGqIFP2Gozw1Ww-n1x8E-gVPH8GY2-Jo-4qTRnT4y63hgwQTX0CGiqpAiCewN5swThaz/w640-h637/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://larsenwork.com/monoid/">https://larsenwork.com/monoid/</a></div><div><br /></div><h2>Mononoki</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqYak55Ft-jpKBjho2Ge3MKMFUe-SF6-uKpaU97VfSL0IFi7VmUFfhU3gSbZwccAf7BZLeXszSU-YyREns6IN1chCbUYnNNgbewIAGllnZzwX437UFOk_ugzB6cLeeb3taURQ7/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="442" data-original-width="681" height="416" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqYak55Ft-jpKBjho2Ge3MKMFUe-SF6-uKpaU97VfSL0IFi7VmUFfhU3gSbZwccAf7BZLeXszSU-YyREns6IN1chCbUYnNNgbewIAGllnZzwX437UFOk_ugzB6cLeeb3taURQ7/w640-h416/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://madmalik.github.io/mononoki/">https://madmalik.github.io/mononoki/</a><br /><div class="separator" style="clear: both; text-align: center;"><br /></div></div></div><h2 style="text-align: left;">Monolisa</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm8uFrQs_EBwKmm5RGXCXh94tmK6LebQSP1tVUgI2nGxWcwICq6EzMxezhx1cNf4GJgbHyRfbhYndq_e8tDdECeBFJRCKjhOlAOVyfs27DoIcSdg2LyQXBSt4quYtdDcUPV364/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="560" data-original-width="928" height="386" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm8uFrQs_EBwKmm5RGXCXh94tmK6LebQSP1tVUgI2nGxWcwICq6EzMxezhx1cNf4GJgbHyRfbhYndq_e8tDdECeBFJRCKjhOlAOVyfs27DoIcSdg2LyQXBSt4quYtdDcUPV364/w640-h386/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://www.monolisa.dev/">https://www.monolisa.dev/</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Monospace Typewriter</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha3yvNlCLCXut6PoHGtcalS85w1n-35B0yEeL7cBzY2xGQQYLHaMLwrxCkBfnnsKzjGxOj35JWlWkG9TRFc55SXCFY_tkMncOYOIuqruH-LPzFVJESimMtdZAeJo8Lcaisvaay/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="541" data-original-width="764" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha3yvNlCLCXut6PoHGtcalS85w1n-35B0yEeL7cBzY2xGQQYLHaMLwrxCkBfnnsKzjGxOj35JWlWkG9TRFc55SXCFY_tkMncOYOIuqruH-LPzFVJESimMtdZAeJo8Lcaisvaay/w640-h454/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://www.fontsquirrel.com/fonts/monospacetypewriter">https://www.fontsquirrel.com/fonts/monospacetypewriter</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Overpass Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEVB1VmvSEipOPMm45A0_brDXi3SwX4Nkp1znwXyECVVsbDd4AasPfNobF6CP3ppU7w14Fz9v5M2cgKxzMyZTHz5H6c4ukQXtsMLAXISGEYHVdJmhVvrNv-pl3vHIEXtEWr0FC/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="508" data-original-width="1021" height="318" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEVB1VmvSEipOPMm45A0_brDXi3SwX4Nkp1znwXyECVVsbDd4AasPfNobF6CP3ppU7w14Fz9v5M2cgKxzMyZTHz5H6c4ukQXtsMLAXISGEYHVdJmhVvrNv-pl3vHIEXtEWr0FC/w640-h318/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://www.1001fonts.com/overpass-mono-font.html">https://www.1001fonts.com/overpass-mono-font.html</a></div><div><br /></div><h2 style="text-align: left;">PT Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOuSFT7-jqY5DQF-k3YZby54aAFH4aY9IRi9nNm7Q7fCiBbD_v8SAqCYAZwPdaHmr-d3VkZEQ-6frkc9Q1FVCl8cDf22PZGdaM4eHEJuxnUZkesGIqFhHc5QSR9Tf4dnC2d2Qq/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="525" data-original-width="763" height="440" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOuSFT7-jqY5DQF-k3YZby54aAFH4aY9IRi9nNm7Q7fCiBbD_v8SAqCYAZwPdaHmr-d3VkZEQ-6frkc9Q1FVCl8cDf22PZGdaM4eHEJuxnUZkesGIqFhHc5QSR9Tf4dnC2d2Qq/w640-h440/image.png" width="640" /></a></div><b>Descarga:</b> <a href="https://www.fontsquirrel.com/fonts/pt-mono">https://www.fontsquirrel.com/fonts/pt-mono</a><br /><br /></div><h2 style="text-align: left;">Roboto Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9JpQlAg4aFrmzstF_Lr2NbpV7DBmcuHl1TaSR8zjSuOmgZTF2zmQb-XPRU7hOqTL-Sb92sSndhPrw1QYRlAiDDdlA_0xu9fVF-iIsZLVT6cVXscFyx0V3d98yo1LvtVjBwLHE/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="728" data-original-width="1477" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9JpQlAg4aFrmzstF_Lr2NbpV7DBmcuHl1TaSR8zjSuOmgZTF2zmQb-XPRU7hOqTL-Sb92sSndhPrw1QYRlAiDDdlA_0xu9fVF-iIsZLVT6cVXscFyx0V3d98yo1LvtVjBwLHE/w640-h316/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://fonts.google.com/specimen/Roboto+Mono?preview.text_type=custom">https://fonts.google.com/specimen/Roboto+Mono?preview.text_type=custom</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">SaxMono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-eKL2u-TlIhut0dNKsIJFzcD4VKkCwAWV_64EEOtCUG5TJv4t567d7YzzAU3QT4Ek9hz_BtDD-uFRI1WjJNt0XYwbHkYqN98MhdjJaXQzV-hkA247HVZucBRjUyvnidyy224h/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="538" data-original-width="758" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-eKL2u-TlIhut0dNKsIJFzcD4VKkCwAWV_64EEOtCUG5TJv4t567d7YzzAU3QT4Ek9hz_BtDD-uFRI1WjJNt0XYwbHkYqN98MhdjJaXQzV-hkA247HVZucBRjUyvnidyy224h/w640-h454/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://www.fontsquirrel.com/fonts/saxmono">https://www.fontsquirrel.com/fonts/saxmono</a></div><div><br /></div><h2 style="text-align: left;">SF Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ53xNzBOXU3uEds6NGGlFaLLXrUZxO_dWRm9SNCQ3aUUekex-17G6EYWjhMGXFa-MdEHq_N-1tB3nGeRvz8tPI4sNch5IM7zlpEtDmDtb3GUcNS2xumCfG4ZQITYRLWN8_5x6/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="763" data-original-width="761" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ53xNzBOXU3uEds6NGGlFaLLXrUZxO_dWRm9SNCQ3aUUekex-17G6EYWjhMGXFa-MdEHq_N-1tB3nGeRvz8tPI4sNch5IM7zlpEtDmDtb3GUcNS2xumCfG4ZQITYRLWN8_5x6/w637-h640/image.png" width="637" /></a></div><br /><b>Descarga:</b> <a href="https://www.cufonfonts.com/font/sf-mono">https://www.cufonfonts.com/font/sf-mono</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Skyhook Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhikPy0MZK2Mjxdqe0ZLLj8BehXxcnVuZR67bbAZkTpk5wkdrzWjbx71h1e34ZJ5bQaWQHz-5qy8A6m4t4uBnO9ArGjzATZ61P3d07oEhMTfqLq_qaFs19uyI2OWYnlBPShhfUI/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="590" data-original-width="885" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhikPy0MZK2Mjxdqe0ZLLj8BehXxcnVuZR67bbAZkTpk5wkdrzWjbx71h1e34ZJ5bQaWQHz-5qy8A6m4t4uBnO9ArGjzATZ61P3d07oEhMTfqLq_qaFs19uyI2OWYnlBPShhfUI/w640-h426/image.png" width="640" /></a></div><br /><b>Descarga:</b> <a href="https://www.fontshmonts.com/display-fonts/skyhook-mono/">https://www.fontshmonts.com/display-fonts/skyhook-mono/</a></div><div><br /></div><div><h2><span style="font-size: large;">Victor Mono</span></h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh34bVWti7VWW64UXaF-5cshw-zYwepYg7rcQ9JbUQKw-L2-ahiHkSVoFH4UWAfGetKnhphLD4tGaNvbxoa6oy9MxNKsjXWbm9BPl-wO_LIkEb577AsbWwaynOHLttpsZPWosc-/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="867" data-original-width="768" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh34bVWti7VWW64UXaF-5cshw-zYwepYg7rcQ9JbUQKw-L2-ahiHkSVoFH4UWAfGetKnhphLD4tGaNvbxoa6oy9MxNKsjXWbm9BPl-wO_LIkEb577AsbWwaynOHLttpsZPWosc-/w568-h640/image.png" width="568" /></a></div><br /><b>Descarga:</b> <a href="https://www.fontsquirrel.com/fonts/victor-mono">https://www.fontsquirrel.com/fonts/victor-mono</a></div><div><br /></div></div><div><br /></div><h1 style="text-align: left;">Tipografías extra</h1><div><br /></div><div>La lista anterior se quedó pequeña, por lo que se añaden nuevas tipografías.</div><div><br /></div><h2 style="text-align: left;">Anonymous Pro</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgMmajINoz0nefWikv9Uo7N0nXW7QAx410CcfKBIAOzjCEfZQf83khcPP3LZndJis4E22skxeIZXl4VOEDhhUY1L0V0oHENyM69Y3FkIqyPcptmuiPyBNkfqKFfUYrJ8CkGKCy/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="396" data-original-width="1108" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgMmajINoz0nefWikv9Uo7N0nXW7QAx410CcfKBIAOzjCEfZQf83khcPP3LZndJis4E22skxeIZXl4VOEDhhUY1L0V0oHENyM69Y3FkIqyPcptmuiPyBNkfqKFfUYrJ8CkGKCy/w640-h228/image.png" width="640" /></a></div><br /><b>Descarga: </b><a href="https://fonts.google.com/specimen/Anonymous+Pro">https://fonts.google.com/specimen/Anonymous+Pro</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Courier Prime Code</h2><div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTYKAky4eaSlUa5mIPrWBfMu6jR82kVE-cRNM80O69M992sQfGkZlZ_MtSkykhb32-zBxUhZB6JbjFm4o8oUO5utz5vBqB6MEOkHrDPyQeDffcHlyB0G8uCs3lkLCF-XFDcaQU/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="504" data-original-width="1019" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTYKAky4eaSlUa5mIPrWBfMu6jR82kVE-cRNM80O69M992sQfGkZlZ_MtSkykhb32-zBxUhZB6JbjFm4o8oUO5utz5vBqB6MEOkHrDPyQeDffcHlyB0G8uCs3lkLCF-XFDcaQU/w640-h316/image.png" width="640" /></a></div><br /></div><div style="text-align: left;"><b>Descarga:</b> <a href="https://www.1001fonts.com/courier-prime-code-font.html">https://www.1001fonts.com/courier-prime-code-font.html</a></div></div><br /><br /></div><div><br /></div><h2 style="text-align: left;">Everson Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhy7kGf17teLweRsW9Qz1XMuoRcK4gGPgh6ojiAH4rWLRedx9dd6PGCD-1oHtoV6Zc35Y5qsLlfQtfHRYHeZ6TYY2IKgHltHCLV9QzftWcXoFwW7GZOc7xzHXNhEqSPSGH19mz/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="396" data-original-width="483" height="524" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhy7kGf17teLweRsW9Qz1XMuoRcK4gGPgh6ojiAH4rWLRedx9dd6PGCD-1oHtoV6Zc35Y5qsLlfQtfHRYHeZ6TYY2IKgHltHCLV9QzftWcXoFwW7GZOc7xzHXNhEqSPSGH19mz/w640-h524/image.png" width="640" /></a></div></div><div><br /></div><div><b>Descarga: </b><a href="https://www.evertype.com/emono/">https://www.evertype.com/emono/</a></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Space Mono</h2><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVB9VjMcSnPuO5dGMlcgdXVh2aE5pu9ol3Z1oSabT8troMuujUbOWuRr3lFpQFy7Zzex6cX1U6rkG9YKNXN9FLtGGkr-aW5enqz9-DsISgaWrLlfRbaEgmplr_nHvl8A-BGHkM/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="504" data-original-width="1019" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVB9VjMcSnPuO5dGMlcgdXVh2aE5pu9ol3Z1oSabT8troMuujUbOWuRr3lFpQFy7Zzex6cX1U6rkG9YKNXN9FLtGGkr-aW5enqz9-DsISgaWrLlfRbaEgmplr_nHvl8A-BGHkM/w640-h316/image.png" width="640" /></a></div><br /></div><br /><b>Descarga:</b> <a href="https://www.1001fonts.com/space-mono-font.html">https://www.1001fonts.com/space-mono-font.html</a></div><div><br /></div><div><br /></div><h1 style="text-align: left;">Enlaces de interés</h1><div><ul style="text-align: left;"><li><b>List of monospaced typefaces (Wikipedia):</b> <a href="https://en.wikipedia.org/wiki/List_of_monospaced_typefaces">https://en.wikipedia.org/wiki/List_of_monospaced_typefaces</a></li><li><b>Monospace fonts (Google Fonts):</b> <a href="https://fonts.google.com/?preview.text_type=custom&category=Monospace">https://fonts.google.com/?preview.text_type=custom&category=Monospace</a></li><li><b>Monospaced fonts (Font Squirrel):</b> <a href="https://www.fontsquirrel.com/fonts/list/classification/monospaced">https://www.fontsquirrel.com/fonts/list/classification/monospaced</a></li><li><b>Monospaced fons (1001fonts):</b> <a href="https://www.1001fonts.com/monospaced-fonts.html">https://www.1001fonts.com/monospaced-fonts.html</a></li></ul></div><div><br /></div><div><br /></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-66110390377059215552021-02-15T19:53:00.003+01:002021-02-15T19:53:25.102+01:00Cómo crear un productor de streaming de eventos para Kafka en Java<div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8_u3vAR0wkMhxTnhNX0iig7tRIig1B9_EOllwadjkCHtcqpjwGf8O7FlzFeeHho0_uawQdK5MN45tK5qcMyNEH5iFur5oDLnb18Q_vTqlLGxBOG3mFna5eH4-XGszqgzBhY0n/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="505" data-original-width="677" height="478" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8_u3vAR0wkMhxTnhNX0iig7tRIig1B9_EOllwadjkCHtcqpjwGf8O7FlzFeeHho0_uawQdK5MN45tK5qcMyNEH5iFur5oDLnb18Q_vTqlLGxBOG3mFna5eH4-XGszqgzBhY0n/w640-h478/image.png" width="640" /></a></div><br /><br /></div><b>Aviso:</b> <i>Este pequeño tutorial no va a realizar una introducción a <b>Kafka</b>. Se asume que el lector ya tiene unas nociones sobre <b>Kafka</b> y quiere comenzar a desarrollar código en <b>Java</b> para enviar eventos a un <b>topic</b> de <b>Kafka</b>. Esto es habitual realizarlo, principalmente, desde <b>microservicios</b> o desde <b>scripts</b> <b>batch</b>.</i><div><br /></div><div><b>Nota: </b><i>El concepto de estado utilizado en este artículo está contextualizado en una <b>EDA</b> (<b>Arquitectura Orientada a Eventos</b>), y representa un estado originado por un evento. Dentro de <b>Kafka</b> se asume este concepto como record o registro, y se refiere al valor que almacenará <b>Kafka</b> en el bus de eventos.</i></div><div><br /></div><h3 style="text-align: left;">Requisitos</h3><div>Se asume que ya se dispone de un entorno de <b>Kafka</b> funcionando, y que en dicho entorno existe, al menos, un <b>topic</b> sobre el cual escribir eventos. Dicho entorno puede estar en la propia máquina de desarrollo (<b>localhost</b>), en un servidor dedicado o en un servidor en <b>cloud</b>.</div><div><br /></div><div>Más adelante (en otro artículo), veremos cómo desarrollar código para suscribirnos a ese <b>topic</b> y poder responder, en consecuencia, a dichos eventos. Ese código corresponderá a la parte del <b>consumidor</b> o <b>suscriptor</b>. En este artículo nos centraremos exclusivamente en la parte del <b>productor</b> o <b>publicador</b>.</div><div><br /></div><div>En el entorno de desarrollo se recomienda tener lo siguiente:</div><div><ul style="text-align: left;"><li><b>Java JDK</b> versión 11 (he utilizado la versión 15)</li><li>Gestión de dependencias con <b>Maven</b></li><li>El IDE que utilizado ha sido el de <b>Spring Tools</b>, pero con <b>Eclipse</b> o <b>IntelliJ IDEA</b> no debería haber problemas.</li><li>Dependencias de <b>Kafka</b> en <b>Maven</b> versión 2.7.0</li></ul><div><br /></div></div><h3 style="text-align: left;">Configuración de Maven</h3><div><br /></div><div>En el archivo <b>pom.xml</b> del proyecto <b>Java</b>, añadir la dependencia encargada de importar las librerías necesarias para trabajar con <b>streams</b> de eventos en <b>Kafka</b>:</div><div><br /></div><div><span style="color: #2b00fe; font-family: courier;"><dependencies></span></div><div><span style="color: #2b00fe; font-family: courier;"><span> <dependency></span><br /></span></div><div><span><span style="color: #2b00fe; font-family: courier;"><span> </span><span> <groupId>org.apache.kafka</groupId></span><br /></span></span></div><div><span><span><span style="color: #2b00fe; font-family: courier;"><span> </span><span> <artifactId>kafka-clients</artifactId></span><br /></span></span></span></div><div><span><span><span><span style="color: #2b00fe; font-family: courier;"><span> </span><span> <version>2.7.0</version></span><br /></span></span></span></span></div><div><span><span style="color: #2b00fe; font-family: courier;"><span> </dependency></span><br /></span></span></div><div><span style="color: #2b00fe; font-family: courier;"></dependencies></span></div><div><br /></div><h4 style="text-align: left;">Configuración de las propiedades</h4><div>El primer paso a realizar en el código, será definir las propiedades para poder configurar la conexión a <b>Kafka</b>. Las más importantes son las siguientes:</div><div><br /></div><div><span style="color: #2b00fe; font-family: courier;">// Propiedades del producer</span></div><div><span style="color: #2b00fe; font-family: courier;">Properties props = new Properties();</span></div><div><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div><span style="color: #2b00fe; font-family: courier;">// Lista de servidores Kafka a los que conectarse</span></div><div><span style="color: #2b00fe; font-family: courier;">props.put("bootstrap.servers", "localhost:9092");</span></div><div><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div><span style="color: #2b00fe; font-family: courier;">// Serializacion de los datos de la clave (key)</span></div><div><span style="color: #2b00fe; font-family: courier;">props.put("key.serializer", StringSerializer.class.getName());</span></div><div><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div><span style="color: #2b00fe; font-family: courier;">// Serializacion de los datos del valor (value)</span></div><div><span style="color: #2b00fe; font-family: courier;">props.put("value.serializer", StringSerializer.class.getName());</span></div><div><br /></div><div>Para el ejemplo, usaremos el tipo <b>String</b>, que es el que viene por defecto. <b>Kafka</b> permite definir estructuras de datos mediante <b>JSON</b> y <b>Avro</b> (este es el preferido), que se definen con el objeto <b>Serdes</b> (<b>SERialize/DESerialize</b>).</div><div><br /></div><div>A continuación se exponen algunas propiedades no tan relevantes ahora (son opcionales), pero que se podrán usar en un futuro para tunear la configuración de la conexión a <b>Kafka</b>:</div><div><br /></div><div><span style="color: #2b00fe; font-family: courier;">props.put("acks", "all");</span></div><div><span style="color: #2b00fe; font-family: courier;">props.put("retries", 0);</span></div><div><span style="color: #2b00fe; font-family: courier;">props.put("batch.size", 16384);</span></div><div><span style="color: #2b00fe; font-family: courier;">props.put("linger.ms", 1);</span></div><div><span style="color: #2b00fe; font-family: courier;">props.put("buffer.memory", 33554432);</span></div><div><br /></div><div><br /></div><h3 style="text-align: left;">Objeto KafkaProducer</h3><div>El objeto <b>KafkaProducer</b> permite crear un cliente para una conexión a un topic de <b>Kafka</b>, a partir de la información proporcionada en las propiedades descritas anteriormente.</div><div><br /></div><div><span style="color: #2b00fe; font-family: courier;">KafkaProducer<String, String> kp = new KafkaProducer<String, String>(props);</span></div><div><br /></div><div>Este objeto permite definir el tipo de datos de la clave (primer parámetro) y del valor o estado (segundo parámetro). En nuestro ejemplo utilizaremos el tipo <b>String</b> (si se desea trabajar con tipos customizados, ver los tipos <b>Serdes</b>, y cómo definir tipos en <b>JSON</b> o <b>Avro</b>).</div><div><br /></div><div><b>Nota:</b> <i>Este objeto crea un cliente genérico a un servidor de <b>Kafka</b>, por lo que se puede utilizar posteriormente para enviar estados a <b>streams</b> de eventos a diferentes <b>topics</b>.</i></div><div><br /></div><h3 style="text-align: left;">Preparación del estado (registro) a enviar</h3><div>Para enviar un estado o registro a <b>Kafka</b> desde el productor, es necesario preparar éste mediante un objeto de tipo <b>ProducerRecord</b>:</div><div><br /></div><div><span style="color: #2b00fe; font-family: courier;">ProducerRecord<String, String> pr = new Producer<String, String>(topic, key, estado);</span></div><div><br /></div><div>Este objeto permite definir el tipo de datos de la clave (primer parámetro) y del valor o estado (segundo parámetro). En nuestro ejemplo utilizaremos el tipo <b>String</b> (si se desea trabajar con tipos customizados, ver los tipos <b>Serdes</b>, y cómo definir tipos en <b>JSON</b> o <b>Avro</b>).</div><div><br /></div><div>En la construcción (entre paréntesis) se pasarán los valores correspondientes a:</div><div><ul style="text-align: left;"><li><b>topic: </b>Valor del nombre del topic a usar en <b>Kafka</b>, donde se enviará el evento.</li><li><b>key:</b> Valor de la clave (<b>key</b>) del evento o registro.</li><li><b>estado:</b> Valor del estado o registro a enviar.</li></ul><div>El valor de la clave puede ser opcional en otros contextos de <b>Kafka</b> (se almacenaría como <b>null</b>). Por ello, también permitiría la siguiente sintaxis:</div></div><div><br /></div><div><span style="color: #2b00fe; font-family: courier;">ProducerRecord<String, String> pr = new Producer<String, String>(topic, estado);</span></div><div><br /></div><div><br /></div><h3 style="text-align: left;">Envío del estado a Kafka</h3><div><br /></div><div>Una vez preparado el estado, éste se envía a <b>Kafka</b> a través del objeto <b>KafkaProducer</b> definido al principio, pasándole el objeto <b>ProducerRecord</b> con la información del estado:</div><div><br /></div><div><span style="color: #2b00fe; font-family: courier;">kp.send(pr);</span></div><div><br /></div><div>El método <b>send()</b> envía el estado o registro al <b>topic</b> especificado.</div><div><br /></div><div><br /></div><h3 style="text-align: left;">Cerrar la conexión a Kafka</h3><div><br /></div><div>Cuando nuestro código no va a enviar más estados a <b>Kafka</b>, debemos cerrar el objeto <b>KafkaProducer</b>, para liberar recursos del <b>stream</b>, así como la conexión. Para ello, utilizaremos el método <b>close()</b>:</div><div><br /></div><div><span style="color: #2b00fe; font-family: courier;">kp.close();</span></div><div><br /></div><div><br /></div><h3 style="text-align: left;">Aplicación de ejemplo de productor Kafka</h3><div><br /></div><div>A continuación os dejo una aplicación completa que hace de productor <b>Kafka</b>.</div><div><br /></div><div>En este ejemplo, se ejecuta desde la consola de comandos como un <b>script</b>, pero la base os servirá también para <b>microservicios</b> u otro tipo de aplicaciones.</div><div><br /></div><div>Lo primero que hará será preguntar por el topic al cual queremos enviar los estados. Después, en un bucle, solicitará el valor del estado a enviar. Dicho estado es un texto libre, por lo que se puede introducir cualquier valor, incluso un <b>JSON</b> en formato <b>String</b>.</div><div><br /></div><div>Este bucle se repetirá hasta que el usuario introduzca el valor <b>'quit' </b>(sin comillas). En ese momento se cerrará la conexión y terminará la ejecución.</div><div><br /></div><div><br /></div><div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">package com.rhernamperez.<wbr></wbr>kafkastreamsdemo;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">import java.io.BufferedReader;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">import java.io.InputStreamReader;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">import java.util.Date;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">import java.util.Properties;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">import org.apache.kafka.clients.<wbr></wbr>producer.KafkaProducer;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">import org.apache.kafka.clients.<wbr></wbr>producer.ProducerRecord;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">import org.apache.kafka.common.<wbr></wbr>serialization.<wbr></wbr>StringSerializer;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">//import org.apache.kafka.streams.<wbr></wbr>StreamsConfig;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">/**<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">* Demostracion de un productor Kafka que envia eventos a un stream<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">* @author rafinguer<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">*<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">*/<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">public class KafkaProducerDemo {<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span>public static void main(String[] args) {<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>// Propiedades del producer<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>Properties props = new Properties();<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>props.put("bootstrap.servers", "localhost:9092");</span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>props.put("key.serializer", StringSerializer.class.<wbr></wbr>getName());<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>props.put("value.serializer", StringSerializer.class.<wbr></wbr>getName());<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>props.put("acks", "all");<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>props.put("retries", 0);<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>props.put("batch.size", 16384);<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>props.put("linger.ms", 1);<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>props.put("buffer.memory", 33554432);</span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>// Creacion del objeto productor<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>KafkaProducer<String, String> kp = new KafkaProducer<String, String>(props);<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>String estado="", topic="", key = "";<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>// Mensaje de bienvenida<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>System.out.println("<wbr></wbr>Demostracion de Kafka producer. Introduce datos para cada evento. 'quit' para salir\n");<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> <span> </span></span>// Introduccion del topic por teclado<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>BufferedReader br = new BufferedReader(new InputStreamReader(System.in));<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>System.out.println("Introduce el nombre del topic: ");<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>try {<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span>topic = br.readLine();<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>} catch (Exception e) {<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span>System.out.println("ERROR > " + e.getMessage());<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>}<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>// Bucle para introducir estados hasta que se escriba 'quit'<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>while(!estado.equals("quit")) {<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span>try {<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>// Lectura de estados por teclado<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>System.out.print(">>> ");<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>estado = br.readLine();<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>if (estado.equals("quit")) continue;<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>// Envio del estado. La key sera la fecha y hora actuales<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>key = new Date().toString();<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>ProducerRecord<String, String> pr = new ProducerRecord<String, String>(topic, key, estado);<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">kp.send(pr);<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>System.out.println("Enviado a topic " + topic + " la clave " + key + " con el estado > " + estado + "\n");<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span>} catch(Exception e) {<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span><span> </span>System.out.println("Error > " + e.getMessage());<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span><span> </span>}<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>}<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>// Cerrar el stream<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>kp.close();<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span><span> </span>System.out.println("**** FIN ****");<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><span> </span>}<br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;"><br /></span></div><div style="background-color: white; font-size: small;"><span style="color: #2b00fe; font-family: courier;">}</span></div></div><div><br /></div><div><br /></div><h2 style="text-align: left;">Enlaces de interés</h2><div><ul style="text-align: left;"><li><b>Página oficial de Kafka:</b> <a href="https://kafka.apache.org/">https://kafka.apache.org/</a></li><li><b>Kafka Streams:</b> <a href="https://kafka.apache.org/documentation/streams/">https://kafka.apache.org/documentation/streams/</a></li><li><b>Javadoc de Kafka (v 2.7.0):</b> <a href="https://kafka.apache.org/27/javadoc/index.html">https://kafka.apache.org/27/javadoc/index.html</a></li><li><b>Documentación KafkaProducer:</b> <a href="https://kafka.apache.org/27/javadoc/index.html">https://kafka.apache.org/27/javadoc/index.html</a></li><li><b>Documentación ProducerRecord:</b> <a href="https://kafka.apache.org/27/javadoc/index.html">https://kafka.apache.org/27/javadoc/index.html</a></li></ul></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-80283412293767668592021-01-31T19:28:00.002+01:002021-01-31T19:36:00.896+01:00Introducción a las Arquitecturas Orientadas a Eventos (AOE / EDA)<p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9OR5FUpvbS5JbbRdMGchCI7wywYQqw2Zsdxw1UovdgCcghcna7job1TV0wR1P2tfM9a3TTf5UsKxZ3N9eRLapv77mpUHm8dboXZW3tHcBoohlS5I35jUA-LryoDNWIu-YkYOM/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="855" data-original-width="1522" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9OR5FUpvbS5JbbRdMGchCI7wywYQqw2Zsdxw1UovdgCcghcna7job1TV0wR1P2tfM9a3TTf5UsKxZ3N9eRLapv77mpUHm8dboXZW3tHcBoohlS5I35jUA-LryoDNWIu-YkYOM/w640-h360/image.png" width="640" /></a></div><br /><p></p><p>La Arquitectura Orientada a Eventos (AOE / EDA) está tomando más protagonismo en los últimos años, ante la demanda creciente de escenarios de baja latencia, escalado rápido, histórico de cambios, asincronía, alta disponibilidad y resiliencia.</p><p>El concepto de AOE/EDA no es algo nuevo, pero con el rebufo de los microservicios, ha sido una solución eficiente al desacoplamiento y al efecto de caída en racimo o en cascada.</p><p>En esta presentación aprenderemos los conocimientos básicos para conocer sus conceptos:</p><p></p><ul style="text-align: left;"><li>Conceptos básicos de Arquitectura Orientada a Eventos</li><ul><li>Paradigma de AOE / EDA</li><li>Eventos</li><ul><li>Tips para eventos</li><li>Protocolos de eventos</li><li>Streams</li></ul><li>Ventajas de AOE / EDA</li><li>Desventajas de AOE / EDA</li><li>Cuándo usar AOE / EDA</li><li>Eventos Vs Comandos Vs Consultas</li></ul><li>Componentes de una Arquitectura Orientada a Eventos</li><ul><li>Generadores</li><li>Mensajes</li><li>Componentes de Mensajería</li><li>Canales</li><li>Patrones de Mensajería</li><li>Procesadores</li><li>Coordinación mediante un bus de eventos</li><li>Ejemplo de un sistema complejo</li></ul><li>Patrones</li><ul><li>Notificación de eventos</li><li>Transferencia del estado de los eventos</li><li>Abastecimiento de eventos (Event Sourcing)</li><li>CQRS (Command Query Responsability Segregation)</li><li>Sagas</li><li>Microservicios orientados a eventos</li><li>Microservicios en Event Backbone</li><li>Base de datos por servicio</li></ul><li>Apache Kafka</li><li>Amazon EventBridge</li></ul><p></p><p>La presentación completa se puede ver y descargar en el siguiente enlace: <a href="https://drive.google.com/file/d/14rimoL-7R6_cGPyUuOvPNgeBAdkKBvPB/view?usp=sharing" target="_blank">Introducción a Arquitecturas Orientadas a Objetos</a></p><p><br /></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-36727331715362108062020-12-08T21:30:00.007+01:002020-12-08T21:30:53.669+01:00Curso de introducción a la analítica de datos con Pandas<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM9BW7d-kktCL6VHFODK737Ew4m4MsZJ3JiDZ_t8686LzkzDD50waXxv5AMIc1VU4MbKVoubf7x-3rTkFj7ta5blIauHv2GYXLNjABOXf6tG_B-C7WCmRF6EJt6CrY6wQhoZAK/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="668" data-original-width="1170" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM9BW7d-kktCL6VHFODK737Ew4m4MsZJ3JiDZ_t8686LzkzDD50waXxv5AMIc1VU4MbKVoubf7x-3rTkFj7ta5blIauHv2GYXLNjABOXf6tG_B-C7WCmRF6EJt6CrY6wQhoZAK/w640-h366/image.png" width="640" /></a></div><br /><h2 style="text-align: left;">Curso de introducción a la analítica de datos con Python y Pandas.</h2><p>Enlace de descarga: <a href="https://drive.google.com/file/d/1kbLhRG5idWq9qtkVl_YcPDsmM-522vEG/view">https://drive.google.com/file/d/1kbLhRG5idWq9qtkVl_YcPDsmM-522vEG/view</a> </p><p><b><u>Contenido</u></b></p><ul style="text-align: left;"><li>Introducción:</li><li>DataFrames:</li><ul><li>Series</li><li>DataFrames</li><li>Crear un DataFrame desde una lista</li><li>Crear un DataFrame desde un diccionario</li><li>Crear un DataFrame desde una lista de diccionarios</li><li>Índices en un DataFrame</li><li>Propiedades de un DataFrame:</li><ul><li>axes </li><li>dtypes</li><li>values</li><li>shape</li><li>size</li><li>empty</li><li>columns</li></ul><li>Información de un DataFrame (info())</li><li>Descripción del DataFrame (describe())</li></ul><li>Importación de datos:</li><ul><li>desde un archivo CSV</li><li>desde un archivo Excel</li></ul><li>Selección:</li><ul><li>Selección de columnas</li><li>Selección de filas</li><li>Selección condicional</li><li>Selección condicional y de columnas</li><li>Selección usando números</li></ul><li>Columnas:</li><ul><li>Añadir columnas</li><li>Insertar columnas</li><li>Eliminar columnas</li><li>Renombrar columnas</li></ul><li>Datos:</li><ul><li>Iteración sobre los datos</li><li>Valores nulos</li><li>Valores perdidos</li><li>Sustituir valores perdidos</li><li>Sustituir valores perdidos por columnas</li><li>Reemplazar valores</li><li>Borrado de filas</li><li>Borrado de filas duplicadas</li><li>Borrado de filas con valores perdidos</li><li>Ordenar los datos</li><li>Agrupar los datos</li><li>Iterar sobre datos agrupados</li><li>Seleccionar grupos</li><li>Agregación sobre un grupo</li><li>Datos de texto</li><li>Datos de fecha/hora</li></ul><li>Mezcla de datos (merge)</li><li>Guardado de datos:</li><li>Visualización de datos:</li><ul><li>Gráficos de Área</li><li>Gráficos de Línea</li><li>Gráficos de Barra</li><li>Gráficos de Histograma</li><li>Gráficos de Dispersión</li><li>Gráficos de Caja</li><li>Otros tipos de Gráficos</li></ul><li>Anexos</li></ul><p></p><p><br /></p><p><br /></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-11627788731442744402020-11-12T21:55:00.002+01:002020-11-13T10:16:51.668+01:00Curso de analítica de datos con NumPy<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoRyDJnlMawQ5RhlooRjN-3WgmO1XmhbA_0AEweP7JqsQtzytoWr6OmEZSMjhHD3IUZ8UoDsOTXCdO5EPUDI0ADAt2TaKagxDi6W5mdG4am8ocfMnNbuNbyQ_1NRGIDm-Lqqu6/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="655" data-original-width="1162" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoRyDJnlMawQ5RhlooRjN-3WgmO1XmhbA_0AEweP7JqsQtzytoWr6OmEZSMjhHD3IUZ8UoDsOTXCdO5EPUDI0ADAt2TaKagxDi6W5mdG4am8ocfMnNbuNbyQ_1NRGIDm-Lqqu6/w640-h360/image.png" width="640" /></a></div><br />NumPy es una poderosa librería de Python que permite realizar analítica de datos, gracias al uso eficiente de arrays multidimensionales.<p></p><p>El contenido del curso es el siguiente:</p><p></p><ul style="text-align: left;"><li>Introducción</li><li>Conceptos básicos:</li><ul><li>Arrays con NumPy</li><li>Multidimensionalidad</li><li>Redimensionamiento y transposición</li><li>Arrays por defecto</li><li>Indexación</li><li>Indexación avanzada de columnas</li><li>Indexación y slicing avanzado</li><li>Indexacion boolean</li><li>Usos de indexación boolean</li></ul><li>Matemáticas:</li><ul><li>Matemáticas entre arrays</li><li>Potencias entre arrays</li><li>Broadcasting</li><li>Operaciones con un valor</li><li>Suma</li><li>Producto</li><li>Máximo y mínimo</li><li>Diferencia entre el máximo y el mínimo</li><li>Media aritmética</li><li>Mediana</li><li>Desviación estándar</li><li>Percentil</li></ul><li>Operaciones avanzadas:</li><ul><li>Valores nan</li><li>Redondeo</li><li>Agregar columnas</li><li>Arrays de datos estructurados</li><li>Concatenación de arrays</li><li>Ordenación de arrays</li><li>Ordenación invertida</li><li>Valores únicos</li><li>Guardar y cargar datos en ficheros</li></ul></ul><div><br /></div><div><b>Enlace al curso:</b></div><div><a href="https://drive.google.com/file/d/1uRJkRYL1z7XhTq9B5MFQhp0P2pUYxFtG/view?usp=sharing" target="_blank">https://drive.google.com/file/d/1uRJkRYL1z7XhTq9B5MFQhp0P2pUYxFtG/view?usp=sharing </a></div><div><br /></div><p></p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-66869678192757786652020-11-07T21:17:00.009+01:002020-11-07T21:34:35.463+01:00What Artificial Intelligence is?<p><b></b></p><div class="separator" style="clear: both; text-align: center;"><b><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmFsmshQq1bZwSNh2vKStszFb1ObG2jYcFcFOpedaDroZE-da0t2QO5p1CENXFKWkPG2t17a2G3x2D4QFx__U7ii0SrA6wivGez3P54xUWE4kHheWxI_Z065uVRnWJVF0bhM58/s2048/proxy-image.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1090" data-original-width="2048" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmFsmshQq1bZwSNh2vKStszFb1ObG2jYcFcFOpedaDroZE-da0t2QO5p1CENXFKWkPG2t17a2G3x2D4QFx__U7ii0SrA6wivGez3P54xUWE4kHheWxI_Z065uVRnWJVF0bhM58/w640-h340/proxy-image.jpg" width="640" /></a></b></div><b><span style="background-color: rgba(255, 255, 255, 0.75); color: rgba(0, 0, 0, 0.87); font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; letter-spacing: 0.15008px; white-space: pre-line;"><br /></span></b><p></p><p><b><span style="background-color: rgba(255, 255, 255, 0.75); color: rgba(0, 0, 0, 0.87); font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; letter-spacing: 0.15008px; white-space: pre-line;">Cool things that computers can't do?</span></b></p><span style="background-color: rgba(255, 255, 255, 0.75); color: rgba(0, 0, 0, 0.87); font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; letter-spacing: 0.15008px; white-space: pre-line;"> This topic has been always overcome in the last years. Finally, an algorithm can imitate and do these cool things that we considered as intelligent.
<b>Machines imitating intelligent human behavior?</b></span><div><span style="background-color: rgba(255, 255, 255, 0.75); color: rgba(0, 0, 0, 0.87); font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; letter-spacing: 0.15008px; white-space: pre-line;">Any imitation is based on procedures resolved previously with (human) intelligence. Therefore, why not consider this imitation as intelligent? We, the human being, are living imitating and repeating constantly procedures from other humans. </span></div><div><span style="background-color: rgba(255, 255, 255, 0.75); color: rgba(0, 0, 0, 0.87); font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; letter-spacing: 0.15008px; white-space: pre-line;"><br /></span></div><div><span style="background-color: rgba(255, 255, 255, 0.75); color: rgba(0, 0, 0, 0.87); font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; letter-spacing: 0.15008px; white-space: pre-line;"><b>Autonomous and adaptive systems? </b></span></div><div><span style="background-color: rgba(255, 255, 255, 0.75); color: rgba(0, 0, 0, 0.87); font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; letter-spacing: 0.15008px; white-space: pre-line;">Autonomy is achieved with a certain intelligence. Adaptation is an intelligent evolution of the current species. From a certain point of view, we can consider as intelligent any system that can be work autonomously and can be adapted and adjusted automatically depending on new factors and scenarios.
<b>On my opinion</b></span></div><div><span style="background-color: rgba(255, 255, 255, 0.75); color: rgba(0, 0, 0, 0.87); font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; letter-spacing: 0.15008px; white-space: pre-line;">Who can be in possession of the true and the reason describing the intelligence? Why cannot exist many types of intelligence? What determines the concept of intelligence? I consider intelligence as any behavior than respond to the environment solving the problem or overcoming adversity with an optimal and profitable result. Depending on the degree achieved with that result, we can consider a best or a worst intelligence.
The above description could be the definition of simplistic intelligence. If we introduce the capacity of that intelligence to self learn from the experience and adapt this experience to new scenarios, this intelligence is more advanced and complex.
Finally, intelligence can grow in complexity and make relations with other types of intelligence that are capable to solve other specific tasks. When these types of intelligence are joined to face new unknown challenges, collective intelligence achieves a very high level of intelligence.
Consciousness could be, at the moment, the top level of intelligence, the limit, or the frontier between the human being and the machines.</span></div><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.comtag:blogger.com,1999:blog-9291335.post-48707511294552929942020-11-04T19:37:00.005+01:002020-11-04T19:37:57.165+01:00Curso gratuito de Introducción a Python<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifil2RGCfP0t-zGjmfWhOknUUDWdGZiV3Sc-tI7ybKAEJR7pnCmDRZw2jVe87OH8eQrS9I618QsiWcWL51__wEjQCIRCUE662S2L0MHCn_Tp0DOeaC-s9B4gAHoNyh1rIHmOTA/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="666" data-original-width="1185" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifil2RGCfP0t-zGjmfWhOknUUDWdGZiV3Sc-tI7ybKAEJR7pnCmDRZw2jVe87OH8eQrS9I618QsiWcWL51__wEjQCIRCUE662S2L0MHCn_Tp0DOeaC-s9B4gAHoNyh1rIHmOTA/w640-h360/image.png" width="640" /></a></div><br />Este curso gratuito es un tour completo y sencillo a los conceptos básicos de Python. <p></p><p></p><ul style="text-align: left;"><li>Datos básicos:</li><ul><li>int</li><li>float</li><li>str</li><li>bool</li><li>type()</li><li>Variables</li><li>print()</li><li>Operadores con cadenas de texto</li><li>Operadores con datos numéricos</li><li>Precedencia de los operadores</li><li>Conversión entre tipos de datos</li></ul><li>Ejecución condicional:</li><ul><li>Expresiones boolean</li><li>Operadores lógicos</li><li>Condiciones mediante if/else</li><li>Condiciones anidadas</li><li>Condiciones encadenadas (elif)</li></ul><li>Excepciones:</li><ul><li>try</li><li>except</li></ul><li>Funciones:</li><ul><li>Desarrollo de funciones</li><li>Funciones estándar</li><li>Librerías de funciones</li><li>Funciones matemáticas</li><li>Funciones para números aleatorios</li></ul><li>Bucles:</li><ul><li>Bucle while</li><li>Bucles infinitos</li><li>Sentencia break</li><li>Sentencia continue</li><li>Bucle for</li><li>Rangos</li></ul><li>Cadenas de texto:</li><ul><li>Cadenas como listas de caracteres</li><li>Slicing de cadenas</li><li>Operaciones con cadenas (funciones)</li><li>Formateo de datos en cadenas</li></ul><li>Listas:</li><ul><li>Conceptos básicos</li><li>Operadores de listas</li><li>Métodos de listas</li><li>Usando funciones estándar en listas</li><li>Listas y cadenas</li></ul><li>Tuplas:</li><ul><li>Conceptos básicos</li><li>Usos especiales de las tuplas</li></ul><li>Diccionarios:</li><ul><li>Conceptos básicos</li><li>Diccionarios y tuplas</li><li>Tuplas como claves</li></ul><li>Programación orientada a objetos:</li><ul><li>Conceptos básicos</li><li>Consultar características de un objeto</li><li>Constructor y destructor</li><li>Herencia</li></ul></ul><p></p><p><br /></p><p>El curso está repleto de ejemplos, y contiene enlaces a recursos interesantes: enlaces oficiales, documentación, libros, entornos de desarrollo, frameworks, librerías, etc.</p><p>Enlace al curso: <a href="https://drive.google.com/file/d/1ZMZqp0K276LZ2p-f9_ZJHFbYMYVLMeY9/view?usp=sharing" target="_blank">Curso de introducción a Python</a> </p><div class="blogger-post-footer">Technology IT News</div>Rafael Hernampérezhttp://www.blogger.com/profile/04102640369106899565noreply@blogger.com