Ir al contenido

Dimensionar un despliegue

Todo lo de esta página es modo HTTP, y todo viene del consumo de recursos, que mide el binario real y nombra la máquina en la que se ejecutó. El host de referencia es un Intel i5-14400 con 16 hilos, y se vuelve a medir en cada versión.

Lee primero Servidor HTTP si el pool, la lista de instancias permitidas y los modos de autenticación no te resultan ya familiares.

Mantener una credencial es casi gratis. El catálogo, sus esquemas, el índice de descubrimiento y el manifiesto de herramientas se comparten por configuración, y el propio servidor MCP se comparte por forma de configuración, así que lo que cuesta una credencial es su cliente de GitLab, su cubo de límite de peticiones, su contador de listen, sus watchers y sus sesiones.

Servir una llamada es donde una instancia se agota. El tiempo de CPU por llamada es el término que limita, y la compartición no lo toca. Todo lo que sigue sale de mantener esas dos cosas separadas.

Medida en reposo y sin ninguna conexión abierta, una credencial del pool cuesta 7,7 KiB en la superficie dinámica, 8,3 KiB en la meta y 8,5 KiB en la individual. Es la misma cifra tres veces, porque lo que guarda una credencial es su cliente de GitLab y su contabilidad, no sus herramientas.

La prueba de regresión que se distribuye toma la misma lectura con las conexiones del arnés de pruebas abiertas: ejecutada en un AMD Ryzen 5 3550H (8 hilos, 60,8 GiB, Go 1.27.1), el heap vivo crece 0,14 MiB entre una credencial y veinte en la superficie dinámica y 0,16 MiB en la individual.

Tres cosas acotan esa medida:

  • Es el heap vivo tras una recolección, no el conjunto residente. El residente es mayor y no encoge de inmediato, porque Go devuelve memoria al sistema operativo de forma perezosa.
  • Es sin ninguna conexión abierta. Una credencial que mantiene una cuesta además los búferes que hay detrás, que el benchmark de recursos mide aparte.
  • Es en reposo. Una credencial con peticiones en vuelo cuesta lo que esas peticiones reserven. Cualquier cifra por credencial medida bajo carga mezcla ocupación con carga y no puede multiplicarse por un número de credenciales.

Lo que cuesta una forma de configuración, una sola vez

Sección titulada «Lo que cuesta una forma de configuración, una sola vez»

Una forma es todo lo que decide qué registra un servidor: superficie de herramientas, superficie de capacidades, modo de esquema de parámetros de las meta-herramientas, tier y si se fijó, GitLab.com o autogestionado, solo lectura incluida la restricción que provoca un token read_api, modo seguro, herramientas excluidas, ámbitos del token y si el transporte es sin estado. Toda credencial cuyo hash caiga en una forma la sirve un único servidor MCP.

Un proceso con una forma registrada y una credencial tiene un heap vivo de unos 38 MiB en la superficie dinámica y 88 MiB en la individual, de la misma ejecución en el mismo host, en reposo. Un proceso HTTP sin ninguna credencial, y por tanto sin forma registrada, ocupa unos 35 MiB residentes en el host de referencia.

EntradaValores en un despliegue
Tier1 con --tier fijado; hasta 3 (free, premium, ultimate) cuando se detecta por credencial
Ámbitos del token2, porque solo admin_mode cambia el catálogo
Detección de ámbitos2, o 1 con --ignore-scopes
Restricción a solo lectura2 cuando el operador no fijó --read-only, 1 cuando sí
GitLab.com o no1, o 2 en un despliegue que publica ambos
Todo lo demás1 cada uno; son ajustes de proceso

Un despliegue con --tier fijado y --ignore-scopes produce exactamente una forma. Uno típico produce entre dos y ocho. Cada una cuesta una construcción de catálogo (medida en 1,8 segundos en la superficie dinámica y 3,0 en la individual) pagada una vez por proceso en lugar de una vez por credencial.

En el host de referencia, bajo la carga de la serie de concurrencia: cuatro peticiones en vuelo por credencial en las superficies dinámica y meta, y dos en la individual.

SuperficieTiempo de CPU por llamadaQué lo domina
dynamicunos 8 msEl serializado y la validación del SDK
metaunos 8 msLo mismo
individualunos 120 msSerializar un tools/list de 3 MB
techo de llamadas por segundo = hilos utilizables / segundos de CPU por llamada

16 / 0,008 son 2.000 llamadas por segundo en teoría. La serie medida se estanca en unas 1.800 llamadas por segundo en la superficie dinámica, alcanzadas con cinco credenciales que mantienen cuatro peticiones en vuelo cada una, y sin superarse por muchas credenciales más que se añadan; esa meseta son catorce de los dieciséis hilos del host. La superficie individual se estanca en unas 130 llamadas por segundo en el mismo host.

Úsalo para dimensionar, no como promesa: tu GitLab está al otro lado de una red que esta medida no cruzó.

Quinientas personas desarrollando, un editor cada una, en la superficie dinámica por defecto, contra una instancia Ultimate autogestionada, con --tier=ultimate fijado.

Memoria. Una forma, luego un catálogo: unos 38 MiB de heap vivo. Quinientas credenciales a 7,7 KiB son menos de 4 MiB. La ocupación no es el término que dimensiona este despliegue; el pico de residente lo decide cuántas llamadas hay en vuelo. Un suelo de 512 MiB es el punto de partida correcto, y lo primero que hay que medir es el pico de residente con tu propio tráfico, no el número de credenciales.

CPU. Quinientos editores no hacen quinientas llamadas concurrentes. Cincuenta llamadas por segundo son 50 × 0,008 = 0,4 de un hilo en el host de referencia. Mil son ocho hilos, algo más de la mitad del techo de un host de referencia; añade una segunda instancia por margen, no por memoria.

Busca una segunda instancia por disponibilidad, antes que por capacidad. El techo que suele limitar a un despliegue ocupado es el propio límite de peticiones de GitLab contra un token, que ningún número de instancias eleva.

AjustePor defectoA escala
--max-http-clients100Ponlo por encima de tu población simultánea esperada; máximo 10000. El desalojo ya no es barato: termina las suscripciones de esa credencial y cierra sus flujos de listen. La presión de tamaño prefiere una entrada que no sirva ninguna, y un valor por encima de 1024 (513 en el transporte sin estado por defecto) deja inalcanzable el desalojo de una entrada ocupada en reposo. Ver la palanca
--pool-idle-timeout1hDéjalo. El barrido corre cada cuarto del tiempo de espera con un suelo de un minuto. Una entrada con watchers vivos o flujos de listen abiertos nunca se desaloja por inactividad
--revalidate-interval15mEl barrido es secuencial con diez segundos de espera por entrada, así que un pool grande contra una instancia lenta cuesta hasta entradas × 10 s por ronda. Una entrada de más de una hora se reconstruye igualmente en el siguiente uso
--rate-limit-rps / --rate-limit-burst10 / 40Por credencial y por proceso. Varias instancias lo multiplican salvo que la afinidad fije a cada cliente en una
--action-timeout65mPor encima de la espera más larga que ofrece cualquier acción. Bájalo solo si prefieres fallar una espera de pipeline a retener una goroutine
GITLAB_MCP_MAX_LISTEN_STREAMS64Por credencial. Un segundo techo de 512 por proceso no es configurable a propósito
--session-timeout30mSolo con --stateless=false. Con el transporte por defecto, una sesión termina con su POST
--http-idle-timeout0Déjalo desactivado. Un valor positivo corta los flujos de larga duración
--drain-delay0Ponlo al menos en un intervalo de detección del balanceador

Otros tres límites no son configurables: diez watchers de recursos por credencial y 512 en todo el proceso, y diez autenticaciones fallidas por minuto y dirección de cliente antes de que esa dirección reciba 429 durante un minuto. Los techos de watchers rechazan en lugar de desalojar: una credencial se acuña con una llamada a la API, así que un número por credencial se multiplica por cuantas tenga quien llame y solo el del proceso acota el proceso.

Lo que no crece con el número de credenciales

Sección titulada «Lo que no crece con el número de credenciales»
  • El catálogo registrado, que se paga una vez por forma.
  • La construcción del catálogo, igual. Una credencial que llega a una forma que otra credencial ya construyó no espera nada.
  • Las goroutines, que son por watcher, por flujo de listen abierto y por sesión viva, no por credencial. Una credencial que no hace nada no tiene ninguna.

Preguntas frecuentes

¿Cuánta memoria cuesta una credencial en el pool?

En reposo y sin ninguna conexión abierta, 7,7 KiB en la superficie dinámica, 8,3 KiB en la meta y 8,5 KiB en la individual. El catálogo, sus esquemas, el índice de descubrimiento y el propio servidor MCP se comparten por forma de configuración, así que lo que guarda una credencial es su cliente de GitLab, su cubo de límite de peticiones, su contador de listen, sus watchers y sus sesiones, y por eso la cifra apenas cambia con la superficie. Es el heap vivo de un proceso ocioso; una credencial que mantiene una conexión cuesta además los búferes que hay detrás, y una con peticiones en vuelo cuesta lo que esas peticiones reserven, que es el término que realmente dimensiona una instancia.

¿Cuántas llamadas por segundo aguanta una instancia?

Hilos divididos entre el tiempo de CPU por llamada. En el host de referencia del benchmark, un Intel i5-14400 con 16 hilos, una llamada cuesta unos 8 ms en las superficies dinámica y meta y unos 120 ms en la individual, y la serie medida se estanca en torno a 1.800 llamadas por segundo en la dinámica, alcanzadas con cinco credenciales ocupadas a la vez y usando catorce de los dieciséis hilos. La superficie individual se estanca cerca de 130 llamadas por segundo, porque un tools/list allí cuesta quince veces lo que una llamada dinámica entera.

¿Dimensiono la memoria con `--max-http-clients`?

No. Acota cuántas credenciales mantiene el pool, y una credencial del pool son decenas de kilobytes, así que su valor por defecto de 100 acota unos cinco mebibytes. Dimensionar una instancia con él es erróneo en ambos sentidos: ni reserva esa memoria ni limita lo que reservan los llamantes que hay detrás de esas credenciales mientras se atienden sus peticiones. Dimensiona por cuántos llamantes tendrán peticiones en vuelo a la vez.

Cuando una instancia deja de bastar, la siguiente pregunta es cómo se reparten los clientes entre varias: Balanceo de carga.