{"id":96515,"date":"2020-10-12T19:43:02","date_gmt":"2020-10-12T17:43:02","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019"},"modified":"2020-10-12T19:43:02","modified_gmt":"2020-10-12T17:43:02","slug":"odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","title":{"rendered":"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6c445191705a4c96939cd094bc457a53.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En la presentaci\u00f3n, Andrey Borodin explicar\u00e1 c\u00f3mo tuvieron en cuenta la experiencia de escalar PgBouncer al dise\u00f1ar el pooler de conexiones <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\">Odisea<\/a><\/noindex>, c\u00f3mo lo implementaron en producci\u00f3n. Adem\u00e1s, discutiremos qu\u00e9 funciones nos gustar\u00eda ver en nuevas versiones del pooler: es importante para nosotros no solo satisfacer nuestras necesidades, sino tambi\u00e9n desarrollar la comunidad de usuarios <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\">Odisea<\/a><\/noindex>.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Video:<\/p>\n<p>\n<center><div class=\"youtube-placeholder\" data-id=\"OUx40ABHFZY\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/OUx40ABHFZY\/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><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/dd2ea50b72e3d9c4e795aecbf9afdd25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00a1Hola a todos! Me llamo Andrey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0a2f1880005bec1f61b72fb23b555adc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En Yandex, me dedico al desarrollo de bases de datos de c\u00f3digo abierto. Hoy tenemos un tema sobre el pooler de conexiones. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c18e7c937423d2514faa12e820e78e70.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Si sabes c\u00f3mo llamar a un pooler de conexiones en espa\u00f1ol, h\u00e1zmelo saber. Tengo muchas ganas de encontrar un buen t\u00e9rmino t\u00e9cnico que se establezca en la literatura t\u00e9cnica. <\/p>\n<p><\/p>\n<p>El tema es bastante complejo, porque en muchas bases de datos el pooler de conexiones est\u00e1 integrado y ni siquiera es necesario conocerlo. Hay algunas configuraciones que, por supuesto, existen en todas partes, pero en Postgres no resulta as\u00ed. Y paralelamente (en HighLoad++ 2019) hay una presentaci\u00f3n de Nikolai Samokhvalov sobre la configuraci\u00f3n de consultas en Postgres. Y entiendo que aqu\u00ed han venido personas que ya han configurado consultas a la perfecci\u00f3n, y son personas que enfrentan problemas sist\u00e9micos m\u00e1s raros relacionados con la red y la utilizaci\u00f3n de recursos. Y a veces esto puede ser bastante complicado en cuanto a que los problemas no son evidentes.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/89c660dd530575e2938e6bf312b83e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En Yandex hay Postgres. En Yandex.Cloud viven muchos servicios de Yandex. Y tenemos varios petabytes de datos que generan no menos de un mill\u00f3n de consultas por segundo en Postgres. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/288bfa37b9dcd60acd22ba48f0ef8a39.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y proporcionamos un cl\u00faster bastante t\u00edpico a todos los servicios: esta es la principal nodo primaria, junto con dos replicas (s\u00edncrona y as\u00edncrona), copias de seguridad y escalado de consultas de lectura en la r\u00e9plica. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c249ca55bb387e25a5560324024cc523.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cada nodo del cl\u00faster es un Postgres, en el que adem\u00e1s de Postgres y sistemas de monitoreo, se ha instalado un pooler de conexiones. El pooler de conexiones se utiliza para fencing y por su prop\u00f3sito principal. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0e29be55cc048007db21c80bbb08a9d4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfCu\u00e1l es el prop\u00f3sito principal del pooler de conexiones? <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e2fbbd440c2781573cb35deeef358f20.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En Postgres se adopta un modelo de procesos al trabajar con la base de datos. Esto significa que una conexi\u00f3n es un proceso, un backend de Postgres. Y en este backend hay muchos tipos de cach\u00e9s que son bastante costosos de hacer diferentes para distintas conexiones. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/587498063b1af8fac4a845961c654bc2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Adem\u00e1s, en el c\u00f3digo de Postgres hay una matriz llamada procArray. Contiene los datos b\u00e1sicos sobre las conexiones de red. Y casi todos los algoritmos de procesamiento de procArray tienen una complejidad lineal, recorren toda la matriz de conexiones de red. Este es un ciclo bastante r\u00e1pido, pero con un gran n\u00famero de conexiones de red entrantes, todo se vuelve un poco m\u00e1s costoso. Y cuando todo se vuelve un poco m\u00e1s caro, al final se puede pagar un precio muy alto por un gran n\u00famero de conexiones de red. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/b534a38d0bfae7a65fc4258155a50280.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Existen 3 enfoques posibles:<\/p>\n<p><\/p>\n<ul>\n<li>En el lado de la aplicaci\u00f3n. <\/li>\n<li>En el lado de la base de datos. <\/li>\n<li>Y en medio, es decir, varias combinaciones. <\/li>\n<\/ul>\n<p><\/p>\n<p>Desafortunadamente, el pooler integrado est\u00e1 actualmente en desarrollo. Los amigos de PostgreSQL Professional se encargan principalmente de esto. Cuando aparezca, es dif\u00edcil de predecir. Y de hecho, tenemos dos soluciones disponibles para el arquitecto. Es el pool de lado de la aplicaci\u00f3n y el pool proxy. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/702527a09e9fc86dd39b7fd69dcf1fc9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>El pool de lado de la aplicaci\u00f3n es la forma m\u00e1s simple. Y casi todos los controladores de cliente te proporcionan una forma de presentar millones de tus conexiones en el c\u00f3digo como unas pocas decenas de conexiones en la base de datos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7b66b9e20d22f472ca5ac39f6b9e0ba4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Surge el problema de que en alg\u00fan momento quieres escalar el backend, quieres desplegarlo en m\u00faltiples m\u00e1quinas virtuales. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f216fd7a8c01c2b07891e2242c48b06a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Luego tambi\u00e9n te das cuenta de que tienes varias zonas de disponibilidad, varios centros de datos. Y el enfoque de pooling del lado del cliente lleva a grandes n\u00fameros. Grandes son alrededor de 10,000 conexiones. Ese es el l\u00edmite en el que puede funcionar adecuadamente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e5bc5f284fd8ff568bbe16c3895b7ac6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En cuanto a los poolers proxy, hay dos poolers que pueden hacer muchas cosas. No solo son poolers. Son poolers + funcionalidad adicional genial. Esto es <noindex><a rel=\"nofollow\" href=\"https:\/\/www.pgpool.net\/\">Pgpool<\/a><\/noindex> y <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CrunchyData\/crunchy-proxy\">Crunchy-Proxy<\/a><\/noindex>. <\/p>\n<p><\/p>\n<p>Pero, desafortunadamente, esta funcionalidad adicional no es necesaria para todos. Y lleva a que los poolers solo admitan el pooling por sesi\u00f3n, es decir, un cliente entrante, un cliente saliente en la base de datos. <\/p>\n<p><\/p>\n<p>Para nuestras tareas, esto no se adapta muy bien, por eso usamos PgBouncer, que implementa el pooling por transacciones, es decir, las conexiones del servidor se emparejan con las conexiones del cliente solo durante el tiempo de la transacci\u00f3n. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e5fedbe14656d2ac2cde8d1878a950e2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y bajo nuestra carga, esto es cierto. <strong>Pero hay varios problemas.<\/strong>.<img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/61fd36cadcd9948d624dafa711777307.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Los problemas comienzan cuando quieres diagnosticar una sesi\u00f3n, porque todas las conexiones entrantes son locales. Todas vinieron del loopback y trazar una sesi\u00f3n se vuelve complicado. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/36108c4956c410a1b1f286a88bc393d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Por supuesto, puedes utilizar application_name_add_host. Esta es una manera de que Bouncer a\u00f1ada una direcci\u00f3n IP a application_name. Pero application_name se establece mediante una conexi\u00f3n adicional. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/b4cec483aa776f48db7ad3966c3b78e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En este gr\u00e1fico, donde la l\u00ednea amarilla representa las solicitudes reales, y donde la l\u00ednea azul las solicitudes que llegan a la base de datos. Y esta diferencia es precisamente la configuraci\u00f3n de application_name, que se necesita solo para el seguimiento, pero no es en absoluto gratuita. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c02ea73a6f1a2a4cd6af6c621f321ab4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Adem\u00e1s, en Bouncer no se puede limitar un pool, es decir, el n\u00famero de conexiones a la base de datos de un usuario espec\u00edfico, para una base de datos espec\u00edfica. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/3431a463e04106066e2799aead66f571.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00bfA d\u00f3nde lleva esto? Tienes un servicio sobrecargado, escrito en C++, y cerca de \u00e9l un peque\u00f1o servicio en node que no hace nada grave con la base de datos, pero su controlador se vuelve loco. Abre 20,000 conexiones, y todo lo dem\u00e1s tendr\u00e1 que esperar. Tu c\u00f3digo est\u00e1 bien. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d7fa321714dc017b017945dffcf79bc6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Desde luego, escribimos un peque\u00f1o parche para Bouncer que a\u00f1adi\u00f3 esta configuraci\u00f3n, es decir, la limitaci\u00f3n de clientes en el pool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d58884fc5ac0f90ff8442f126972157a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Se podr\u00eda hacer del lado de Postgres, es decir, limitar el n\u00famero de conexiones para los roles en la base de datos.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/8d6ff70db72964ed4eae5eaa47309931.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pero entonces pierdes la capacidad de entender por qu\u00e9 no tienes conexiones con el servidor. PgBouncer no transmite el error de conexi\u00f3n, siempre devuelve la misma informaci\u00f3n. Y no puedes comprender: tal vez tu contrase\u00f1a ha cambiado, tal vez la base de datos simplemente se ha ca\u00eddo, tal vez algo no est\u00e1 bien. Pero no hay diagn\u00f3stico. Si no se puede establecer la sesi\u00f3n, no sabr\u00e1s por qu\u00e9 no se puede hacer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cb3048344a94f2953bf403485d28e69f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En alg\u00fan momento observas las gr\u00e1ficas de la aplicaci\u00f3n y ves que la aplicaci\u00f3n no est\u00e1 funcionando.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e67c6680bb9a7f41242af9f9e4920916.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Miras el top y ves que Bouncer es de un solo hilo. Este es un punto de inflexi\u00f3n en la vida del servicio. Te das cuenta de que te preparabas para la escalabilidad de la base de datos en un a\u00f1o y medio, pero ahora necesitas escalar el pooler. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4c140c4ba6db19cb9939c1148638fb73.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Llegamos a la conclusi\u00f3n de que necesitamos m\u00e1s PgBouncer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d369f572a66c16a8917e13393324a644.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/lwn.net\/Articles\/542629\/\">https:\/\/lwn.net\/Articles\/542629\/<\/a><\/noindex><\/p>\n<p><\/p>\n<p>Hicimos algunos peque\u00f1os parches a Bouncer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/97755489a25ebfe38efd56ff897bd8fa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y configuramos que se puedan levantar varios Bouncers reutilizando el puerto TCP. Y ya el sistema operativo redistribuye autom\u00e1ticamente las conexiones TCP entrantes entre ellos de manera round-robin.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/ac30d3f067de2a8cd66ad2325c3a3b58.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esto es transparente para los clientes, es decir, todo parece que tienes un solo Bouncer, pero tienes una fragmentaci\u00f3n de conexiones inactivas entre los Bouncers en funcionamiento. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/53825f075db00b026c12013a610be456.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y en un momento determinado, puede notar que estos 3 Bouncers est\u00e1n utilizando cada uno su n\u00facleo al 100%. Necesita bastante Bouncers. \u00bfPor qu\u00e9? <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/66c17883a043e157cd7ceab2c2a4e326.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Porque tiene TLS. Tiene una conexi\u00f3n cifrada. Y si hace benchmarks de Postgres con TLS y sin TLS, descubrir\u00e1 que el n\u00famero de conexiones establecidas disminuye casi en dos \u00f3rdenes de magnitud con la inclusi\u00f3n del cifrado, porque el apret\u00f3n de manos de TLS consume recursos de la CPU. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6101121ebe136af16e5eb1a484c65d66.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y en la parte superior, puede ver varias funciones criptogr\u00e1ficas que se llevan a cabo durante la oleada de conexiones entrantes. Dado que nuestro primary puede cambiar entre zonas de disponibilidad, la oleada de conexiones entrantes es una situaci\u00f3n bastante t\u00edpica. Es decir, por alguna raz\u00f3n, el antiguo primary no estaba disponible, y toda la carga fue enviada a otro centro de datos. Todos llegar\u00e1n al mismo tiempo para saludar con TLS. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c238ac2f511568590dc275e01c192c00.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y una gran cantidad de apret\u00f3n de manos de TLS puede no saludar ya a Bouncer, sino que puede ahogarlo. Debido al tiempo de espera, la oleada de conexiones entrantes puede volverse inagotable. Si tiene reintentos en la base sin un backoff exponencial, no llegar\u00e1n una y otra vez como una ola coherente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f42d0b210174d4d172254603ae6b834a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aqu\u00ed hay un ejemplo de 16 PgBouncers que utilizan 16 n\u00facleos al 100%.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/8d048d3774c09e5b6a3fb3c7bff62084.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hemos llegado al PgBouncer en cascada. Esta es la mejor configuraci\u00f3n que se puede alcanzar con nuestra carga con Bouncer. Los Bouncers externos sirven para el apret\u00f3n de manos TCP, mientras que los Bouncers internos sirven para el pooling real, para no fragmentar demasiado las conexiones externas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/3a4ee4ea46d5fe8479a5a7222ee134da.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En tal configuraci\u00f3n, es posible un reinicio suave. Puede reiniciar todos estos 18 Bouncers uno por uno. Pero mantener tal configuraci\u00f3n es bastante dif\u00edcil. Los administradores del sistema, los DevOps y las personas que realmente son responsables de este servidor no estar\u00e1n muy contentos con tal esquema. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/5291fe67dbe02036f3ff8e98bdd84d1b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aparentemente, podr\u00edamos promover todas nuestras mejoras en open source, pero Bouncer no tiene un buen soporte. Por ejemplo, la capacidad de ejecutar m\u00faltiples PgBouncers en un solo puerto se comprometi\u00f3 hace un mes. Y la solicitud de incorporaci\u00f3n con esta funci\u00f3n fue hace varios a\u00f1os. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/2059d7f49649d136249103db4aa3ec19.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/libpq-cancel.html\">https:\/\/www.postgresql.org\/docs\/current\/libpq-cancel.html<\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pgbouncer\/pgbouncer\/pull\/79\">https:\/\/github.com\/pgbouncer\/pgbouncer\/pull\/79<\/a><\/noindex><\/p>\n<p><\/p>\n<p>O otro ejemplo. En Postgres, puedes cancelar una consulta en ejecuci\u00f3n enviando un secreto a otra conexi\u00f3n sin autenticaci\u00f3n adicional. Pero algunos clientes simplemente env\u00edan un TCP-reset, es decir, rompen la conexi\u00f3n de red. \u00bfQu\u00e9 har\u00e1 Bouncer en ese caso? No har\u00e1 nada. Continuar\u00e1 ejecutando la consulta. Si tienes una enorme cantidad de conexiones que han saturado la base de datos con peque\u00f1as consultas, simplemente desconectar de Bouncer no ser\u00e1 suficiente, tambi\u00e9n tendr\u00e1s que terminar aquellas consultas que est\u00e1n corriendo en la base de datos. <\/p>\n<p><\/p>\n<p>Esto se ha parcheado y este problema a\u00fan no se ha fusionado en el upstream de Bouncer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a9695b6d9e640a5543dc73429eb0050b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>As\u00ed llegamos a la conclusi\u00f3n de que necesitamos nuestro propio pool de conexiones, que se desarrollar\u00e1, ser\u00e1 parcheado, en el que podamos corregir problemas de manera r\u00e1pida y que, por supuesto, debe ser multihilo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e755cd9b06a004f0eced1dc12fd3a6fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hemos establecido la multihilo como una tarea principal. Necesitamos manejar bien la ola de conexiones TLS entrantes. <\/p>\n<p><\/p>\n<p>Para esto, tuvimos que desarrollar una biblioteca separada llamada Machinarium, dise\u00f1ada para describir los estados de las m\u00e1quinas de una conexi\u00f3n de red como c\u00f3digo secuencial. Si miras el c\u00f3digo fuente de libpq, ver\u00e1s llamadas bastante complejas que pueden devolverte un resultado y decir: 'Ll\u00e1mame un poco m\u00e1s tarde. Ahora tengo IO, pero cuando termine con IO, tendr\u00e9 carga para el procesador'. Y esto es un esquema de m\u00faltiples niveles. La interacci\u00f3n en red generalmente se describe como una m\u00e1quina de estados, con muchas reglas como 'Si anteriormente recib\u00ed un encabezado de paquete de tama\u00f1o N, ahora espero N bytes' o 'Si envi\u00e9 un paquete SYNC, ahora espero un paquete con los metadatos del resultado'. Esto resulta en un c\u00f3digo bastante dif\u00edcil de entender, como si un laberinto se convirtiera en un despliegue lineal. Hicimos que, en lugar de una m\u00e1quina de estados, el programador describa el camino principal de la interacci\u00f3n en c\u00f3digo imperativo com\u00fan. Simplemente, en este c\u00f3digo imperativo se deben insertar lugares donde la secuencia de ejecuci\u00f3n deba ser interrumpida para esperar datos de la red, pasando el contexto de ejecuci\u00f3n a otra corrutina (green thread). Este enfoque es similar a que anotamos el camino m\u00e1s esperado del laberinto secuencialmente y luego agregamos a \u00e9l ramificaciones. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a6bfb4b11961c7db3a7c7184674e3bc2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Al final, tenemos un hilo que hace TCP accept y, mediante round-robin, transmite una conexi\u00f3n TPC a m\u00faltiples trabajadores. <\/p>\n<p><\/p>\n<p>Cada conexi\u00f3n del cliente siempre funciona en un solo procesador. Esto permite que sea amigable con el cach\u00e9. <\/p>\n<p><\/p>\n<p>Adem\u00e1s, hemos mejorado la recolecci\u00f3n de peque\u00f1os paquetes en uno grande para reducir la carga del TCP-stack del sistema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7d740c23baecdd2f993c83cd54a0a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tambi\u00e9n hemos optimizado el pooling transaccional de manera que Odyssey, con la configuraci\u00f3n adecuada, puede enviar CANCEL y ROLLBACK en caso de interrupci\u00f3n de la conexi\u00f3n de red, es decir, si nadie est\u00e1 esperando la solicitud, Odyssey le indicar\u00e1 a la base de datos que no se esfuerce en ejecutar esa solicitud que podr\u00eda consumir recursos valiosos.<\/p>\n<p><\/p>\n<p>Y, en la medida de lo posible, mantenemos las conexiones con el mismo cliente. Esto evita reinstalar application_name_add_host. Si es posible, no hay reinstalaci\u00f3n adicional de par\u00e1metros necesarios para diagn\u00f3stico. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/afb2fb7fb16d65c9ea73a8978d1eb83c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Trabajamos en inter\u00e9s de Yandex.Cloud. Si utiliza PostgreSQL gestionado y tiene un connection pooler configurado, puede crear replicaci\u00f3n l\u00f3gica hacia afuera, es decir, irse de nosotros si lo desea, mediante replicaci\u00f3n l\u00f3gica. El Bouncer no entregar\u00e1 el flujo de replicaci\u00f3n l\u00f3gica hacia afuera. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c53defc92ebd8f3bec57ce64d97b9f72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Este es un ejemplo de configuraci\u00f3n de replicaci\u00f3n l\u00f3gica. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/a37d9d1abf288d17fa646b642e8b62ab.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Adem\u00e1s, tenemos soporte para replicaci\u00f3n f\u00edsica hacia afuera. En la Nube, por supuesto, esto no es posible porque entonces su cl\u00faster dar\u00eda demasiada informaci\u00f3n sobre s\u00ed mismo. Sin embargo, en sus instalaciones, si necesita replicaci\u00f3n f\u00edsica a trav\u00e9s del connection pooler en Odyssey, es posible. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/572934ce5b08115e57ab4b55d2153c6d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En Odyssey, hay un monitoreo completamente compatible con PgBouncer. Tenemos una consola similar que ejecuta casi los mismos comandos. Si falta algo, env\u00edenos un pull request o al menos un issue en GitHub, y estaremos encantados de agregar los comandos necesarios. Pero ya tenemos la funcionalidad principal de la consola de PgBouncer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/451dd798fb3523a7a174ebfe00a14bc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y, por supuesto, tenemos el reenv\u00edo de errores. Devolveremos el error que inform\u00f3 la base de datos. Recibir\u00e1 informaci\u00f3n sobre por qu\u00e9 no puede acceder a la base, en lugar de simplemente que no puede acceder. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/14b4cb0efa33a2658dfc528349a5382f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esta capacidad se puede desactivar en caso de que necesite una compatibilidad del 100% con PgBouncer. Podemos comportarnos igual que el Bouncer, por si acaso. <\/p>\n<p><\/p>\n<p><strong>Desarrollo<\/strong><\/p>\n<p><\/p>\n<p>Algunas palabras sobre el c\u00f3digo fuente de Odyssey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6055d5ec9676c331a83592916a6a292f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\/pull\/66\">https:\/\/github.com\/yandex\/odyssey\/pull\/66<\/a><\/noindex><\/p>\n<p><\/p>\n<p>Por ejemplo, hay comandos como \u00abPause \/ Resume\u00bb. Normalmente se utilizan para actualizar la base de datos. Si necesitas actualizar Postgres, puedes ponerlo en pausa en el pool de conexiones, hacer un pg_upgrade y luego reanudarlo. Desde el lado del cliente, parecer\u00e1 que la base de datos simplemente se detuvo. Esta funcionalidad fue tra\u00edda por personas de la comunidad. A\u00fan no ha sido fusionada, pero pronto estar\u00e1 disponible. (Ya est\u00e1 fusionada)<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/d2f7c57e0ae3e466ec2a701bbdb8eb3f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\/pull\/73\">https:\/\/github.com\/yandex\/odyssey\/pull\/73<\/a><\/noindex> \u2014 ya est\u00e1 fusionada<\/p>\n<p><\/p>\n<p>Adem\u00e1s, una de las nuevas caracter\u00edsticas de PgBouncer es el soporte para la autenticaci\u00f3n SCRAM, tambi\u00e9n tra\u00edda por una persona que no trabaja en Yandex.Cloud. Ambas funcionalidades son complejas e importantes. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/f39346a543c88d17728233d05c2dff19.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Por eso, quiero contarles de qu\u00e9 est\u00e1 hecho Odyssey, quiz\u00e1s tambi\u00e9n quieran escribir un poco de c\u00f3digo. <\/p>\n<p><\/p>\n<p>Tienes la base Odyssey, que se basa en dos bibliotecas principales. La biblioteca Kiwi es una implementaci\u00f3n del protocolo de mensajes de Postgres. Es decir, el proto 3 nativo de Postgres son los mensajes est\u00e1ndar que los frontends y backends pueden intercambiar. Esto est\u00e1 implementado en la biblioteca Kiwi.<\/p>\n<p><\/p>\n<p>La biblioteca Machinarium es la implementaci\u00f3n de flujos. Un peque\u00f1o fragmento de este Machinarium est\u00e1 escrito en ensamblador. Pero no se asusten, son solo 15 l\u00edneas. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cd18f250af50eabd53536b2c0d7f12b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Arquitectura de Odyssey. Hay una m\u00e1quina principal donde se ejecutan corutinas. En esta m\u00e1quina se realiza la aceptaci\u00f3n de conexiones TCP entrantes y su distribuci\u00f3n a los workers. <\/p>\n<p><\/p>\n<p>Dentro de un worker puede trabajar un manejador de varios clientes. Adem\u00e1s, en el hilo principal se ejecutan la consola y el procesamiento de tareas crone para eliminar conexiones que ya no son necesarias en el pool.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/7072fb20f406f2ee5788542860ccdf50.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Para probar Odyssey, se utiliza el conjunto est\u00e1ndar de pruebas de Postgres. Simplemente ejecutamos install-check a trav\u00e9s de Bouncer y a trav\u00e9s de Odyssey, obteniendo un div cero. Hay varias pruebas relacionadas con el formateo de fechas que no pasan de manera id\u00e9ntica en Bouncer y en Odyssey.<\/p>\n<p><\/p>\n<p>Adem\u00e1s, hay muchos drivers que tienen sus propias pruebas. Utilizamos estas pruebas para probar Odyssey.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/fb01cc9a0e9724ddcd3cc3d088afb182.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Adem\u00e1s, debido a nuestra configuraci\u00f3n en cascada, tenemos que probar diferentes combinaciones: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey, para asegurarnos de que, si Odyssey se encuentra en alguna parte de la cascada, tambi\u00e9n sigue funcionando como esperamos. <\/p>\n<p><\/p>\n<p><strong>Trampas<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/25855b691180bca083025b9e8b611c09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Utilizamos Odyssey en producci\u00f3n. No ser\u00eda justo decir que todo funciona sin problemas. No, o sea, s\u00ed, pero no siempre. Por ejemplo, en producci\u00f3n todo funcion\u00f3 bien, luego nuestros amigos de PostgreSQL Professional llegaron y dijeron que ten\u00edamos una fuga de memoria. Ellos ten\u00edan raz\u00f3n, la corregimos. Pero eso fue simplemente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/e638d88397b32b1ca0b74c9c1b905f81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Luego descubrimos que en el pool de conexiones hay conexiones TLS entrantes y salientes. Y se requieren certificados de cliente y certificados de servidor en las conexiones.<\/p>\n<p><\/p>\n<p>Los certificados de servidor Bouncer y Odyssey los leen desde su pcache, pero los certificados de cliente no necesitan leerse desde pcache porque nuestro Odyssey escalable acaba topando con el rendimiento del sistema en la lectura de ese certificado. Esto nos sorprendi\u00f3, pues no ocurri\u00f3 de inmediato. Al principio escalaba de manera lineal, y despu\u00e9s de 20,000 conexiones simult\u00e1neas entrantes, se present\u00f3 este problema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6cff094cd59a990e448b82fa0b1572b7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>El M\u00e9todo de Autenticaci\u00f3n Pluggable es la capacidad de autenticarse utilizando herramientas integradas de Linux. En PgBouncer se implementa de tal manera que hay un hilo separado para esperar la respuesta de PAM y hay el hilo principal de PgBouncer, que atiende la conexi\u00f3n actual y puede pedir que se mantengan en el hilo de PAM. <\/p>\n<p><\/p>\n<p>No implementamos esto por una sencilla raz\u00f3n. Tenemos muchos hilos. \u00bfPara qu\u00e9 lo necesitamos?<\/p>\n<p><\/p>\n<p>Esto podr\u00eda causar problemas porque si tiene autenticaci\u00f3n PAM y no PAM, una gran ola de autenticaciones PAM puede retrasar significativamente las no PAM. Esta es una de esas cosas que no corregimos. Pero si desea corregirlo, puede ocuparse de ello. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/c7bd9e9980ff7298b30a59c130f03dbb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Otro problema fue que tenemos un hilo que acepta todas las conexiones entrantes. Y luego las pasa al pool de trabajadores, donde se realizar\u00e1 el apret\u00f3n de manos TLS.<\/p>\n<p><\/p>\n<p>As\u00ed que si tiene una ola coherente de 20,000 conexiones de red, todas ser\u00e1n aceptadas. Y del lado del cliente, libpq comenzar\u00e1 a registrar los tiempos de espera. Por defecto, parece que son 3 segundos. <\/p>\n<p><\/p>\n<p>Si no pueden acceder a la base de datos al mismo tiempo, entonces no pueden acceder a la base de datos, porque todo esto podr\u00eda estar cubierto por un retry no exponencial. <\/p>\n<p><\/p>\n<p>Llegamos a la conclusi\u00f3n de que copiamos aqu\u00ed el esquema de PgBouncer con la que tenemos un control en la cantidad de conexiones TCP, las cuales aceptamos. <\/p>\n<p><\/p>\n<p>Si vemos que aceptamos conexiones, pero estas finalmente no logran hacer el handshake, las colocamos en una cola para que no consuman recursos de la CPU. Esto provoca que el handshake simult\u00e1neo puede no realizarse para todas las conexiones que llegaron. Pero al menos alguien entrar\u00e1 a la base, incluso si la carga es bastante alta.<\/p>\n<p><\/p>\n<p><strong>Hoja de ruta<\/strong><\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 gustar\u00eda ver en el futuro en Odyssey? \u00bfQu\u00e9 estamos dispuestos a desarrollar nosotros mismos y qu\u00e9 esperamos de la comunidad?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4719437d80b33efc3da6572af9a4dedb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>A agosto de 2019.<\/strong><\/p>\n<p><\/p>\n<p>As\u00ed luc\u00eda la hoja de ruta de Odyssey en agosto:<\/p>\n<p><\/p>\n<ul>\n<li>Quer\u00edamos autenticaci\u00f3n SCRAM y PAM.<\/li>\n<li>Quer\u00edamos redirigir consultas de lectura a standby. <\/li>\n<li>Nos gustar\u00eda un reinicio en l\u00ednea. <\/li>\n<li>Y la posibilidad de hacer pausas en el servidor. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/455c92f92df826257c2c57dc2b034e22.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La mitad de esta hoja de ruta se ha cumplido, y no por nosotros. Y eso es bueno. As\u00ed que hablemos de lo que queda y a\u00f1adamos m\u00e1s. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4a1daafbfe8d65ba0dd3e1ebdae8dd94.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\/issues\/12\">En cuanto a redirigir consultas solo de lectura a standby<\/a><\/noindex>? \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0440\u0435\u043f\u043b\u0438\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0435\u0437 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u0433\u0440\u0435\u0442\u044c \u0432\u043e\u0437\u0434\u0443\u0445. \u041e\u043d\u0438 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f failover \u0438 switchover. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0434\u0430\u0442\u0430-\u0446\u0435\u043d\u0442\u0440\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0438\u0445 \u0437\u0430\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u043e\u0439. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u0435 \u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u044b, \u0442\u0443 \u0436\u0435 \u0441\u0430\u043c\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u043d\u0430\u0447\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0873cffd4f1ae15d9ffa6d080671051b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En principio, en Postgres, desde la versi\u00f3n 10, hay posibilidad al conectar de indicar tambi\u00e9n session_attrs. En la conexi\u00f3n puedes enumerar todos los hosts de las bases de datos y decir por qu\u00e9 accedes a la base de datos: para escribir o solo para leer. Y el controlador elegir\u00e1 el primer host de la lista que m\u00e1s le guste, que cumpla con los requisitos de session_attrs. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/0693d1327fe5826502a01c21d05d5b4c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pero el problema de este enfoque es que no controla el retraso de replicaci\u00f3n. Puede haber alguna r\u00e9plica que est\u00e9 atrasada en un tiempo inaceptable para tu servicio. Para hacer que las consultas de lectura funcionen plenamente en la r\u00e9plica, necesitamos mantener en Odyssey la capacidad de no operar cuando no se puede leer. <\/p>\n<p><\/p>\n<p>Odyssey deber\u00eda consultar peri\u00f3dicamente la base y preguntar la distancia de replicaci\u00f3n desde el primario. Y si ha alcanzado el valor l\u00edmite, no permitir nuevas consultas a la base, informar al cliente que debe reiniciar las conexiones y posiblemente elegir otro host para ejecutar las consultas. Esto permitir\u00e1 que la base recupere m\u00e1s r\u00e1pido el retraso de replicaci\u00f3n y vuelva a responder a las consultas. <\/p>\n<p><\/p>\n<p>Es dif\u00edcil nombrar plazos de implementaci\u00f3n, ya que es open source. Pero espero que no sean 2,5 a\u00f1os como en el caso de mis colegas de PgBouncer. Esta funci\u00f3n me gustar\u00eda ver en Odyssey. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/4ec3cd2ff7b2298927cccfe8e0ba890a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/yandex\/odyssey\/issues\/16\">En la comunidad, la gente ha preguntado sobre el soporte para declaraciones preparadas.<\/a><\/noindex>Ahora puede crear declaraciones preparadas de dos maneras. Primero, puede ejecutar el comando SQL, es decir, 'prepared'. Para comprender este comando SQL, necesitamos aprender a entender SQL desde el lado de Bouncer. Ser\u00eda un exceso, porque necesitamos un analizador completo. No podemos analizar cada comando SQL. <\/p>\n<p><\/p>\n<p>Pero hay declaraciones preparadas a nivel de protocolo de mensajes en proto3. Y ese es el momento en que la informaci\u00f3n sobre la creaci\u00f3n de la declaraci\u00f3n preparada llega en forma estructurada. Y podr\u00edamos mantener la comprensi\u00f3n de que en cierta conexi\u00f3n del servidor, el cliente solicit\u00f3 crear declaraciones preparadas. E incluso si la transacci\u00f3n se cerr\u00f3, a\u00fan necesitamos mantener la coherencia entre el servidor y el cliente. <\/p>\n<p><\/p>\n<p>Pero aqu\u00ed surge una discrepancia en el di\u00e1logo, porque alguien dice que es necesario entender qu\u00e9 declaraciones preparadas cre\u00f3 el cliente y dividir la conexi\u00f3n del servidor entre todos los clientes que crearon esta conexi\u00f3n del servidor, es decir, aquellos que crearon tal declaraci\u00f3n preparada. <\/p>\n<p><\/p>\n<p>Andr\u00e9s Freund dijo que si llega un cliente que ya cre\u00f3 tal declaraci\u00f3n preparada en otra conexi\u00f3n del servidor, entonces cr\u00e9elo por \u00e9l. Pero parece un poco incorrecto ejecutar consultas en la base de datos en lugar del cliente, aunque desde la perspectiva del desarrollador que escribe el protocolo de interacci\u00f3n con la base de datos, ser\u00eda conveniente que simplemente le proporcionaran una conexi\u00f3n de red en la que existe tal consulta preparada. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/cd56b3ad015195d86a64e52be365b16a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Y otra caracter\u00edstica que necesitamos implementar. Actualmente tenemos un monitoreo compatible con PgBouncer. Podemos devolver el tiempo promedio de ejecuci\u00f3n de la consulta. Pero el tiempo promedio es como la temperatura media en un hospital: algunos est\u00e1n fr\u00edos, otros tibios; en promedio todos est\u00e1n sanos. Eso no es verdad. <\/p>\n<p><\/p>\n<p>Necesitamos implementar el soporte para percentiles que indiquen que hay consultas lentas que consumen recursos y har\u00edan que el monitoreo sea m\u00e1s aceptable. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/6f285f3eb0d79e7f25d42f0e792b85b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lo m\u00e1s importante es que quiero la versi\u00f3n 1.0 (ya ha salido la versi\u00f3n 1.1). La cuesti\u00f3n es que ahora Odyssey est\u00e1 en la versi\u00f3n 1.0rc, es decir, candidato a lanzamiento. Y todos los problemas que mencion\u00e9 se han solucionado precisamente con esa versi\u00f3n, excepto la fuga de memoria. <\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 significar\u00e1 para nosotros la versi\u00f3n 1.0? Estamos lanzando Odyssey en nuestras bases. Ya est\u00e1 funcionando en nuestras bases, pero cuando alcance la marca de 1,000,000 de solicitudes por segundo, podremos decir que esta es la versi\u00f3n de lanzamiento y que se puede considerar la versi\u00f3n 1.0. <\/p>\n<p><\/p>\n<p>En la comunidad, algunas personas han pedido que la versi\u00f3n 1.0 incluya una pausa y SCRAM. Pero eso significar\u00e1 que tendremos que lanzar la siguiente versi\u00f3n en producci\u00f3n, porque ni SCRAM ni la pausa se han fusionado a\u00fan. Sin embargo, es probable que este problema se resuelva con bastante rapidez. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hoja de ruta de Odyssey: lo que esperamos del agrupador de conexiones. Andrey Borodin (2019)\" src=\"\/wp-content\/uploads\/2020\/10\/2f50de9f51f653a7396965239bd545e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Estoy esperando sus pull requests. Tambi\u00e9n me gustar\u00eda saber qu\u00e9 problemas tienen con Bouncer. Discut\u00e1moslo. Quiz\u00e1s podamos implementar algunas funciones que ustedes necesiten. <\/p>\n<p><\/p>\n<p>Con esto concluyo mi parte, me gustar\u00eda escucharlos. \u00a1Gracias!<\/p>\n<p><\/p>\n<p>Preguntas<\/p>\n<p><\/p>\n<p><em>Si configuro application_name, \u00bfse transmitir\u00e1 correctamente, incluso en el pooling de transacciones en Odyssey?<\/em><\/p>\n<p><\/p>\n<p>\u00bfEn Odyssey o en Bouncer?<\/p>\n<p><\/p>\n<p><em>En Odyssey. En Bouncer se transmite.<\/em> <\/p>\n<p><\/p>\n<p>Realizaremos el set. <\/p>\n<p><\/p>\n<p><em>Y si mi conexi\u00f3n real salta entre otras conexiones, \u00bfse transmitir\u00e1?<\/em><\/p>\n<p><\/p>\n<p>Haremos un set de todos los par\u00e1metros que est\u00e1n en la lista. No puedo decir si application_name est\u00e1 en esta lista. Creo haberlo visto ah\u00ed. Estableceremos todos los mismos par\u00e1metros. Con una sola solicitud, el set har\u00e1 todo lo que se configur\u00f3 por el cliente al iniciar. <\/p>\n<p><\/p>\n<p><em>\u00a1Gracias, Andrey, por la presentaci\u00f3n! \u00a1Buena presentaci\u00f3n! Me alegra que Odyssey est\u00e9 evolucionando cada vez m\u00e1s r\u00e1pido. Espero que contin\u00faen as\u00ed. Ya nos hemos comunicado con ustedes sobre la posibilidad de una conexi\u00f3n multi data-source, para que Odyssey pueda conectarse simult\u00e1neamente a diferentes bases de datos, es decir, master-slave, y luego conectarse autom\u00e1ticamente a un nuevo master despu\u00e9s de un failover.<\/em> <\/p>\n<p><\/p>\n<p>S\u00ed, creo recordar esa discusi\u00f3n. Actualmente hay varios storages. Pero no hay conmutaci\u00f3n entre ellos. Debemos sondear el servidor de nuestro lado para saber si sigue activo y entender que ha ocurrido un failover, quien llamar\u00e1 a pg_recovery. Tengo un m\u00e9todo est\u00e1ndar para saber que no estamos conectados al master. Y debemos averiguarlo a partir de alg\u00fan error o de otra manera. Es decir, la idea es interesante, se est\u00e1 discutiendo. Escriban m\u00e1s comentarios. Si tienen manos a la obra que sepan C, ser\u00eda genial. <\/p>\n<p><\/p>\n<p>La cuesti\u00f3n de la escalabilidad a trav\u00e9s de r\u00e9plicas tambi\u00e9n nos interesa, porque queremos hacer que la adopci\u00f3n de cl\u00fasteres replicados sea lo m\u00e1s simple posible para los desarrolladores de aplicaciones. Sin embargo, aqu\u00ed nos gustar\u00eda tener m\u00e1s comentarios, es decir, c\u00f3mo exactamente hacerlo, c\u00f3mo hacerlo bien. <\/p>\n<p><\/p>\n<p><em>La pregunta tambi\u00e9n es sobre las r\u00e9plicas. As\u00ed que tienen un maestro y varias r\u00e9plicas. Y est\u00e1 claro que se accede a la r\u00e9plica con menor frecuencia que al maestro en cuanto a las conexiones, porque pueden tener diferencias. Ustedes mencionaron que las diferencias en los datos pueden ser tales que no satisfacen su negocio y no acceder\u00e1n a ellas hasta que se repliquen completamente. Adem\u00e1s, si no se accede durante mucho tiempo, y luego se comienza a acceder, los datos que se necesitan no estar\u00e1n disponibles de inmediato. Es decir, si constantemente accedemos al maestro, el cach\u00e9 all\u00ed est\u00e1 caliente, mientras que en la r\u00e9plica el cach\u00e9 se queda un poco atr\u00e1s.<\/em> <\/p>\n<p><\/p>\n<p>S\u00ed, es cierto. En el pcache no habr\u00e1 bloques de datos que deseen, en el cache real no habr\u00e1 informaci\u00f3n sobre las tablas que desean, en los planes no habr\u00e1 consultas analizadas, en general, no habr\u00e1 nada. <\/p>\n<p><\/p>\n<p><em>Y cuando tienen un cl\u00faster y a\u00f1aden una nueva r\u00e9plica, mientras se inicia, todo va mal, es decir, va acumulando su cach\u00e9.<\/em> <\/p>\n<p><\/p>\n<p>Entend\u00ed la idea. Un enfoque correcto ser\u00eda iniciar un peque\u00f1o porcentaje de solicitudes primero en la r\u00e9plica, que calentar\u00edan el cach\u00e9. A grosso modo, tenemos la condici\u00f3n de que no debemos estar m\u00e1s de 10 segundos atr\u00e1s respecto al maestro. Y esta condici\u00f3n no debe activarse de una sola vez, sino de forma gradual para algunos clientes. <\/p>\n<p><\/p>\n<p><em>S\u00ed, aumentar el peso.<\/em><\/p>\n<p><\/p>\n<p>Es una buena idea. Pero primero necesitamos implementar esta desconexi\u00f3n. Primero debemos desconectarnos, y luego pensaremos en c\u00f3mo reconectarnos. Es una gran caracter\u00edstica para reiniciar de manera gradual.<\/p>\n<p><\/p>\n<p><em>En nginx hay una opci\u00f3n as\u00ed <code>slowly start<\/code> en el cl\u00faster para el servidor. Y va incrementando la carga gradualmente.<\/em> <\/p>\n<p><\/p>\n<p>S\u00ed, es una excelente idea, lo probaremos cuando lleguemos a eso.<\/p>\n<p>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/522734\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u0410\u043d\u0434\u0440\u0435\u0439 \u0411\u043e\u0440\u043e\u0434\u0438\u043d \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442, \u043a\u0430\u043a \u043e\u043d\u0438 \u0443\u0447\u043b\u0438 \u043e\u043f\u044b\u0442 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f PgBouncer \u043f\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0443\u043b\u0435\u0440\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 Odyssey, \u043a\u0430\u043a \u0432\u044b\u043a\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u0435\u0433\u043e \u0432 production. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043e\u0431\u0441\u0443\u0434\u0438\u043c \u043a\u0430\u043a\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0443\u043b\u0435\u0440\u0430 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445: \u043d\u0430\u043c \u0432\u0430\u0436\u043d\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438, \u043d\u043e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u041e\u0434\u0438\u0441\u0441\u0435\u044f. \u0412\u0438\u0434\u0435\u043e: \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043d\u0434\u0440\u0435\u0439. \u0412 \u042f\u043d\u0434\u0435\u043a\u0441\u0435 \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":96516,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-96515","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.2 - aioseo.com -->\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\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\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\udd47Odyssey roadmap: \u0447\u0442\u043e \u0435\u0449\u0451 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442 \u043f\u0443\u043b\u0435\u0440\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439. \u0410\u043d\u0434\u0440\u0435\u0439 \u0411\u043e\u0440\u043e\u0434\u0438\u043d (2019) | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019\" \/>\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=\"2020-10-12T17:43:02+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-10-12T17:43:02+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\udd47Odyssey roadmap: qu\u00e9 m\u00e1s queremos del agrupador de conexiones. Andrey Borodin (2019) | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","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\udd47Odyssey roadmap: \u0447\u0442\u043e \u0435\u0449\u0451 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442 \u043f\u0443\u043b\u0435\u0440\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439. \u0410\u043d\u0434\u0440\u0435\u0439 \u0411\u043e\u0440\u043e\u0434\u0438\u043d (2019) | ProHoster","og:url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/odyssey-roadmap-chto-eshhyo-my-hotim-ot-pulera-soedinenij-andrej-borodin-2019","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":"2020-10-12T17:43:02+00:00","article:modified_time":"2020-10-12T17:43:02+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"96515","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 10:41:30","updated":"2022-10-01 00:02:14","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\/96515","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=96515"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/96515\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/96516"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=96515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=96515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=96515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}