Modo Router de Faucet
El modo router de Faucet te permite servir múltiples aplicaciones distintas desde una única instancia de Faucet. Cada aplicación, o "ruta", puede tener su propia configuración (como tipo de aplicación, directorio de trabajo, número de workers y estrategia de balanceo de carga) y es accesible a través de un prefijo de ruta URL único.
Esto es particularly útil para:
- Alojar múltiples aplicaciones Shiny, APIs de Plumber o documentos Quarto Shiny en el mismo servidor y puerto.
- Desplegar diferentes versiones o configuraciones de la misma aplicación bajo diferentes rutas.
- Consolidar tus despliegues de aplicaciones R en un único proceso de Faucet.
Resumen en Video
Para una demostración visual de la característica del router de Faucet, revisa el siguiente video:
Activación del Modo Router
Para ejecutar Faucet en modo router, utilizas el subcomando router:
faucet router [OPCIONES]
La opción principal para el modo router es especificar el archivo de configuración:
- CLI:
--conf <RUTA_AL_ARCHIVO_DE_CONFIGURACION>o-c <RUTA_AL_ARCHIVO_DE_CONFIGURACION> - Variable de Entorno:
FAUCET_ROUTER_CONF=<RUTA_AL_ARCHIVO_DE_CONFIGURACION> - Por Defecto: Si no se especifica, Faucet buscará un archivo llamado
frouter.tomlen el directorio de trabajo actual (./frouter.toml).
Las opciones globales de Faucet como --host, --ip-from, --rscript, --quarto y las configuraciones de telemetría (por ejemplo, --pg-con-string) se aplican a toda la instancia del router y a todas las rutas que gestiona.
Archivo de Configuración (frouter.toml)
El modo router se configura mediante un archivo TOML. Este archivo debe definir un array llamado route, donde cada elemento del array es un objeto que configura una ruta de aplicación específica.
Aquí está la estructura de un único objeto de ruta dentro del archivo frouter.toml:
[[route]]
# El prefijo de la ruta URL para esta aplicación.
# Este prefijo DEBE terminar con una barra inclinada (ej., "/app/", "/api/v1/").
# Si es la ruta raíz, debe ser "/".
# (Requerido)
route = "/mi_aplicacion/"
# El tipo de aplicación.
# (Requerido)
# Posibles valores: "plumber", "shiny", "quarto-shiny"
# Alias como "Plumber", "Shiny", "QuartoShiny" también son aceptados.
server_type = "shiny"
# El directorio de trabajo para esta aplicación específica.
# Archivos como app.R o plumber.R se buscarán en relación con este directorio,
# o dentro de `app_dir` si se especifica. Las rutas pueden ser relativas (a donde está frouter.toml) o absolutas.
# (Opcional, por defecto es "." - el directorio donde se encuentra frouter.toml)
workdir = "./apps/mi_app_shiny"
# El subdirectorio dentro de `workdir` donde se encuentra el archivo principal de la aplicación (ej., app.R).
# Si tu app.R está directamente en `workdir`, puedes omitir esto o configurarlo como ".".
# (Opcional)
app_dir = "source" # Busca ./apps/mi_app_shiny/source/app.R
# El número de procesos worker a generar para esta aplicación.
# (Requerido)
workers = 2
# La estrategia de balanceo de carga para esta aplicación.
# (Opcional, los valores por defecto dependen del tipo de aplicación: "ip-hash" para shiny/quarto-shiny, "round-robin" para plumber)
# Posibles valores: "round-robin", "ip-hash", "cookie-hash"
strategy = "ip-hash"
# Ruta al documento Quarto (.qmd), requerido si server_type es "quarto-shiny".
# La ruta debe ser relativa a `workdir` o una ruta absoluta.
# (Opcional, pero requerido para quarto-shiny)
# qmd = "dashboard.qmd"
Campos Explicados:
route(String, Requerido): El prefijo de la ruta URL. Este prefijo debe terminar con una barra inclinada (ej.,/app/,/api/v1/) a menos que sea la ruta raíz (/). Faucet dirigirá las solicitudes que comiencen con esta ruta a la aplicación configurada.server_type(String, Requerido): Determina el tipo de aplicación R. Debe ser uno deplumber,shinyoquarto-shiny. Alias comoPlumber,Shiny,QuartoShinytambién son aceptados.workdir(String, Opcional): El directorio de trabajo base para la aplicación. Si no se especifica, por defecto es el directorio donde se está ejecutando Faucet (típicamente donde se encuentrafrouter.toml). Las rutas paraapp_diryqmdse resuelven típicamente en relación con este.app_dir(String, Opcional): Un subdirectorio dentro deworkdirque contiene el archivo principal de la aplicación (por ejemplo,app.Rpara Shiny,plumber.Rpara Plumber). Por ejemplo, siworkdir = "./mi_coleccion_apps"yapp_dir = "app_especifica_src", Faucet buscará./mi_coleccion_apps/app_especifica_src/app.R. Si el archivo principal está directamente enworkdir, puedes omitir esto o usarapp_dir = ".".workers(Integer, Requerido): El número de procesos worker de R a lanzar para esta ruta específica. Debe ser un entero positivo.strategy(String, Opcional): La estrategia de balanceo de carga para esta ruta.- Para aplicaciones
shinyyquarto-shiny, generalmente se recomiendaip-hashy es el valor por defecto para asegurar la persistencia de la sesión. - Para APIs
plumber,round-robines el valor por defecto común. - Opciones disponibles:
round-robin,ip-hash,cookie-hash.
- Para aplicaciones
qmd(String, Opcional): Siserver_typeesquarto-shiny, este campo es requerido y debe especificar la ruta al archivo.qmd. Esta ruta es típicamente relativa aworkdir.
Importante: Cada valor de route en el archivo de configuración debe ser único. Rutas duplicadas harán que Faucet termine con un error al iniciarse.
Comportamiento del Enrutamiento y Eliminación de Prefijo de Ruta (Path Stripping)
Cuando Faucet recibe una solicitud HTTP en modo router:
- Itera a través de las definiciones
[[route]]enfrouter.tomlen el orden en que están definidas. - Coincidencia de Rutas y Orden:
- Para cada ruta definida, Faucet comprueba si la ruta URL de la solicitud entrante comienza con el prefijo
routede la ruta. - Se utiliza la primera ruta que coincida. Esto significa que el orden de tus rutas en
frouter.tomles crítico. Las rutas más específicas (ej.,/app/feature1/) deben listarse antes que las rutas más generales (ej.,/app/) si comparten una ruta base común, para evitar que la ruta general "sombreé" a la específica. La ruta raíz/generalmente debe listarse al final.
- Para cada ruta definida, Faucet comprueba si la ruta URL de la solicitud entrante comienza con el prefijo
- Eliminación de Prefijo de Ruta (Path Stripping):
- Todos los prefijos
route(excepto la ruta raíz/) deben terminar con una barra inclinada (/). - Una vez que se encuentra una ruta coincidente, su prefijo
routedefinido se elimina del inicio de la ruta URL de la solicitud. - La parte restante de la ruta se reenvía entonces a la aplicación configurada para esa ruta.
- Ejemplo: Si se define
route = "/myapp/":- Una solicitud a
/myapp/usuarios/1hace que la aplicación vea/usuarios/1. - Una solicitud a
/myapp/(con la barra inclinada final) hace que la aplicación vea/.
- Una solicitud a
- Ejemplo: Si se define
route = "/":- Una solicitud a
/paginahace que la aplicación vea/pagina. - Una solicitud a
/hace que la aplicación vea/.
- Una solicitud a
- Todos los prefijos
- Si se encuentra una ruta coincidente, la solicitud (con la ruta potencialmente modificada) se entrega a la instancia del servidor Faucet que gestiona esa aplicación específica, la cual luego aplica su estrategia de balanceo de carga configurada para seleccionar un worker.
- Si ninguna
routeconfigurada coincide con la ruta de la solicitud entrante, Faucet devuelve una respuesta404 Not Found.
Ejemplo de frouter.toml
Este ejemplo se basa en faucet-router-example disponible en el repositorio de GitHub de Faucet bajo el directorio examples/. Para ejecutar este ejemplo, navega a examples/faucet-router-example-main/ y ejecuta faucet router.
# frouter.toml
# Este archivo está ubicado en examples/faucet-router-example-main/
# Ruta para la aplicación Shiny "sliders".
# `workdir` está configurado como "./sliders", entonces Faucet busca app.R
# en examples/faucet-router-example-main/sliders/app.R
[[route]]
route = "/sliders/"
workers = 1
server_type = "shiny" # Nota: "Shiny" (con mayúscula) también es aceptado
workdir = "./sliders"
# Ruta para la aplicación Shiny "text".
# `workdir` por defecto es "." (donde está frouter.toml).
# `app_dir` es "./text", entonces Faucet busca app.R
# en examples/faucet-router-example-main/text/app.R
[[route]]
route = "/text/"
workers = 1
server_type = "shiny"
app_dir = "./text"
# Ruta para un documento Quarto Shiny.
# `workdir` es "./qmd".
# `qmd` especifica "old_faithful.qmd" relativo a workdir.
# Faucet busca examples/faucet-router-example-main/qmd/old_faithful.qmd
[[route]]
route = "/qmd/"
workers = 1
server_type = "quarto-shiny" # Nota: "QuartoShiny" (con mayúscula) también es aceptado
workdir = "./qmd"
qmd = "old_faithful.qmd"
# Ruta para una API de Plumber.
# `workdir` es "./api". Faucet busca plumber.R
# en examples/faucet-router-example-main/api/plumber.R
[[route]]
route = "/api/"
workers = 1
server_type = "plumber" # Nota: "Plumber" (con mayúscula) también es aceptado
workdir = "./api"
strategy = "round-robin"
# Ruta raíz para la aplicación Shiny principal.
# `workdir` por defecto es "." (donde está frouter.toml).
# Faucet busca app.R en examples/faucet-router-example-main/app.R
# Esta ruta se coloca al final para evitar solapar otras rutas específicas.
[[route]]
route = "/"
workers = 1
server_type = "shiny"
strategy = "cookie-hash"
Con la configuración anterior, si Faucet se está ejecutando en http://localhost:3838 desde el directorio examples/faucet-router-example-main/:
- Las solicitudes a
http://localhost:3838/sliders/serían enrutadas a la aplicación Shiny en el subdirectoriosliders. - Las solicitudes a
http://localhost:3838/text/serían enrutadas a la aplicación Shiny en el subdirectoriotext. - Las solicitudes a
http://localhost:3838/qmd/serían enrutadas al documento Quarto Shinyold_faithful.qmd. - Las solicitudes a
http://localhost:3838/api/echo?msg=holaserían enrutadas a la API de Plumber en el subdirectorioapi(la API vería/echo?msg=hola). - Las solicitudes a
http://localhost:3838/serían enrutadas alapp.Ren la raíz del directoriofaucet-router-example-main.
Nota sobre el Orden de las Rutas: Recuerda que si tienes rutas con rutas base superpuestas (ej., /datos/especifico/ y /datos/), debes listar la ruta más específica (/datos/especifico/) antes que la ruta más general (/datos/) en tu archivo frouter.toml. De lo contrario, la ruta general /datos/ coincidiría con las solicitudes destinadas a /datos/especifico/, y nunca se alcanzaría la ruta específica. La ruta raíz / típicamente debería ser la última entrada.
Este modo router proporciona una forma flexible de gestionar y servir múltiples aplicaciones R eficientemente usando una única instancia de Faucet.