One place for hosting & domains

      Información sobre algoritmos de selección de bloques de servidores y ubicación de Nginx


      Introducción

      Nginx es uno de los servidores web más populares del mundo. Puede manejar correctamente altas cargas con muchas conexiones de clientes concurrentes y puede funcionar fácilmente como servidor web, servidor de correo o servidor de proxy inverso.

      En esta guía, explicaremos algunos de los detalles en segundo plano que determinan cómo Nginx procesa las solicitudes de los clientes. Entender estas ideas puede ayudar a despejar las incógnitas sobre el diseño de bloques de servidores y ubicación, y puede hacer que el manejo de las solicitudes parezca menos impredecible.

      Configuraciones de bloques de Nginx

      Nginx divide de forma lógica las configuraciones destinadas a entregar distintos contenidos en bloques, que conviven en una estructura jerárquica. Cada vez que se realiza una solicitud de cliente, Nginx inicia un proceso para determinar qué bloques de configuración deben usarse para gestionar la solicitud. Este proceso de decisión es lo que explicaremos en esta guía.

      Los bloques principales que explicaremos son el bloque de servidor y el bloque de ubicación.

      Un bloque de servidor es un subconjunto de la configuración de Nginx que define un servidor virtual utilizado para gestionar las solicitudes de un tipo definido. Los administradores suelen configurar varios bloques de servidores y decidir qué bloque debe gestionar cada conexión según el nombre de dominio, el puerto y la dirección IP solicitados.

      Un bloque de ubicación reside dentro de un bloque de servidor y se utiliza para definir la manera en que Nginx debe gestionar las solicitudes para diferentes recursos y URI para el servidor principal. El espacio URI puede subdividirse de la manera que el administrador quiera utilizando estos bloques. Es un modelo extremadamente flexible.

      Cómo decide Nginx qué bloque de servidor gestionará una solicitud

      Dado que Nginx permite que el administrador defina varios bloques de servidores que funcionan como instancias de servidores web virtuales independientes, necesita un procedimiento para determinar cuál de estos bloques de servidores se utilizará para satisfacer una solicitud.

      Lo hace mediante un sistema definido de comprobaciones que se utilizan para encontrar la mejor coincidencia posible. Las principales directivas de bloques de servidores de las que se ocupa Nginx durante este proceso son la directiva listen y la directiva server_name.

      Análisis de la directiva “listen” para encontrar posibles coincidencias

      Primero, Nginx examina la dirección IP y el puerto de la solicitud. Luego, lo compara con la directiva listen de cada servidor para crear una lista de los bloques de servidores que pueden resolver la solicitud.

      La directiva listen generalmente define la dirección IP y el puerto a los que responderá el bloque de servidor. De manera predeterminada, cualquier bloque de servidor que no incluya una directiva listen recibe los parámetros de escucha 0.0.0.0:80 (o 0.0.0.0:8080 si Nginx está siendo ejecutado por un usuario no root regular). Eso permite que estos bloques respondan a las solicitudes en cualquier interfaz en el puerto 80, pero este valor predeterminado no afecta demasiado al proceso de selección de servidores.

      La directiva listen puede establecerse para las siguientes características:

      • Una combinación de dirección IP y puerto.
      • Una dirección IP individual que escuchará en el puerto 80 de manera predeterminada.
      • Un puerto individual que escuchará cada interfaz en ese puerto.
      • La ruta al socket Unix.

      La última opción, por lo general, solo tendrá implicaciones al pasar solicitudes entre distintos servidores.

      Cuando intente determinar a qué bloque de servidor enviar una solicitud, Nginx tratará primero de decidir según la especificidad de la directiva listen usando las siguientes reglas:

      • Nginx traduce todas las directivas listen “incompletas” sustituyendo los valores que faltan por sus valores predeterminados para que cada bloque pueda evaluarse por su dirección IP y su puerto. Algunos ejemplos de estas traslaciones son:
        • Un bloque sin directiva listen utiliza el valor 0.0.0.0:80.
        • Un bloque establecido en una dirección IP 111.111.111.111 sin puerto se convierte en 111.111.111.111:80.
        • Un bloque establecido en el puerto 8888 sin dirección IP se convierte en 0.0.0.0:8888.
      • Luego, Nginx intenta recopilar una lista de los bloques de servidores que coinciden con la solicitud más específicamente basada en la dirección IP y el puerto. Eso significa que cualquier bloque que esté usando de forma funcional 0.0.0.0 como su dirección IP (para coincidir con cualquier interfaz), no se seleccionará si hay bloques coincidentes que enumeran una dirección IP específica. En todo caso, el puerto debe coincidir con exactitud.
      • Si solo hay una coincidencia más específica, ese bloque de servidor se utilizará para atender la solicitud. Si hay varios bloques de servidores con el mismo nivel de coincidencia de especificidad, Nginx comienza a evaluar la directiva server_name de cada bloque de servidores.

      Es importante entender que Nginx solo evaluará la directiva server_name cuando necesite distinguir entre bloques de servidores que coinciden con el mismo nivel de especificidad en la directiva listen. Por ejemplo, si example.com está alojado en el puerto 80 de 192.168.1.10, una solicitud para example.com siempre será atendida por el primer bloque de este ejemplo, a pesar de la directiva server_name en el segundo bloque.

      server {
          listen 192.168.1.10;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      

      En caso de que más de un bloque de servidor coincida con la misma especificidad, el siguiente paso es verificar la directiva server_name.

      Análisis de la directiva “server_name” para elegir una coincidencia

      Luego, para evaluar más a fondo las solicitudes que tienen directivas listen igualmente específicas, Nginx verifica el encabezado “Host” de la solicitud. Ese valor contiene el dominio o la dirección IP que el cliente estaba intentando alcanzar.

      Nginx intenta encontrar la mejor coincidencia para el valor que encuentra al ver la directiva server_name dentro de cada uno de los bloques de servidores que aún son candidatos a selección. Nginx lo evalúa usando la siguiente formula:

      • Nginx intentará primero encontrar un bloque de servidor con un server_name que coincida con el valor en el encabezado “Host” de la solicitud de manera exacta. Si lo encuentra, ese bloque asociado se utilizará para atender la solicitud. Si se encuentran varias coincidencias exactas, se utiliza la primera coincidencia.
      • Si no se encuentra ninguna coincidencia exacta, Nginx intentará encontrar un bloque de servidor con un server_name que coincida usando un comodín inicial (indicado por un * al principio del nombre en la configuración). Si lo encuentra, ese bloque se utilizará para atender la solicitud. Si se encuentran varias coincidencias, la coincidencia más larga se utilizará para atender la solicitud.
      • Si no se encuentra ninguna coincidencia con el comodín inicial, Nginx buscará entonces un bloque de servidor con un server_name que coincida usando un comodín final (indicado por un nombre de servidor que termina con un * en la configuración). Si lo encuentra, ese bloque se utilizará para atender la solicitud. Si se encuentran varias coincidencias, la coincidencia más larga se utilizará para atender la solicitud.
      • Si no se encuentra ninguna coincidencia usando un comodín final, Nginx evalúa los bloques de servidor que definen el server_name usando expresiones regulares (indicadas por un ~ antes del nombre). El primer server_name con una expresión regular que coincida con el encabezado “Host” se utilizará para atender la solicitud.
      • Si no se encuentra ninguna coincidencia de expresión regular, Nginx selecciona el bloque de servidor predeterminado para esa dirección IP y ese puerto.

      Cada combinación de dirección IP/puerto tiene un bloque de servidor predeterminado que se utilizará cuando no se pueda determinar un curso de acción con los métodos anteriores. En el caso de una combinación de dirección IP y puerto, será el primer bloque de la configuración o el bloque que contiene la opción default_server como parte de la directiva listen (que anularía el primer algoritmo encontrado). Solo puede haber una declaración default_server por cada combinación de dirección IP y puerto.

      Ejemplos

      Si se define un server_name que coincida exactamente con el valor de encabezado “Host”, se selecciona ese bloque de servidor para procesar la solicitud.

      En este ejemplo, si el encabezado “Host” de la solicitud se estableció en “host1.example.com”, se seleccionaría el segundo servidor:

      server {
          listen 80;
          server_name *.example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name host1.example.com;
      
          . . .
      
      }
      

      Si no se encuentra ninguna coincidencia exacta, Nginx comprueba entonces si hay un server_name con un comodín inicial que coincida. Se seleccionará la coincidencia más larga que comience con un comodín para satisfacer la solicitud.

      En este ejemplo, si la solicitud tuviera un encabezado “Host” de “www.example.org”, se seleccionaría el segundo bloque de servidor:

      server {
          listen 80;
          server_name www.example.*;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name *.example.org;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name *.org;
      
          . . .
      
      }
      

      Si no se encuentra ninguna coincidencia con un comodín inicial, Nginx verá si existe una coincidencia usando un comodín al final de la expresión. En este punto, se seleccionará la coincidencia más larga que termine con un comodín para atender la solicitud.

      Por ejemplo, si la solicitud tiene un encabezado “Host” establecido en “www.example.com”, se seleccionará el tercer bloque de servidor:

      server {
          listen 80;
          server_name host1.example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name www.example.*;
      
          . . .
      
      }
      

      Si no se encuentran coincidencias con los comodines, Nginx pasará a intentar coincidir con las directivas server_name que utilicen expresiones regulares. Se seleccionará la primera expresión regular que coincida para responder a la solicitud.

      Por ejemplo, si el encabezado “Host” de la solicitud está configurado en “www.example.com”, se seleccionará el segundo bloque de servidor para satisfacer la solicitud:

      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name ~^(www|host1).*.example.com$;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name ~^(subdomain|set|www|host1).*.example.com$;
      
          . . .
      
      }
      

      Si ninguno de los pasos anteriores puede satisfacer la solicitud, la solicitud se pasará al servidor predeterminado para la dirección IP y el puerto que coincidan.

      Bloques de ubicación que coinciden

      De forma similar al proceso que utiliza Nginx para seleccionar el bloque del servidor que procesará una solicitud, Nginx también tiene un algoritmo establecido para decidir qué bloque de ubicación dentro del servidor se utilizará para gestionar las solicitudes.

      Sintaxis de bloques de ubicación

      Antes de ver cómo Nginx decide qué bloque de ubicación utilizar para gestionar las solicitudes, repasemos parte de la sintaxis que se podría encontrar en las definiciones de los bloques de ubicación. Los bloques de ubicación se encuentran dentro de los bloques de servidor (u otros bloques de ubicación) y se utilizan para decidir cómo procesar la URI de la solicitud (la parte de la solicitud que viene después del nombre de dominio o la dirección IP/puerto).

      Los bloques de ubicación generalmente tienen la siguiente forma:

      location optional_modifier location_match {
      
          . . .
      
      }
      

      location_match que aparece arriba define contra qué debe comprobar Nginx la URI de la solicitud. La existencia o la inexistencia del modificador en el ejemplo anterior afecta a la forma en que Nginx intenta hacer coincidir el bloque de ubicación. Los modificadores que se muestran abajo harán que el bloque de ubicación asociado se interprete de la siguiente manera:

      • (none): si no hay modificadores, la ubicación se interpreta como una coincidencia de prefijo. Eso significa que la ubicación dada coincidirá con el principio del URI de la solicitud para determinar una coincidencia.
      • =: si se utiliza un signo igual, este bloque se considerará coincidente si el URI de la solicitud coincide exactamente con la ubicación indicada.
      • ~: si hay una tilde de la eñe, esta ubicación se interpretará como una coincidencia de expresión regular que distingue entre mayúsculas y minúsculas.
      • ~*: si se utiliza un modificador de tilde de la eñe y asterisco, el bloque de ubicación se interpretará como una coincidencia de expresión regular que no distingue entre mayúsculas y minúsculas.
      • ^~: si hay un modificador de acento circunflejo y tilde de la eñe, y si este bloque se selecciona como la mejor coincidencia de expresión no regular, no se realizará la coincidencia de expresión regular.

      Ejemplos que demuestran la sintaxis del bloque de ubicación

      Como ejemplo de concordancia de prefijos, se puede seleccionar el siguiente bloque de ubicación para responder a los URI de solicitud que tienen el aspecto /site, /site/page1/index.html o /site/index.html:

      location /site {
      
          . . .
      
      }
      

      Para una demostración de la coincidencia exacta del URI de la solicitud, este bloque siempre se utilizará para responder a un URI de solicitud que tenga el aspecto /page1. No se utilizará para responder a un URI de solicitud /page1/index.html. Tenga en cuenta que, si se selecciona este bloque y la solicitud se cumple usando una página de índice, se realizará un redireccionamiento interno a otra ubicación que será la que realmente gestione la solicitud:

      location = /page1 {
      
          . . .
      
      }
      

      Como ejemplo de una ubicación que debe interpretarse como una expresión regular que distingue entre mayúsculas y minúsculas, este bloque puede usarse para gestionar las solicitudes de /tortoise.jpg, pero no para /FLOWER.PNG:

      location ~ .(jpe?g|png|gif|ico)$ {
      
          . . .
      
      }
      

      A continuación, se muestra un bloque que permitiría una coincidencia sin distinción ente mayúsculas y minúsculas similar al que se mostró anteriormente. Este bloque podría gestionar /tortoise.jpg y /FLOWER.PNG:

      location ~* .(jpe?g|png|gif|ico)$ {
      
          . . .
      
      }
      

      Por último, este bloque evitaría que se produjera una coincidencia de expresión regular si se determina que es la mejor coincidencia de expresión no regular. Podría gestionar las solicitudes de /costumes/ninja.html:

      location ^~ /costumes {
      
          . . .
      
      }
      

      Como ve, los modificadores indican cómo debe interpretarse el bloque de ubicación. Sin embargo, esto no nos indica el algoritmo que utiliza Nginx para decidir a qué bloque de ubicación enviar la solicitud. Lo repasaremos a continuación.

      Cómo elige Nginx qué ubicación utilizar para gestionar las solicitudes

      Nginx elige la ubicación que se utilizará para atender una solicitud de forma similar a cómo selecciona un bloque de servidor. Se ejecuta a través de un proceso que determina el mejor bloque de ubicación para cualquier solicitud. Entender este proceso es un requisito crucial para poder configurar Nginx de forma fiable y precisa.

      Teniendo en cuenta los tipos de declaraciones de ubicación que hemos descrito anteriormente, Nginx evalúa los posibles contextos de ubicación comparando el URI de solicitud con cada una de las ubicaciones. Lo hace mediante el siguiente algoritmo:

      • Nginx comienza comprobando todas las coincidencias de ubicación basadas en prefijos (todos los tipos de ubicación que no implican una expresión regular). Comprueba cada ubicación con el URI completo de la solicitud.
      • Primero, Nginx busca una coincidencia exacta. Si se encuentra un bloque de ubicación que utilice el modificador = y que coincida con el URI de la solicitud de manera exacta, este bloque de ubicación se selecciona inmediatamente para atender la solicitud.
      • Si no se encuentran coincidencias exactas con bloques de ubicación (con el modificador =), Nginx pasa a evaluar los prefijos no exactos. Descubre la ubicación del prefijo más largo que coincide con el URI de la solicitud dada que luego evalúa de la siguiente manera:
        • Si la ubicación del prefijo más largo que coincide tiene el modificador ^~, Nginx finalizará inmediatamente su búsqueda y seleccionará esta ubicación para atender la solicitud.
        • Si la ubicación del prefijo más largo que coincide no utiliza el modificador ^~, Nginx almacena la coincidencia de momento para poder cambiar el enfoque de la búsqueda.
      • Una vez que se determina y almacena la ubicación del prefijo más largo que coincide, Nginx procede a evaluar las ubicaciones de expresiones regulares (las que distinguen entre mayúsculas y minúsculas, y las que no). Si hay alguna ubicación de expresiones regulares dentro de la ubicación del prefijo más largo que coincide, Nginx la pondrá a la parte superior de su lista de ubicaciones de regex para comprobar. Luego, Nginx intentará hacer coincidir con las ubicaciones de expresiones regulares de forma secuencial. La primera ubicación de expresión regular que coincida con el URI de la solicitud se seleccionará inmediatamente para atender la solicitud.
      • Si no se encuentra ninguna ubicación de expresión regular que coincida con el URI de la solicitud, se seleccionará la ubicación de prefijo previamente almacenado para atender la solicitud.

      Es importante entender que, de manera predeterminada, Nginx atenderá las coincidencias de expresiones regulares con mayor preferencia en comparación con las coincidencias de prefijos. Sin embargo, primero evalúa las ubicaciones de prefijos, lo que permite al administrador anular esta tendencia especificando las ubicaciones usando los modificadores = y ^~.

      También es importante tener en cuenta que, aunque las ubicaciones de prefijos generalmente se seleccionan según la coincidencia más larga y específica, la evaluación de la expresión regular se detiene cuando se encuentra la primera ubicación que coincida. Eso significa que el posicionamiento dentro de la configuración tiene amplias implicaciones para las ubicaciones de expresiones regulares.

      Por último, es importante entender que las coincidencias de expresiones regulares dentro de la coincidencia del prefijo más largo “saltarán la línea” cuando Nginx evalúe las ubicaciones de regex. Estas se evaluarán en orden, antes de que se consideren las demás coincidencias de expresiones regulares. Maxim Dounin, un desarrollador de Nginx increíblemente atento, explica en esta publicación esta parte del algoritmo de selección.

      ¿Cuándo salta la evaluación del bloque de ubicaciones a otras ubicaciones?

      En general, cuando se selecciona un bloque de ubicación para atender una solicitud, la solicitud se gestiona completamente dentro de ese contexto a partir de ese momento. Solo la ubicación seleccionada y las directivas heredadas determinan cómo se procesa la solicitud, sin interferencia de los bloques de ubicación hermanos.

      Aunque esta es una regla general que le permitirá diseñar sus bloques de ubicación de una manera predecible, es importante darse cuenta de que, a veces, una nueva búsqueda de ubicación se activa por ciertas directivas dentro de la ubicación seleccionada. Las excepciones a la regla “solo un bloque de ubicación” pueden tener implicaciones sobre cómo se atiende realmente la solicitud y pueden no coincidir con las expectativas que tenía al diseñar sus bloques de ubicación.

      Algunas directivas que pueden dar como resultado este tipo de redireccionamiento interno son:

      • index
      • try_files
      • rewrite
      • error_page

      Las repasaremos brevemente.

      La directiva index siempre conduce a un redireccionamiento interno si se utiliza para gestionar la solicitud. Las coincidencias de ubicación exactas se utilizan a menudo para acelerar el proceso de selección, terminando inmediatamente la ejecución del algoritmo. Sin embargo, si realiza una coincidencia de ubicación exacta que sea un directorio, hay una buena probabilidad de que la solicitud sea redirigida a una ubicación diferente para el procesamiento real.

      En este ejemplo, la primera ubicación coincide con un URI de solicitud de /exact, pero, para gestionar la solicitud, la directiva index heredada por el bloque inicia un redireccionamiento interno al segundo bloque:

      index index.html;
      
      location = /exact {
      
          . . .
      
      }
      
      location / {
      
          . . .
      
      }
      

      En el caso anterior, si realmente necesita que la ejecución permanezca en el primer bloque, tendrá que encontrar un método diferente para satisfacer la solicitud al directorio. Por ejemplo, podría establecer un index no válido para ese bloque y activar autoindex:

      location = /exact {
          index nothing_will_match;
          autoindex on;
      }
      
      location  / {
      
          . . .
      
      }
      

      Esta es una forma de evitar que un index cambie de contexto, pero probablemente no sea útil para la mayoría de las configuraciones. Generalmente, una coincidencia exacta en directorios puede ser útil para acciones como reescribir la solicitud (lo que también genera una nueva búsqueda de ubicación).

      Otro caso en que se puede reevaluar la ubicación del procesamiento es con la directiva try_files. Esa directiva le indica a Nginx que busque la existencia de un conjunto determinado de archivos o directorios. El último parámetro puede ser un URI al que Nginx realizará un redireccionamiento interno.

      Analice la siguiente configuración:

      root /var/www/main;
      location / {
          try_files $uri $uri.html $uri/ /fallback/index.html;
      }
      
      location /fallback {
          root /var/www/another;
      }
      

      En el ejemplo anterior, si se realiza una solicitud para /blahblah, la primera ubicación obtendrá inicialmente la solicitud. Intentará encontrar un archivo llamado blahblah en el directorio /var/www/main. Si no puede encontrar ninguno, procederá a buscar un archivo llamado blahblah.html. Luego, intentará buscar un directorio llamado blahblah/ dentro del directorio /var/www/main. Si todos esos intentos fallan, se redirigirá a /fallback/index.html. Eso activará otra búsqueda de ubicación que el segundo bloque de ubicación capturará. Y atenderá el archivo /var/www/another/fallback/index.html.

      Otra directiva que puede pasar el bloque de ubicación es la directiva rewrite. Cuando utiliza el último parámetro con la directiva rewrite o cuando no utiliza ningún parámetro, Nginx buscará una nueva ubicación que coincida según los resultados de la reescritura.

      Por ejemplo, si modificamos el último ejemplo para incluir una reescritura, podemos ver que la solicitud a veces se pasa directamente a la segunda ubicación sin depender de la directiva try_files:

      root /var/www/main;
      location / {
          rewrite ^/rewriteme/(.*)$ /$1 last;
          try_files $uri $uri.html $uri/ /fallback/index.html;
      }
      
      location /fallback {
          root /var/www/another;
      }
      

      En el ejemplo de arriba, el primer bloque de ubicación gestionará inicialmente una solicitud de /rewriteme/hello. Se reescribirá a /hello y se buscará una ubicación. En este caso, volverá a coincidir con la primera ubicación y se procesará mediante try_files de manera habitual, probablemente regresando a /fallback/index.html si no se encuentra nada (usando el redireccionamiento interno de try_files que mencionamos antes).

      Sin embargo, si se realiza una solicitud para /rewriteme/fallback/hello, el primer bloque volverá a coincidir. Se aplicará la reescritura de nuevo, dando como resultado /fallback/hello esta vez. La solicitud se atenderá desde el segundo bloque de ubicación.

      Algo similar sucede con la directiva return cuando se envían los códigos de estado 301 o 302. La diferencia en este caso es que da como resultado una solicitud completamente nueva en forma de un redireccionamiento visible desde el exterior. Eso mismo puede suceder con la directiva rewrite cuando se utilizan los indicadores redirect o permanent. Sin embargo, estas búsquedas de ubicación no deberían ser inesperadas, ya que los redireccionamientos visibles externamente siempre dan como resultado una nueva solicitud.

      La directiva error_page puede dar como resultado un redireccionamiento interno similar al que se creó con try_files. Esa directiva se utiliza para definir lo que debe suceder cuando se encuentran ciertos códigos de estado. Esto probablemente nunca se ejecutará si se establece try_files, ya que esa directiva maneja todo el ciclo de vida de una solicitud.

      Analice este ejemplo:

      root /var/www/main;
      
      location / {
          error_page 404 /another/whoops.html;
      }
      
      location /another {
          root /var/www;
      }
      

      Todas las solicitudes (aparte de las que comienzan con /another) se gestionarán mediante el primer bloque, que atenderá archivos desde /var/www/main. Sin embargo, si no se encuentra un archivo (un estado 404), se producirá un redireccionamiento interno a /another/whoops.html, lo que llevará a una nueva búsqueda de ubicación que finalmente aterrizará en el segundo bloque. Este archivo se atenderá desde /var/www/another/whoops.html.

      Como se puede ver, entender las circunstancias en que Nginx activa una nueva búsqueda de ubicación puede ayudar a predecir el comportamiento que habrá cuando se hagan solicitudes.

      Conclusión

      Entender las formas en que Nginx procesa las solicitudes de los clientes puede hacer que su trabajo como administrador sea mucho más fácil. Podrá saber qué bloque de servidor seleccionará Nginx según cada solicitud del cliente. También podrá saber cómo se seleccionará el bloque de ubicación según el URI de la solicitud. En general, saber la forma en que Nginx selecciona los diferentes bloques le permitirá rastrear los contextos que Nginx aplicará para atender cada solicitud.



      Source link

      Información sobre las bases de datos relacionales


      Introducción

      Los sistemas de administración de bases de datos (DBMS) son programas que permiten a los usuarios interactuar con una base de datos. Les permiten controlar el acceso a una base de datos, escribir datos, ejecutar consultas y realizar otras tareas relacionadas con la administración de bases de datos.

      Sin embargo, para realizar cualquiera de estas tareas, los DBMS deben tener algún tipo de modelo subyacente que defina la organización de los datos. El modelo relacional es un enfoque para la organización de datos que se ha utilizado ampliamente en programas de software de bases de datos desde su concepción a fines de la década de 1960; a tal grado que, a la fecha de redacción de este artículo, cuatro de los cinco DBMS más populares son relacionales.

      Este artículo conceptual describe la historia del modelo relacional, la manera en que se organizan los datos en las bases de datos relacionales y cómo se utilizan hoy en día.

      Historia del modelo relacional

      Las bases de datos son conjuntos de información, o datos, modelados de forma lógica. Cualquier recopilación de datos es una base de datos, independientemente de cómo o dónde se almacene. Incluso un gabinete de archivos con información sobre nómina es una base de datos, al igual que una pila de formularios de pacientes hospitalizados o la recopilación de información sobre clientes de una empresa repartida en varias ubicaciones. Antes de que almacenar y administrar datos con computadoras se convirtiera en una práctica común, las bases de datos físicas como estas eran lo único con lo que contaban las organizaciones gubernamentales y empresariales que necesitaban almacenar información.

      A mediados del siglo XX, los desarrollos en las ciencias de la computación dieron lugar a máquinas con mayor capacidad de procesamiento y almacenamiento, tanto local como externo. Estos avances hicieron que los especialistas en ciencias de la computación comenzaran a reconocer el potencial que tenían estas máquinas para almacenar y administrar cantidades de datos cada vez más grandes.

      Sin embargo, no había teorías sobre cómo las computadoras podían organizar datos de manera significativa y lógica. Una cosa es almacenar datos no ordenados en una máquina, pero es mucho más complicado diseñar sistemas que permitan agregar, recuperar, clasificar y administrar esos datos de forma sistemática y práctica. La necesidad de contar con un marco de trabajo lógico para almacenar y organizar datos dio lugar a varias propuestas sobre cómo utilizar las computadoras para administrar datos.

      Uno de los primeros modelos de bases de datos fue el modelo jerárquico, en el que los datos se organizan con una estructura de árbol similar a la de los sistemas de archivos modernos. El siguiente ejemplo muestra el aspecto que podría tener el diseño de una parte de una base de datos jerárquica utilizada para categorizar animales:

      Ejemplo de base de datos jerárquica: categorización de animales

      El modelo jerárquico se implementó ampliamente en los primeros sistemas de administración de bases de datos, pero resultaba poco flexible. En este modelo, a pesar de que los registros individuales pueden tener varios “elementos secundarios”, cada uno puede tener un solo “elemento primario” en la jerarquía. Es por eso que estas primeras bases de datos jerárquicas se limitaban a representar relaciones “uno a uno” y “uno a varios”. Esta carencia de relaciones “varios a varios” podía provocar problemas al trabajar con puntos de datos que se deseaba asociar a más de un elemento primario.

      A fines de los años 60, Edgar F. Codd, un especialista en ciencias de la computación que trabajaba en IBM, diseñó el modelo relacional de administración de bases de datos. El modelo relacional de Codd permitía que los registros individuales se relacionaran con más de una tabla y, de esta manera, posibilitaba las relaciones “varios a varios” entre los puntos de datos además de las relaciones “uno a varios”. Esto proporcionó más flexibilidad que los demás modelos existentes a la hora de diseñar estructuras de base de datos y permitió que los sistemas de gestión de bases de datos relacionales (RDBMS) pudieran satisfacer una gama mucho más amplia de necesidades empresariales.

      Codd propuso un lenguaje para la administración de datos relacionales, conocido como Alfa, que influyó en el desarrollo de los lenguajes de bases de datos posteriores. Dos colegas de Codd en IBM, Donald Chamberlin y Raymond Boyce, crearon un lenguaje similar inspirado en Alpha. Lo llamaron SEQUEL, abreviatura de Structured English Query Language (Lenguaje de consulta estructurado en inglés), pero debido a una marca comercial existente, lo abreviaron a SQL (conocido formalmente como* Lenguaje de consulta estructurado*).

      Debido a las limitaciones de hardware, las primeras bases de datos relacionales eran prohibitivamente lentas y el uso de la tecnología tardó un tiempo en generalizarse. Pero a mediados de los años ochenta, el modelo relacional de Codd se había implementado en varios productos comerciales de administración de bases de datos, tanto de IBM como de sus competidores. Estos proveedores también siguieron el liderazgo de IBM al desarrollar e implementar sus propios dialectos de SQL. Para 1987, tanto el Instituto Nacional Estadounidense de Estándares (American National Standards Institute) como la Organización Internacional de Normalización (International Organization for Standardization) habían ratificado y publicado normas para SQL, lo que consolidó su estado como el lenguaje aceptado para la administración de RDBMS.

      Gracias al uso extendido del modelo relacional en varias industrias, se lo comenzó a reconocer como el modelo estándar para la administración de datos. Incluso con el surgimiento de varias bases de datos NoSQL en los últimos años, las bases de datos relacionales siguen siendo las herramientas predominantes para almacenar y organizar datos.

      Cómo organizan los datos las bases de datos relacionales

      Ahora que tiene una idea general de la historia del modelo relacional, vamos a analizar en detalle cómo organiza los datos.

      Los elementos más fundamentales del modelo relacional son las relaciones, que los usuarios y los RDBMS modernos reconocen como tablas. Una relación es un conjunto de tuplas, o filas de una tabla, en el que cada una de ellas comparte un conjunto de atributos o columnas:

      Diagrama de ejemplo de la asociación entre las relaciones, las tuplas y los atributos

      Una columna es la estructura de organización más pequeña de una base de datos relacional y representa las distintas facetas que definen los registros en la tabla. De ahí proviene su nombre más formal: atributos. Se puede pensar que cada tupla es como una instancia única de cualquier tipo de personas, objetos, eventos o asociaciones que contenga la tabla.  Estas instancias pueden ser desde empleados de una empresa y ventas de un negocio en línea hasta resultados de pruebas de laboratorio. Por ejemplo, en una tabla que contiene registros de los maestros de una escuela, las tuplas pueden tener atributos como name, subjects, start_date, etc.

      Al crear una columna, especificamos un* tipo de datos *que determina el tipo de entradas que se permiten en esa columna. Los sistemas de administración de bases de datos relacionales (RDBMS) suelen implementar sus propios tipos de datos únicos, que pueden no ser directamente intercambiables con tipos de datos similares de otros sistemas. Algunos tipos de datos frecuentes son fechas, cadenas, enteros y booleanos.

      En el modelo relacional, cada tabla contiene, por lo menos, una columna que puede utilizarse para identificar de forma única cada fila, lo que se denomina clave primaria. Esto es importante, dado que significa que los usuarios no necesitan saber dónde se almacenan físicamente los datos en una máquina; en su lugar, sus DBMS pueden realizar un seguimiento de cada registro y devolverlo según corresponda. A su vez, significa que los registros no tienen un orden lógico definido y que los usuarios tienen la capacidad de devolver sus datos en cualquier orden y a través de los filtros que deseen.

      Si tiene dos tablas que desea asociar, una manera de hacerlo es con una clave externa. Una clave externa es, básicamente, una copia de la clave primaria de una tabla (la tabla “primaria”) insertada en una columna de otra tabla (la “secundaria”). El siguiente ejemplo destaca la relación entre dos tablas: una se utiliza para registrar información sobre los empleados de una empresa y la otra, para realizar un seguimiento de las ventas de la empresa. En este ejemplo, la clave primaria de la tabla EMPLOYEES se utiliza como clave externa de la tabla SALES:

      Diagrama de ejemplo de cómo la clave primaria de la tabla EMPLOYEE actúa como la clave externa de la tabla SALES

      Si intenta agregar un registro a la tabla secundaria y el valor ingresado en la columna de la clave externa no existe en la clave primaria de la tabla primaria, la instrucción de inserción no será válida. Esto ayuda a mantener la integridad del nivel de las relaciones, dado que las filas de ambas tablas siempre se relacionarán correctamente.

      Los elementos estructurales del modelo relacional ayudan a mantener los datos almacenados de forma organizada, pero el almacenamiento de datos solo es útil si se pueden recuperar. Para obtener información de un RDBMS, puede emitir una consulta o una solicitud estructurada de un conjunto de información. Como se mencionó anteriormente, la mayoría de las bases de datos relacionales utilizan SQL para administrar y consultar datos. SQL permite filtrar y manipular los resultados de las consultas con una variedad de cláusulas, predicados y expresiones, lo que, a su vez, permite controlar correctamente qué datos se mostrarán en el conjunto de resultados.

      Ventajas y limitaciones de las bases de datos relacionales

      Teniendo en cuenta la estructura organizativa subyacente de las bases de datos relacionales, consideremos algunas de sus ventajas y desventajas.

      Hoy en día, tanto SQL como las bases de datos que lo implementan se desvían del modelo relacional de Codd de diversas maneras. Por ejemplo, el modelo de Codd determina que cada fila de una tabla debe ser única, mientras que, por cuestiones de practicidad, la mayoría de las bases de datos relacionales modernas permiten la duplicación de filas. Algunas personas no consideran que las bases de datos SQL sean verdaderas bases de datos relacionales a menos que cumplan con las especificaciones de Codd del modelo relacional. Sin embargo, en términos prácticos, es probable que cualquier DBMS que utilice SQL y, por lo menos, se adhiera en cierta medida al modelo relacional se denomine “sistema de administración de bases de datos relacionales”.

      A pesar de que las bases de datos relacionales ganaron popularidad rápidamente, algunas de las deficiencias del modelo relacional comenzaron a hacerse evidentes a medida que los datos se volvieron más valiosos y las empresas comenzaron a almacenar más de ellos. Entre otras cosas, puede ser difícil escalar una base de datos relacional de forma horizontal.  Los términos escalado horizontal o escala horizontal se refieren a la práctica de agregar más máquinas a una pila existente para extender la carga y permitir un mayor tráfico y un procesamiento más rápido. Se suele contrastar con el escalado vertical, que implica la actualización del hardware de un servidor existente, generalmente, añadiendo más RAM o CPU.

      El motivo por el cual es difícil escalar una base de datos relacional de forma horizontal está relacionado con el hecho de que el modelo relacional se diseñó para garantizar coherencia, lo que significa que los clientes que realizan consultas en la misma base de datos siempre obtendrán los mismos datos. Al querer escalar una base de datos relacional de forma horizontal en varias máquinas, resulta difícil asegurar la coherencia, dado que los clientes pueden escribir datos en un nodo pero no en otros.  Es probable que haya un retraso entre la escritura inicial y el momento en que se actualicen los demás nodos para reflejar los cambios, lo que daría lugar a inconsistencias entre ellos.

      Otra limitación que presentan los RDBMS es que el modelo relacional se diseñó para administrar datos estructurados o alineados con un tipo de datos predeterminado o, por lo menos, organizado de una manera predeterminada para que se puedan ordenar o buscar de forma más sencilla. Sin embargo, con la difusión de los equipos informáticos personales y el auge de Internet a principios de la década de 1990, los datos no estructurados, como los mensajes de correo electrónico, las fotos, los videos, etc., se volvieron más comunes.

      Nada de esto significa que las bases de datos relacionales no sean útiles. Al contrario, después de más de 40 años, el modelo relacional sigue siendo el marco dominante para la administración de datos. Su prevalencia y longevidad indican que las bases de datos relacionales son una tecnología madura, lo que constituye una de sus principales ventajas. Hay muchas aplicaciones diseñadas para trabajar con el modelo relacional, así como muchos administradores de bases de datos profesionales expertos en bases de datos relacionales. También hay una amplia variedad de recursos disponibles en formato impreso y digital para quienes desean comenzar a utilizar bases de datos relacionales.

      Otra ventaja de las bases de datos relacionales es que casi todos los RDBMS admiten transacciones. Las transacciones constan de una o más instrucciones SQL individuales que se ejecutan en secuencia como una unidad de trabajo única. Las transacciones tienen un enfoque de todo o nada, lo que significa que todas las instrucciones SQL de una transacción deben ser válidas; de lo contrario, falla en su totalidad. Esto es muy útil para garantizar la integridad de los datos al realizar cambios en varias filas o tablas.

      Por último, las bases de datos relacionales son sumamente flexibles. Se han utilizado para crear una amplia variedad de aplicaciones distintas y siguen funcionando de forma eficiente incluso con grandes cantidades de datos. SQL también es sumamente potente y permite agregar y cambiar datos sobre la marcha, así como alterar la estructura de los esquemas y las tablas de las bases de datos sin afectar a los datos existentes.

      Conclusión

      Gracias a su flexibilidad y diseño para la integridad de los datos, más de cincuenta años después de su concepción inicial, las bases de datos relacionales siguen siendo la principal forma de administrar y almacenar datos.  A pesar del surgimiento de diversas bases de datos NoSQL en los últimos años, la comprensión del modelo relacional y la manera de trabajar con RDBMS es fundamental para cualquier persona que desee crear aplicaciones que aprovechen el poder de los datos.

      Para obtener más información sobre RDBMS populares de código abierto, le recomendamos consultar nuestra comparación de diversas bases de datos relacionales SQL de código abierto. Si desea obtener más información sobre las bases de datos en general, le recomendamos consultar nuestra biblioteca completa de contenidos relacionados con bases de datos.



      Source link

      [Guía de inicio rápido] sobre cómo instalar y configurar Ansible en Ubuntu 18.04


      Introducción

      En esta guía, explicaremos cómo instalar y configurar Ansible en un servidor Ubuntu 18.04. Para obtener una versión más detallada de este tutorial, con más explicaciones de cada paso, consulte Cómo instalar y configurar Ansible en Ubuntu 18.04.

      Requisitos previos

      Para este tutorial, necesitará lo siguiente:

      • Un nodo de control de Ansible: un sistema Ubuntu 18.04 donde se instalará Ansible. Puede ser un servidor remoto o una máquina local.
      • Uno o más hosts de Ansible: uno o más servidores de Ubuntu 18.04 accesibles desde su nodo de control mediante SSH.

      Paso 1: Instalar Ansible

      Desde su nodo de control, ejecute el siguiente comando para incluir el PPA (archivo de paquetes personal) oficial del proyecto en la lista de fuentes de su sistema:

      • sudo apt-add-repository ppa:ansible/ansible

      Actualice el índice de paquetes de su sistema con lo siguiente:

      Después de esta actualización, podrá instalar el software Ansible con lo siguiente:

      Paso 2: Configurar el archivo de inventario

      Para editar el contenido de su inventario predeterminado de Ansible, abra el archivo /etc/ansible/hosts con el editor de texto que prefiera:

      • sudo nano /etc/ansible/hosts

      El archivo de inventario predeterminado proporcionado por la instalación de Ansible contiene varios ejemplos que puede utilizar como referencias para configurar su inventario. En el siguiente ejemplo se define un grupo llamado [servers] con tres servidores diferentes, cada uno identificado por un alias personalizado: server1, server2 y server3. Asegúrese de reemplazar las IP resaltadas por las direcciones IP de sus hosts de Ansible.

      /etc/ansible/hosts

      [servers]
      server1 ansible_host=203.0.113.111
      server2 ansible_host=203.0.113.112
      server3 ansible_host=203.0.113.113
      
      [all:vars]
      ansible_python_interpreter=/usr/bin/python3
      

      El subgrupo all:vars establece el parámetro de host ansible_python_interpreter, que será válido para todos los hosts de este inventario. Este parámetro garantiza que el servidor remoto utilice el ejecutable /usr/bin/python3 Python 3 en lugar de /usr/bin/python (Python 2.7), que no está presente en versiones recientes de Ubuntu.

      No olvide guardar y cerrar el archivo cuando termine.

      Paso 3: Probar la conexión

      Puede usar el argumento -u para especificar el usuario de sistema remoto. Cuando no se proporcione, Ansible intentará conectarse como su usuario de sistema actual en el nodo de control.

      Desde su nodo de control de Ansible, ejecute lo siguiente:

      • ansible all -m ping -u root

      El resultado deberá ser similar a este:

      Output

      server1 | SUCCESS => { "changed": false, "ping": "pong" } server2 | SUCCESS => { "changed": false, "ping": "pong" } server3 | SUCCESS => { "changed": false, "ping": "pong" }

      Si es la primera vez que se conecta a estos servidores a través de SSH, se le solicitará confirmar la autenticidad de los hosts a los que se conecte a través de Ansible. Cuando se le solicite, escriba yes y luego presione ENTER para confirmar.

      Una vez que reciba una respuesta “pong” de un host, estará listo para ejecutar comandos y playbooks de Ansible en el servidor en cuestión.

      Tutoriales relacionados

      A continuación, se ofrecen los enlaces a más guías detalladas relacionadas con este tutorial:



      Source link