{"id":32723,"date":"2019-10-31T21:48:35","date_gmt":"2019-10-31T18:48:35","guid":{"rendered":"https:\/\/prohoster.info\/blog\/yurij-bushmelev-karta-grablej-na-pole-sbora-i-dostavki-logov-rasshifrovka-doklada\/"},"modified":"2019-10-31T21:48:35","modified_gmt":"2019-10-31T18:48:35","slug":"yurij-bushmelev-karta-grablej-na-pole-sbora-i-dostavki-logov-rasshifrovka-doklada","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/yurij-bushmelev-karta-grablej-na-pole-sbora-i-dostavki-logov-rasshifrovka-doklada","title":{"rendered":"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Los registros son una parte importante del sistema que permite entender si funciona (o no) como se espera. En un entorno de arquitectura de microservicios, trabajar con registros se convierte en una disciplina propia de una olimpiada especial. Hay que resolver una serie de preguntas:<\/p>\n<p><\/p>\n<ul>\n<li>\u00bfc\u00f3mo redactar registros desde la aplicaci\u00f3n?<\/li>\n<li>\u00bfd\u00f3nde escribir los registros?<\/li>\n<li>\u00bfc\u00f3mo enviar los registros para su almacenamiento y procesamiento?<\/li>\n<li>\u00bfc\u00f3mo procesar y almacenar los registros?<\/li>\n<\/ul>\n<p><\/p>\n<p>La aplicaci\u00f3n de tecnolog\u00edas de contenedorizaci\u00f3n actualmente populares a\u00f1ade complejidad a la b\u00fasqueda de soluciones a este problema.<\/p>\n<p><\/p>\n<p>Just this is the interpretation of Yuri Bushmelev's report \"Mapa de trampas en el campo de recolecci\u00f3n y entrega de registros\" <\/p>\n<p>\n<center><div class=\"youtube-placeholder\" data-id=\"NAeedJv-S3I\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/NAeedJv-S3I\/hqdefault.jpg\" alt=\"Reproducir video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><\/p>\n<p>A quienes les interese, les invito a leer m\u00e1s.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Me llamo Yuri Bushmelev. Trabajo en Lazada. Hoy hablar\u00e9 sobre c\u00f3mo manejamos nuestros registros, c\u00f3mo los recolectamos y qu\u00e9 escribimos en ellos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/ece6053b1027ab3681022049ddcd79ea.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfDe d\u00f3nde somos? \u00bfQui\u00e9nes somos? Lazada es la tienda en l\u00ednea n\u00famero 1 en seis pa\u00edses del sudeste asi\u00e1tico. Todos estos pa\u00edses est\u00e1n representados en nuestros centros de datos. Actualmente tenemos 4 centros de datos. \u00bfPor qu\u00e9 es importante? Porque algunas decisiones se deben a que hay un enlace muy d\u00e9bil entre los centros. Nuestra arquitectura es de microservicios. Me sorprendi\u00f3 descubrir que ya tenemos 80 microservicios. Cuando comenc\u00e9 con la tarea de los registros, solo hab\u00eda 20. Adem\u00e1s, hay una gran parte de legado en PHP con la que tambi\u00e9n tenemos que convivir. Todo esto genera en este momento m\u00e1s de 6 millones de mensajes por minuto en todo el sistema. A continuaci\u00f3n, mostrar\u00e9 c\u00f3mo intentamos manejar esto y por qu\u00e9 es as\u00ed.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/0ba5fcee5064865e836cefd47c40d246.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hay que vivir con estos 6 millones de mensajes. \u00bfQu\u00e9 debemos hacer con ellos? 6 millones de mensajes que hay que:<\/p>\n<p><\/p>\n<ul>\n<li>enviar desde la aplicaci\u00f3n<\/li>\n<li>recibir para la entrega<\/li>\n<li>entregar para an\u00e1lisis y almacenamiento.<\/li>\n<li>analizar<\/li>\n<li>almacenar de alguna manera.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/a449062193c4b1757a61f5c92e270a74.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cuando aparecieron tres millones de mensajes, ten\u00eda una expresi\u00f3n m\u00e1s o menos similar. Porque empezamos desde unas pocas monedas. Es obvio que se escriben registros de las aplicaciones. Por ejemplo, no se pudo conectar a la base de datos, se pudo conectar a la base de datos, pero no se pudo leer algo. Pero adem\u00e1s de eso, cada uno de nuestros microservicios escribe tambi\u00e9n un registro de acceso. Cada solicitud que llega al microservicio se registra. \u00bfPor qu\u00e9 hacemos esto? Los desarrolladores quieren tener la capacidad de rastrear. En cada registro de acceso hay un campo traceid, a partir del cual una interfaz especial descompone toda la cadena y muestra el trazado de manera ordenada. El trazado muestra c\u00f3mo pas\u00f3 la solicitud y esto ayuda a nuestros desarrolladores a lidiar m\u00e1s r\u00e1pidamente con cualquier cosa indeseada.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/e13a2d37ce57e894d023ad405a2b5200.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfC\u00f3mo vivir con esto? Ahora les contar\u00e9 brevemente sobre las opciones: c\u00f3mo se resuelve en general este problema. C\u00f3mo abordar la tarea de recopilaci\u00f3n, transmisi\u00f3n y almacenamiento de registros. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/60af5e5db804770295741995adb37d90.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfC\u00f3mo escribir desde la aplicaci\u00f3n? Es obvio que hay diferentes formas. En particular, hay mejores pr\u00e1cticas, seg\u00fan nos cuentan los compa\u00f1eros de moda. Hay el m\u00e9todo tradicional en dos variantes, como sol\u00edan contar nuestros abuelos. Existen otros m\u00e9todos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/deab57e4ac0472a8591c0fad9e9f2910.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La situaci\u00f3n con la recopilaci\u00f3n de registros es bastante similar. No hay muchas opciones para resolver esta parte concreta. Ya hay m\u00e1s, pero todav\u00eda no son muchas. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/8a6004aaeb931332983a975d0fa5c1d6.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pero con la entrega y el posterior an\u00e1lisis, la cantidad de variaciones comienza a explotar. No describir\u00e9 cada variante ahora. Creo que las opciones principales son conocidas por todos los que han estado interesados en el tema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/6a0b64c7e58bc59f56aaddd27112ec51.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mostrar\u00e9 c\u00f3mo hicimos esto en Lazada y c\u00f3mo comenz\u00f3 todo esto. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/20f3aa5ceea8b28733ce5399bc30f5b5.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hace un a\u00f1o llegu\u00e9 a Lazada y me enviaron al proyecto sobre registros. As\u00ed era m\u00e1s o menos. El registro de la aplicaci\u00f3n se escrib\u00eda en stdout y stderr. Todos lo hicimos a la moda. Pero luego los desarrolladores lo sacaron de los flujos est\u00e1ndar, y despu\u00e9s los especialistas en infraestructura se encargar\u00e1n de ello. Entre los especialistas en infraestructura y los desarrolladores hay tambi\u00e9n los responsables de las versiones, que dijeron: 'Eh... bueno, simplemente encapsulemos esto en un archivo usando shell y ya est\u00e1'. Y dado que todo esto est\u00e1 en un contenedor, se encapsul\u00f3 directamente dentro del contenedor, mapeamos el directorio y lo pusimos all\u00ed. Creo que a todos les resulta m\u00e1s o menos obvio qu\u00e9 sali\u00f3 de esto.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/d92e02c18a4c683c9389321e4d5412df.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Veamos un poco m\u00e1s lejos. C\u00f3mo entreg\u00e1bamos estos registros. Alguien eligi\u00f3 td-agent, que en realidad es fluentd, pero no exactamente fluentd. No entend\u00ed la relaci\u00f3n entre estos dos proyectos, pero parecen tratar sobre lo mismo. Y este fluentd, escrito en Ruby, le\u00eda archivos de registro, los analizaba en JSON mediante algunas expresiones regulares. Luego los enviaba a Kafka. De hecho, en Kafka ten\u00edamos 4 temas separados para cada API. \u00bfPor qu\u00e9 4? Porque hay live, hay staging, y porque hay stdout y stderr. Los desarrolladores los generan, y los del equipo de infraestructura deben crearlos en Kafka. Adem\u00e1s, Kafka era controlada por otro departamento. Por lo tanto, ten\u00edas que crear un ticket para que ellos crearan 4 temas para cada API. Todos se olvidaban de esto. En resumen, fue un desastre total. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/3130f9ebfda22713cffacf10db45ca89.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 hicimos luego con esto? Lo enviamos a Kafka. Luego, de Kafka, la mitad de los registros iban a Logstash. La otra mitad de los registros se divid\u00edan. Una parte iba a un Graylog, y la otra a otro Graylog. Al final, todo esto terminaba en un cl\u00faster de Elasticsearch. As\u00ed que, todo este desorden acababa ah\u00ed. \u00a1No se debe hacer as\u00ed!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/98bf4811c102fc12fcd1114c25886b69.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>As\u00ed es como se ve, si lo miramos de manera general. \u00a1No se debe hacer as\u00ed! Aqu\u00ed, de inmediato, los lugares problem\u00e1ticos est\u00e1n marcados con n\u00fameros. En realidad, hay m\u00e1s, pero 6 son los realmente problem\u00e1ticos, con los que hay que hacer algo. Ahora les hablar\u00e9 de ellos por separado. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/69f7682e6677bdda3068d6dea4db7732.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aqu\u00ed (1,2,3) se est\u00e1n escribiendo archivos y, por lo tanto, aqu\u00ed hay tres dificultades de inmediato. <\/p>\n<p><\/p>\n<p>Primero (1) \u2014 necesitamos escribirlos en alguna parte. No siempre quisi\u00e9ramos dar a la API la posibilidad de escribir directamente en un archivo. Ser\u00eda deseable que la API estuviera aislada en un contenedor, y a\u00fan mejor, que fuera de solo lectura. Soy administrador de sistemas, as\u00ed que tengo una perspectiva un poco alternativa sobre estas cosas.<\/p>\n<p><\/p>\n<p>El segundo punto (2,3) es que recibimos muchas solicitudes en la API. La API escribe muchos datos en un archivo. Los archivos crecen. Necesitamos rotarlos. De lo contrario, no habr\u00e1 suficientes discos. Rotarlos es problem\u00e1tico porque est\u00e1n redirigidos a trav\u00e9s de shell a un directorio. No podemos rotarlos de ninguna manera. No podemos decirle a la aplicaci\u00f3n que vuelva a abrir los descriptores. Porque los desarrolladores te mirar\u00edan como si fueras un tonto: \"\u00bfQu\u00e9 descriptores? Nosotros simplemente escribimos en stdout\". Los administradores de infraestructura implementaron copytruncate en logrotate, que simplemente hace una copia del archivo y trunca el original. As\u00ed que, entre esos procesos de copia, generalmente se termina el espacio en disco.<\/p>\n<p><\/p>\n<p>(4) Tuvimos diferentes formatos en diferentes API. Eran un poco distintos, pero hab\u00eda que escribir regex distintos. Dado que todo esto se gestionaba con Puppet, hab\u00eda un gran conjunto de clases con sus propios problemas. Adem\u00e1s, td-agent podr\u00eda consumir memoria la mayor parte del tiempo, volverse lento, y simplemente podr\u00eda hacer como si estuviera funcionando sin hacer nada. Desde afuera, era imposible notar que no estaba haciendo nada. En el mejor de los casos, se ca\u00eda y alguien lo levantaba despu\u00e9s. M\u00e1s bien, llegaba una alerta y alguien ten\u00eda que reiniciarlo manualmente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/424cda2b60e9e5669b7ef2b34ca74e48.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>(6) Y el desastre total fue elasticsearch. Porque era una versi\u00f3n antigua. En ese momento no ten\u00edamos maestros dedicados. Ten\u00edamos registros heterog\u00e9neos cuyos campos pod\u00edan superponerse. Diferentes registros de diferentes aplicaciones pod\u00edan tener nombres de campos id\u00e9nticos, pero los datos dentro pod\u00edan ser diferentes. Es decir, un registro llegaba con un Integer en el campo, por ejemplo, level. Otro registro llegaba con un String en el campo level. En ausencia de un mapeo est\u00e1tico, esto pod\u00eda causar problemas. Si despu\u00e9s de rotar el \u00edndice en elasticsearch, el primer mensaje que llega es una cadena, todo funciona bien. Pero si el primero es un Integer, todos los mensajes posteriores que llegan con String simplemente son descartados. Porque el tipo de campo no coincide.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/bc869f827bed326792857113191bb028.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Comenzamos a hacernos estas preguntas. Decidimos no buscar culpables.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/a071a4b38462f249339c988c35463639.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00a1Pero hay que hacer algo! Es obvio que necesitamos establecer est\u00e1ndares. Ya ten\u00edamos algunos est\u00e1ndares. Algunos se establecieron un poco m\u00e1s tarde. Afortunadamente, en ese momento ya se aprob\u00f3 un formato unificado de registros para todas las API. Est\u00e1 especificado en los est\u00e1ndares de interacci\u00f3n de los servicios. Por lo tanto, aquellos que quieran recibir registros deben escribirlos en este formato. Si alguien no escribe registros en este formato, significa que no garantizamos nada. <\/p>\n<p><\/p>\n<p>Adem\u00e1s, nos gustar\u00eda establecer un est\u00e1ndar \u00fanico para los m\u00e9todos de grabaci\u00f3n, entrega y recolecci\u00f3n de registros. B\u00e1sicamente, d\u00f3nde escribirlos y c\u00f3mo entregarlos. La situaci\u00f3n ideal es cuando en los proyectos se utiliza la misma biblioteca. Hay una biblioteca de registro separada para Go, otra para PHP. Todos los que tenemos deben usarlas. En este momento dir\u00eda que tenemos un 80% de \u00e9xito en esto. Pero algunos siguen teniendo problemas.<\/p>\n<p><\/p>\n<p>Y ah\u00ed (en la diapositiva) apenas comienza a aparecer el 'SLA para la entrega de registros'. A\u00fan no lo tenemos, pero estamos trabajando en ello. Porque es muy conveniente cuando la infraestructura dice que si escribes en un formato determinado en un lugar espec\u00edfico y no m\u00e1s de N mensajes por segundo, entonces lo entregaremos con cierta probabilidad a tal lado. Esto elimina muchos dolores de cabeza. Si hay un SLA, \u00a1eso es realmente genial!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/a887aceac13135afe90bb5f5a5ec1d26.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfC\u00f3mo comenzamos a resolver el problema? El principal obst\u00e1culo era el td-agent. No estaba claro a d\u00f3nde iban nuestros registros. \u00bfSe est\u00e1n entregando? \u00bfSe est\u00e1n recolectando? \u00bfD\u00f3nde est\u00e1n, en realidad? Por lo tanto, el primer paso fue decidir reemplazar el td-agent. He bosquejado brevemente las opciones para lo que se puede usar como sustituto.<\/p>\n<p><\/p>\n<p>Fluentd. En primer lugar, lo hab\u00eda encontrado en mi trabajo anterior, y all\u00ed tambi\u00e9n se ca\u00eda peri\u00f3dicamente. En segundo lugar, es pr\u00e1cticamente lo mismo, pero m\u00e1s adaptado. <\/p>\n<p><\/p>\n<p>Filebeat. \u00bfPor qu\u00e9 era conveniente para nosotros? Porque est\u00e1 hecho en Go, y tenemos una gran experiencia en Go. Por lo tanto, si fuera necesario, podr\u00edamos adaptarlo de alguna manera. As\u00ed que no lo elegimos. Para no caer en la tentaci\u00f3n de reescribirlo para nosotros. <\/p>\n<p><\/p>\n<p>La soluci\u00f3n obvia para los administradores de sistemas son varios syslogs en esta cantidad (syslog-ng\/rsyslog\/nxlog).<\/p>\n<p><\/p>\n<p>O escribir algo propio, pero descartamos eso, al igual que filebeat. Si vamos a escribir algo, lo mejor es que sea algo \u00fatil para el negocio. Para la entrega de registros, es mejor elegir algo ya existente.<\/p>\n<p><\/p>\n<p>Por lo tanto, la elecci\u00f3n se redujo a elegir entre syslog-ng y rsyslog. Me inclin\u00e9 por rsyslog simplemente porque ya ten\u00edamos clases para rsyslog en Puppet, y no encontr\u00e9 diferencias evidentes entre ellos. No importa si es syslog aqu\u00ed o all\u00e1. S\u00ed, la documentaci\u00f3n de algunos es peor, la de otros es mejor. Uno lo hace de una manera, el otro de otra.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/a88116711b547fa5b2b34daf72cc4220.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y un poco sobre rsyslog. En primer lugar, es genial porque tiene muchos m\u00f3dulos. Tiene un RainerScript comprensible para los humanos (un lenguaje de configuraci\u00f3n moderno). Un gran bono es que pudimos simular el comportamiento de td-agent con medios est\u00e1ndar, y para las aplicaciones no hubo cambios. Es decir, cambiamos td-agent por rsyslog, y todo lo dem\u00e1s permanece sin cambios. Y de inmediato obtenemos una entrega funcional. Adem\u00e1s, mmnormalize es algo impresionante en rsyslog. Permite parsear logs, pero no usando Grok y regexp. Hace un \u00e1rbol de sintaxis abstracta. Parsea los logs m\u00e1s o menos como un compilador parsea el c\u00f3digo fuente. Esto permite trabajar muy r\u00e1pido, consumir poco CPU y, en general, es algo realmente genial. Hay muchas otras ventajas. No me detendr\u00e9 en ellas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/ca811be9f9ff318fb8c8bbf3dc45a038.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Rsyslog tambi\u00e9n tiene muchos inconvenientes. Son aproximadamente los mismos que los beneficios. Los principales problemas son que hay que saber configurarlo y hay que elegir la versi\u00f3n adecuada.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/034f588e0834b1d4e4873d9c3dbd0873.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Decidimos que escribir\u00edamos logs en un socket unix. No en \/dev\/log, porque ah\u00ed hay un l\u00edo de logs del sistema, con journald en esa canalizaci\u00f3n. Por lo tanto, escribamos en un socket personalizado. Lo conectaremos a un conjunto de reglas separado. No mezclaremos nada. Todo ser\u00e1 transparente y claro. As\u00ed lo hicimos. El directorio con estos sockets est\u00e1 estandarizado y se pasa a todos los contenedores. Los contenedores pueden ver el socket que necesitan, abrirlo y escribir en \u00e9l. <\/p>\n<p><\/p>\n<p>\u00bfPor qu\u00e9 no un archivo? Porque todos leyeron <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/badoo\/blog\/280606\/\">el art\u00edculo sobre Badushka<\/a><\/noindex>, que intentaba pasar un archivo en docker y descubr\u00eda que despu\u00e9s de reiniciar rsyslog, el descriptor de archivo cambiaba y docker perd\u00eda ese archivo. Mantiene abierto algo diferente, pero ya no el socket al que se escribe. Decidimos que evitar\u00edamos este problema y, de paso, evitar\u00edamos el problema del bloqueo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/78db15581a68ce16d11f5ebe7e6fe04e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Rsyslog realiza las acciones indicadas en la diapositiva y env\u00eda los logs ya sea a un relay o a Kafka. Kafka corresponde al antiguo m\u00e9todo. El relay es que intent\u00e9 utilizar rsyslog puro para la entrega de logs. Sin Message Queue, con los medios est\u00e1ndar de rsyslog. En principio, esto funciona.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/e61a25005ecbdc86d9de3215ee6fb97e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pero hay matices sobre c\u00f3mo introducirlos en esta parte (Logstash\/Graylog\/ES). Esta parte (rsyslog-rsyslog) se utiliza entre los centros de datos. Aqu\u00ed hay un enlace TCP comprimido que permite ahorrar ancho de banda y, por lo tanto, aumentar la probabilidad de que recibamos algunos registros del otro centro de datos en condiciones en las que el canal est\u00e1 saturado. Porque tenemos Indonesia, donde todo va mal. All\u00ed hay un problema constante.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/7509ba360be2db4dec0c8679225d285f.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nos preguntamos c\u00f3mo controlar la probabilidad de que los registros que hemos grabado desde la aplicaci\u00f3n lleguen a su destino. Decidimos establecer m\u00e9tricas. Rsyslog tiene su propio m\u00f3dulo de recopilaci\u00f3n de estad\u00edsticas, que tiene algunos contadores. Por ejemplo, puede mostrar el tama\u00f1o de la cola o cu\u00e1ntos mensajes llegaron a una acci\u00f3n determinada. De ah\u00ed se puede extraer algo. Adem\u00e1s, tiene contadores personalizados que se pueden configurar, y te mostrar\u00e1, por ejemplo, la cantidad de mensajes que ha registrado una API determinada. Luego, escrib\u00ed rsyslog_exporter en Python, y enviamos todo esto a Prometheus y construimos gr\u00e1ficos. Las m\u00e9tricas de Graylog eran muy deseadas, pero a\u00fan no hemos tenido tiempo para configurarlas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/ef9bd61fc43e056b4a56240c85e7fd20.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfCu\u00e1les fueron los problemas? Los problemas surgieron porque descubrimos (\u00a1SORPRESA!) que nuestras API en vivo est\u00e1n escribiendo 50k mensajes por segundo. Eso es solo para las API en vivo, sin contar el staging. Y Graylog solo nos muestra 12 mil mensajes por segundo. Y se plante\u00f3 la pregunta razonable, \u00bfd\u00f3nde est\u00e1n los dem\u00e1s? De lo que dedujimos que Graylog simplemente no puede manejarlo. Miramos y, efectivamente, Graylog con Elasticsearch no pod\u00eda procesar este flujo.<\/p>\n<p><\/p>\n<p>A continuaci\u00f3n, otros descubrimientos que hicimos en el proceso.<\/p>\n<p><\/p>\n<p>Las escrituras en el socket se bloquean. \u00bfC\u00f3mo ocurri\u00f3 esto? Cuando us\u00e9 rsyslog para la entrega, en alg\u00fan momento se rompi\u00f3 el canal entre los centros de datos. La entrega se detuvo en un lugar y luego en otro. Todo esto lleg\u00f3 a la m\u00e1quina con la API que escribe en el socket de rsyslog. Se llen\u00f3 la cola. Luego se llen\u00f3 la cola para escribir en el socket unix, que por defecto tiene un l\u00edmite de 128 paquetes. Y la siguiente write() en la aplicaci\u00f3n se bloquea. Cuando revisamos la biblioteca que usamos en las aplicaciones de Go, dec\u00eda que la escritura en el socket se realiza en modo no bloqueante. Est\u00e1bamos seguros de que nada se bloqueaba. Porque le\u00edmos. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/badoo\/blog\/280606\/\">el art\u00edculo sobre Badushka<\/a><\/noindex>, que escribi\u00f3 sobre esto. Pero hay un detalle. Alrededor de esta llamada hab\u00eda un ciclo infinito, donde constantemente se intentaba enviar un mensaje al socket. Eso no lo notamos. Tuvimos que reescribir la biblioteca. Desde entonces ha cambiado varias veces, pero ahora hemos eliminado los bloqueos en todos los subsistemas. Por lo tanto, se puede detener rsyslog y no fallar\u00e1 nada.<\/p>\n<p><\/p>\n<p>Es necesario monitorear el tama\u00f1o de las colas, lo que ayuda a evitar cometer estos errores. En primer lugar, podemos monitorear cu\u00e1ndo comenzamos a perder mensajes. En segundo lugar, podemos monitorear si en general tenemos problemas con la entrega.<\/p>\n<p><\/p>\n<p>Y hay otro punto desagradable: la amplificaci\u00f3n de 10 veces en una arquitectura de microservicios es muy f\u00e1cil. No tenemos muchas solicitudes entrantes, pero debido al grafo por el que circulan estos mensajes, debido a los registros de acceso, realmente aumentamos la carga en los registros aproximadamente diez veces. Lamentablemente, no tuve tiempo de calcular cifras exactas, pero los microservicios son as\u00ed. Hay que tenerlo en cuenta. Por lo tanto, en este momento, el subsistema de recopilaci\u00f3n de registros es el m\u00e1s sobrecargado en Lazada. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/d76c6d91613ff77c41b8985cee83218f.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfC\u00f3mo solucionar el problema de elasticsearch? Si necesita obtener r\u00e1pidamente los registros en un solo lugar, para no tener que ir a todas las m\u00e1quinas y recogerlos all\u00ed, use un almacenamiento de archivos. Eso funciona garantizado. Se puede hacer desde cualquier servidor. Solo necesita colocar discos all\u00ed y configurar syslog. Despu\u00e9s de eso, tendr\u00e1 todos los registros garantizados en un solo lugar. Luego podr\u00e1 configurar elasticsearch, graylog o algo m\u00e1s a su ritmo. Pero ya tendr\u00e1 todos los registros y, de hecho, podr\u00e1 almacenarlos tanto como los arrays de disco lo permitan.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/571297f25de76958769f3a4b9bfbf5b9.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En el momento de mi presentaci\u00f3n, el esquema se ve\u00eda as\u00ed. Pr\u00e1cticamente hemos dejado de escribir en archivos. Ahora, probablemente, desconectaremos los remanentes. En las m\u00e1quinas locales donde se ejecutan las API, dejaremos de escribir en archivos. En primer lugar, hay un almacenamiento de archivos que funciona muy bien. En segundo lugar, en estas m\u00e1quinas, el espacio se llena constantemente, hay que monitorearlo continuamente.<\/p>\n<p><\/p>\n<p>Esta parte con Logstash y Graylog realmente est\u00e1 generando problemas. Por eso hay que deshacerse de ella. Hay que elegir una de las dos.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/4a285577708aa1c55c16a72364fa8072.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Decidimos dejar de lado Logstash y Kibana. Porque tenemos un departamento de seguridad. \u00bfCu\u00e1l es la conexi\u00f3n? La conexi\u00f3n es que Kibana, sin X-Pack y sin Shield, no permite diferenciar los derechos de acceso a los registros. Por eso optamos por Graylog. Tiene todo esto. No me gusta, pero funciona. Compramos nuevo hardware, instalamos Graylog fresco y trasladamos todos los registros con formatos estrictos a un Graylog separado. Resolv\u00edmos el problema de diferentes tipos de campos iguales de manera organizativa.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/91b9fdada2648ae1caec05169b11926a.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 incluye realmente el nuevo Graylog? Simplemente lo grabamos todo en Docker. Tomamos un mont\u00f3n de servidores, desplegamos tres instancias de Kafka y 7 servidores de Graylog versi\u00f3n 2.3 (porque quer\u00edamos Elasticsearch versi\u00f3n 5). Todo esto lo levantamos en RAID de HDD. Vimos una tasa de indexaci\u00f3n de hasta 100 mil mensajes por segundo. Vimos la cifra de que 140 terabytes de datos por semana. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/05f9b3c06739548f092bbe271bf8fc54.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00a1Y nuevamente tropiezos! Se avecinan dos ventas. Nos mudamos por 6 millones de mensajes. Graylog no logra procesar todo. De alguna manera, tenemos que sobrevivir nuevamente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/424aa2febc2fd903aabee4aeabb64010.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sobrevivimos de esta manera. Agregamos un poco m\u00e1s de servidores y SSD. En este momento, vivimos de esta forma. Ahora procesamos ya 160 mil mensajes por segundo. A\u00fan no hemos llegado al l\u00edmite, por lo que por ahora no est\u00e1 claro cu\u00e1nto realmente podremos extraer de esto. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/17d84fa7de5403551e55f42345e62a1a.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Estos son nuestros planes para el futuro. De ellos, realmente, lo m\u00e1s importante, probablemente, sea la alta disponibilidad. A\u00fan no la tenemos. Algunas m\u00e1quinas est\u00e1n configuradas de la misma manera, pero todo pasa por una sola m\u00e1quina. Necesitamos dedicar tiempo a configurar el failover entre ellas.<\/p>\n<p><\/p>\n<p>Recoger m\u00e9tricas de Graylog.<\/p>\n<p><\/p>\n<p>Hacer un rate limit para que nuestra API, que se volvi\u00f3 loca, no nos destruya el bandwidth y todo lo dem\u00e1s.<\/p>\n<p><\/p>\n<p>Y finalmente, firmar alg\u00fan SLA con los desarrolladores, indicando que podemos atender hasta esta cantidad. Si ustedes escriben m\u00e1s, lo sentimos.<\/p>\n<p><\/p>\n<p>Y escribir documentaci\u00f3n.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Yuri Bushmelev \u00abMapa de recolecci\u00f3n y entrega de troncos\u00bb \u2014 transcripci\u00f3n del informe\" src=\"\/wp-content\/uploads\/2019\/04\/4a78e2834d5877f8bf17d77a44000c22.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En resumen, los resultados de todo lo que hemos vivido. Primero, est\u00e1ndares. Segundo, syslog \u2014 una delicia. Tercero, rsyslog funciona exactamente como se indica en la diapositiva. Y pasemos a las preguntas.<\/p>\n<p><\/p>\n<p><strong>Preguntas<\/strong>.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfPor qu\u00e9 decidieron no usar\u2026 (filebeat?)<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Necesitamos escribir en un archivo. No quer\u00eda hacerlo en absoluto. Cuando tu API escribe miles de mensajes por segundo, incluso si rotas una vez por hora, sigue sin ser una opci\u00f3n. Se puede escribir en un pipe. A lo que los desarrolladores me preguntaron: \u00ab\u00bfQu\u00e9 pasar\u00e1 si el proceso al que estamos escribiendo se cae?\u00bb Simplemente no encontr\u00e9 qu\u00e9 responderles y dije: \u00abBueno, est\u00e1 bien, no lo hagamos\u00bb.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfPor qu\u00e9 no escriben los registros directamente en HDFS?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Este es el siguiente paso. Lo pensamos desde un principio, pero, como en este momento no hay recursos para trabajar en ello, queda como una soluci\u00f3n a largo plazo.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: Un formato columnar ser\u00eda m\u00e1s adecuado.<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Entiendo todo. Estamos \"a favor\" con ambas manos. <\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: Escriben en rsyslog. Ah\u00ed se puede usar TCP y UDP. Pero si es UDP, \u00bfc\u00f3mo garantizan la entrega?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Hay dos puntos. Primero, les digo desde el principio que no garantizamos la entrega de los registros. Porque cuando los desarrolladores vienen y dicen: 'Vamos a empezar a escribir datos financieros ah\u00ed, y ustedes los almacenar\u00e1n en alg\u00fan lugar por si algo sucede', nosotros les respondemos '\u00a1Genial! Vamos a hacer que se bloqueen en la escritura en el socket y a hacer esto en transacciones, para que nos aseguren que lo han puesto en el socket y verifiquen que lo recibimos por el otro lado.' En ese momento, a todos se les quita el inter\u00e9s. Y si no est\u00e1n interesados, \u00bfcu\u00e1les son nuestras preguntas? Si no quieren garantizar la escritura en el socket, \u00bfpor qu\u00e9 debemos garantizar la entrega? Hacemos un esfuerzo m\u00e1ximo. Realmente intentamos entregar tanto como sea posible y lo mejor que podamos, pero no damos garant\u00edas del 100%. As\u00ed que no deben escribir datos financieros ah\u00ed. Para eso hay bases de datos con transacciones.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: Cuando una API genera alg\u00fan mensaje en el registro y pasa el control a los microservicios, \u00bfno han tenido el problema de que los mensajes de diferentes microservicios llegan en un orden incorrecto? Esto causa confusi\u00f3n.<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Es normal que lleguen en diferente orden. Hay que estar preparados para ello. Porque cualquier entrega a trav\u00e9s de la red no garantiza el orden, o hay que gastar recursos espec\u00edficamente para eso. Si tomamos los almacenes de archivos, cada API guarda los registros en su propio archivo. M\u00e1s bien, rsyslog los distribuye en carpetas. Cada API tiene sus propios registros a los que se puede acceder y luego se pueden correlacionar por timestamp en ese registro. Si van a ver en Graylog, all\u00ed est\u00e1n ordenados por timestamp. Todo estar\u00e1 bien.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: El timestamp puede diferir en milisegundos.<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: El timestamp lo genera la API misma. Esa es la esencia. Nosotros tenemos NTP. La API genera el timestamp ya en el propio mensaje. No lo agrega rsyslog.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: No est\u00e1 muy claro c\u00f3mo interact\u00faan los centros de datos. Dentro de un centro de datos se entiende c\u00f3mo se recopilan y procesan los logs. \u00bfC\u00f3mo se produce la interacci\u00f3n entre los centros de datos? \u00bfO cada centro de datos vive su propia vida?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Casi. Cada pa\u00eds est\u00e1 en alg\u00fan centro de datos espec\u00edfico. No tenemos, en este momento, una dispersi\u00f3n de un pa\u00eds a varios centros de datos. As\u00ed que no es necesario fusionarlos. Dentro de cada centro hay un Log Relay. Es un servidor Rsyslog. En realidad, hay dos m\u00e1quinas de gesti\u00f3n. Est\u00e1n configuradas de la misma manera. Pero, por ahora, el tr\u00e1fico solo pasa por una de ellas. Esta agrega todos los logs. Tiene una cola en disco por si acaso. Comprime los logs y los env\u00eda al centro de datos central (el de Singapur), donde luego se env\u00edan a Graylog. Y en cada centro de datos hay su propio almacenamiento de archivos. En caso de que perdamos la conexi\u00f3n, tenemos todos los logs ah\u00ed. Permanecer\u00e1n all\u00ed. Ser\u00e1n guardados.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfRecibes logs de ah\u00ed en situaciones excepcionales?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Se puede ir all\u00ed (al almacenamiento de archivos) y revisar.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfC\u00f3mo monitorean para asegurarse de que no pierden logs?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: En realidad, los perdemos, y lo estamos monitoreando. Iniciamos el monitoreo hace un mes. En la biblioteca que utiliza la API de Go, hay m\u00e9tricas. Puede contar cu\u00e1ntas veces no pudo escribir en el socket. Actualmente, hay una heur\u00edstica inteligente. Hay un b\u00fafer. Intenta escribir mensajes en el socket desde \u00e9l. Si el b\u00fafer se llena, comienza a descartarlos. Y cuenta cu\u00e1ntos ha descartado. Si los contadores comienzan a llenarse, nos enteramos. Ahora llegan a Prometheus y se pueden ver gr\u00e1ficos en Grafana. Se pueden configurar alertas. Pero por ahora no est\u00e1 claro a qui\u00e9n enviarlas.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: En Elasticsearch almacenar logs con redundancia. \u00bfCu\u00e1ntas r\u00e9plicas tienen?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Una r\u00e9plica.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfEs solo una r\u00e9plica?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Es un maestro y una r\u00e9plica. Los datos se almacenan en dos instancias.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfHas ajustado de alguna manera el tama\u00f1o del b\u00fafer de rsyslog? <\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Estamos escribiendo datagramas en un socket unix personalizado. Esto nos impone de inmediato una limitaci\u00f3n de 128 kilobytes. No podemos escribir m\u00e1s que eso. Lo hemos establecido en el est\u00e1ndar. Aquellos que quieren acceder a los storages, escriben 128 kilobytes. Las bibliotecas, de hecho, recortan y colocan una bandera indicando que el mensaje fue recortado. En nuestro est\u00e1ndar del propio mensaje hay un campo especial que muestra si fue recortado al escribir o no. As\u00ed que tenemos la capacidad de rastrear ese aspecto.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfEscriben JSON da\u00f1ados? <\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: El JSON da\u00f1ado ser\u00e1 descartado ya sea durante el relay, porque el paquete es demasiado grande, o ser\u00e1 descartado por Graylog, ya que no podr\u00e1 parsear el JSON. Pero aqu\u00ed hay matices que deben corregirse, y la mayor\u00eda de ellos est\u00e1n relacionados con rsyslog. Ya he registrado all\u00ed varios problemas que a\u00fan debemos abordar.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfPor qu\u00e9 Kafka? \u00bfHan probado RabbitMQ? \u00bfGraylog no se desempe\u00f1a bien bajo tales cargas?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: No tenemos buena experiencia con Graylog. Con \u00e9l realmente es problem\u00e1tico. Es una cosa peculiar. Y, en realidad, no lo necesitamos. Preferir\u00eda escribir directamente desde rsyslog a Elasticsearch y luego ver en Kibana. Pero necesitamos resolver el tema con los de seguridad. Esta es una posible direcci\u00f3n de nuestro desarrollo, cuando desecharemos Graylog y usaremos Kibana. No tiene sentido usar Logstash. Porque puedo hacer exactamente lo mismo con rsyslog. Y tiene un m\u00f3dulo para escribir en Elasticsearch. Estamos tratando de lidiar con Graylog. Incluso lo hemos afinado un poco. Pero a\u00fan hay espacio para mejoras.<\/p>\n<p><\/p>\n<p>Sobre Kafka. Hist\u00f3ricamente, as\u00ed ha sido. Cuando llegu\u00e9, ya exist\u00eda y se estaban registrando logs en ella. Simplemente levantamos nuestro cl\u00faster y trasladamos los logs a \u00e9l. Lo gestionamos, sabemos c\u00f3mo est\u00e1 funcionando. En cuanto a RabbitMQ... no nos llevamos bien con RabbitMQ. Pero con RabbitMQ tenemos una buena relaci\u00f3n. Lo tenemos en producci\u00f3n y tuvimos problemas con \u00e9l. Poco antes de las rebajas le hicimos ajustes y empez\u00f3 a funcionar bien. Pero antes de eso, no estaba listo para ponerlo en producci\u00f3n. Hay otro aspecto. Graylog puede leer la versi\u00f3n AMQP 0.9, mientras que rsyslog puede escribir la versi\u00f3n AMQP 1.0. No hay soluci\u00f3n alguna que maneje ambos. Solo hay una o la otra. Por lo tanto, por el momento, solo Kafka. Pero tambi\u00e9n tiene sus matices. Porque omkafka de la versi\u00f3n de rsyslog que usamos puede perder todo el buffer de mensajes que ha recopilado de rsyslog. Por ahora, tenemos que vivir con eso. <\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfUtilizan Kafka porque ya la ten\u00edan? \u00bfNo se utiliza para otros prop\u00f3sitos?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: La Kafka que ten\u00edan est\u00e1 siendo utilizada por el equipo de Data Science. Es un proyecto completamente separado, del que, lamentablemente, no puedo decir mucho. No estoy al tanto. Estaba bajo la responsabilidad del equipo de Data Science. Decidieron usarla al empezar a registrar logs, para no instalar otra. Ahora hemos actualizado Graylog y hemos perdido la compatibilidad porque hay una versi\u00f3n antigua de Kafka. Tuvimos que establecer la nuestra. Adem\u00e1s, nos deshicimos de esos cuatro t\u00f3picos para cada API. Creamos un \u00fanico t\u00f3pico ancho para todos los live, un t\u00f3pico ancho para todos los staging y simple y sencillamente estamos enviando todos los logs all\u00ed. Graylog est\u00e1 recogiendo todo eso en paralelo.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: \u00bfPor qu\u00e9 es necesario este tipo de ajustes con los sockets? \u00bfHan probado utilizar el controlador de logs syslog para los contenedores?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: En el momento en que est\u00e1bamos abordando este tema, nuestra relaci\u00f3n con Docker era tensa. Era Docker 1.0 o 0.9. Docker en s\u00ed era extra\u00f1o. En segundo lugar, si encima se intentaban meter los logs... Tengo una sospecha no comprobada de que pasa todos los logs a trav\u00e9s de su demonio. Si una de nuestras APIs se vuelve loca, las otras APIs se atascan porque no pueden enviar stdout y stderr. No s\u00e9 a d\u00f3nde conducir\u00e1 esto. Tengo una sospecha, a nivel de intuici\u00f3n, de que no deber\u00edamos usar el controlador syslog de Docker en este lugar. Nuestro departamento de pruebas funcionales tiene su propio peque\u00f1o cl\u00faster de Graylog para los logs. Ellos usan los controladores de logs de Docker y, al parecer, les va bastante bien. Pero ellos escriben directamente en Graylog utilizando GELF. En ese momento, cuando comenzamos con todo esto, solo necesit\u00e1bamos que funcionara. Quiz\u00e1s m\u00e1s adelante, cuando alguien venga y diga que ya lleva funcionando bien un tiempo, lo intentaremos.<\/p>\n<p><\/p>\n<p><strong>Pregunta<\/strong>: Hacen la entrega entre centros de datos con rsyslog. \u00bfPor qu\u00e9 no con Kafka?<\/p>\n<p><\/p>\n<p><strong>Respuesta<\/strong>: Hacemos ambas cosas, en realidad. Por dos razones. Si el canal est\u00e1 completamente da\u00f1ado, ni siquiera todos nuestros logs en versi\u00f3n comprimida pasan a trav\u00e9s de \u00e9l. Kafka nos permite simplemente perderlos en el proceso. De esta manera, evitamos que esos logs se queden atascados. En este caso, usamos Kafka directamente. Si el canal es bueno y queremos liberarlo, utilizamos rsyslog. Pero en realidad, podr\u00eda configurarse para que eliminara autom\u00e1ticamente lo que no pudo pasar. Actualmente, usamos rsyslog directamente en algunos lugares y Kafka en otros.<\/p>\n<p>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/450098\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041b\u043e\u0433\u0438 \u2014 \u0432\u0430\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 (\u043b\u0438\u0431\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442), \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f. \u0412 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043b\u043e\u0433\u0430\u043c\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u044b. \u041d\u0443\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u043a\u0443\u0447\u0443 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432: \u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c \u043b\u043e\u0433\u0438 \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f; \u043a\u0443\u0434\u0430 \u043f\u0438\u0441\u0430\u0442\u044c \u043b\u043e\u0433\u0438; \u043a\u0430\u043a \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043b\u043e\u0433\u0438 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438; \u043a\u0430\u043a \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043b\u043e\u0433\u0438. \u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043d\u044b\u043d\u0435 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24507,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32723","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041b\u043e\u0433\u0438 \u2014 \u0432\u0430\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 (\u043b\u0438\u0431\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442), \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f. \u0412 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043b\u043e\u0433\u0430\u043c\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u044b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/yurij-bushmelev-karta-grablej-na-pole-sbora-i-dostavki-logov-rasshifrovka-doklada\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u042e\u0440\u0438\u0439 \u0411\u0443\u0448\u043c\u0435\u043b\u0435\u0432 \u00ab\u041a\u0430\u0440\u0442\u0430 \u0433\u0440\u0430\u0431\u043b\u0435\u0439 \u043d\u0430 \u043f\u043e\u043b\u0435 \u0441\u0431\u043e\u0440\u0430 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043b\u043e\u0433\u043e\u0432\u00bb \u2014 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041b\u043e\u0433\u0438 \u2014 \u0432\u0430\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 (\u043b\u0438\u0431\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442), \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f. \u0412 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043b\u043e\u0433\u0430\u043c\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u044b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/yurij-bushmelev-karta-grablej-na-pole-sbora-i-dostavki-logov-rasshifrovka-doklada\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:48:35+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:48:35+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Yuri Bushmelev \"Mapa de problemas en la recolecci\u00f3n y entrega de logs\" - transcripci\u00f3n de la presentaci\u00f3n | ProHoster","description":"Los logs son una parte importante del sistema que permite entender si est\u00e1 funcionando (o no) como se espera. En un entorno de arquitectura microservicios, trabajar con logs se convierte en una disciplina por s\u00ed misma.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/yurij-bushmelev-karta-grablej-na-pole-sbora-i-dostavki-logov-rasshifrovka-doklada","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u042e\u0440\u0438\u0439 \u0411\u0443\u0448\u043c\u0435\u043b\u0435\u0432 \u00ab\u041a\u0430\u0440\u0442\u0430 \u0433\u0440\u0430\u0431\u043b\u0435\u0439 \u043d\u0430 \u043f\u043e\u043b\u0435 \u0441\u0431\u043e\u0440\u0430 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043b\u043e\u0433\u043e\u0432\u00bb \u2014 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 | ProHoster","og:description":"\u041b\u043e\u0433\u0438 \u2014 \u0432\u0430\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 (\u043b\u0438\u0431\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442), \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f. \u0412 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043b\u043e\u0433\u0430\u043c\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u044b.","og:url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/yurij-bushmelev-karta-grablej-na-pole-sbora-i-dostavki-logov-rasshifrovka-doklada","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:48:35+00:00","article:modified_time":"2019-10-31T18:48:35+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32723","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 12:16:55","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:53:25","updated":"2026-01-21 12:16:55","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/32723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=32723"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/32723\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/24507"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=32723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=32723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=32723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}