Zaroz
Guía de la API de Units

El buffer caliente y allocate

Arrancar un servidor de juego tarda decenas de segundos. Un buffer caliente es un número de unidades que la plataforma mantiene iniciadas e inactivas, de modo que cuando una partida está lista, una sola llamada le entrega un servidor que ya está en marcha.

Pasar la política a modo code

La política de escalado vive en .../units/policy. Cambiarla requiere el token de una persona: un principal de servicio puede controlar unidades pero nunca la política.

curl

TerminalCode
curl -sS -X PATCH "$ZAROZ_API/projects/$PROJECT/service-instances/$SERVICE/units/policy" \ -H "$AUTH" -H "Content-Type: application/json" -d '{ "mode": "code", "max_units": 12, "warm_units": 3, "default_on_exit": "destroy", "idle_action": "stop", "idle_after_seconds": 600, "rollout": "replace_idle" }'

TypeScript

TypeScriptCode
const policy = await call("PATCH", `${UNITS}/policy`, { mode: "code", max_units: 12, warm_units: 3, default_on_exit: "destroy", idle_action: "stop", idle_after_seconds: 600, rollout: "replace_idle", }); console.log(policy.status, policy.body.mode);

Python

Code
status, policy = call("PATCH", f"{UNITS}/policy", { "mode": "code", "max_units": 12, "warm_units": 3, "default_on_exit": "destroy", "idle_action": "stop", "idle_after_seconds": 600, "rollout": "replace_idle", }) print(status, policy["mode"])
CampoSignificadoPor defecto y rango
modefixed, autoscaled o codefixed con una unidad
max_unitsel máximo de unidades con pod a la vez: calientes, asignadas, creadas por clave y en marchahasta el máximo del producto y el límite de tu organización
warm_unitsunidades listas y sin asignar que se mantienen además de todo lo demásde 0 a max_units
default_on_exitrestart, stop o destroyrestart
idle_action, idle_after_secondsdetiene o destruye una unidad que lleva este tiempo señalando idle. Nunca se aplica a unidades calientes sin asignarninguna; de 60 a 86.400
destroy_stopped_after_daysdestruye las unidades detenidas tras este tiempo90; de 1 a 365
ready_timeout_secondsuna unidad que no está Ready tras este tiempo desde que arrancó su pod pasa a Failed300; de 10 a 3.600
readinessauto o signal (Ready solo cuando la unidad señala ready)auto
rolloutrolling, replace_idle o next_startreplace_idle para code
spend_cap_centslo máximo que pueden costar las unidades extra en un mes antes de rechazar el crecimientoel peor caso

Calcula el coste antes de confirmar, con el mismo cuerpo, en POST .../units/policy/quote:

curl

TerminalCode
curl -sS -X POST "$UNITS/policy/quote" -H "$AUTH" -H "Content-Type: application/json" -d '{"mode": "code", "max_units": 12, "warm_units": 3}'

TypeScript

TypeScriptCode
const quote = await call("POST", `${UNITS}/policy/quote`, { mode: "code", max_units: 12, warm_units: 3 }); console.log(quote.body);

Python

Code
status, quote = call("POST", f"{UNITS}/policy/quote", {"mode": "code", "max_units": 12, "warm_units": 3}) print(quote)

Una unidad caliente se factura como cualquier unidad extra en marcha: ocupa CPU y memoria. Cada arranque factura al menos 5 minutos. Las unidades detenidas son gratis.

Allocate

POST .../units/allocate toma una unidad caliente lista, que acepta tráfico, sin asignar y sin drenar, prefiriendo la plantilla actual y después la que lleva más tiempo lista. Fija labels y user_data de la unidad si los envías y el buffer se rellena en aproximadamente un segundo.

curl

TerminalCode
curl -sS -X POST "$UNITS/allocate?wait=delivered" -H "$AUTH" -H "Content-Type: application/json" \ -H "Idempotency-Key: match-7f3a" -d '{ "labels": {"mode": "2v2"}, "user_data": {"roster": ["ana", "luis", "marta", "pau"], "map": "dunes"}, "if_none": "fail" }' # 200 {"created": false, "replayed": false, "unit": {"key": "w-k3m9q2xa", "allocation": {...}, ...}} # 409 {"code": "no-warm-unit", "warm_ready": 0, "warm_starting": 2, "retry_after_seconds": 5, ...}

TypeScript

TypeScriptCode
const res = await call( "POST", `${UNITS}/allocate?wait=delivered`, { labels: { mode: "2v2" }, user_data: { roster: ["ana", "luis", "marta", "pau"], map: "dunes" }, if_none: "fail", }, { "Idempotency-Key": "match-7f3a" }, ); if (res.status === 409 && res.body.code === "no-warm-unit") { // none ready: wait res.body.retry_after_seconds and retry, or use if_none: "create" } else { console.log(res.body.unit.key, res.body.unit.private_name, res.body.unit.public_endpoints); }

Python

Code
status, res = call( "POST", f"{UNITS}/allocate?wait=delivered", { "labels": {"mode": "2v2"}, "user_data": {"roster": ["ana", "luis", "marta", "pau"], "map": "dunes"}, "if_none": "fail", }, headers={"Idempotency-Key": "match-7f3a"}, ) if status == 409 and res["code"] == "no-warm-unit": pass # none ready: sleep res["retry_after_seconds"] and retry, or use if_none="create" else: print(res["unit"]["key"], res["unit"]["private_name"], res["unit"]["public_endpoints"])
  • Atómico. Dos llamadas nunca reciben la misma unidad.
  • Idempotency-Key (opcional, hasta 64 caracteres imprimibles): reintentar con la misma clave devuelve la misma unidad mientras viva (200, replayed: true). Sin ella, cada llamada asigna una unidad nueva. Envíala siempre desde un matchmaker.
  • ?wait=delivered retiene la respuesta hasta que el agente de la unidad ha escrito los archivos de la asignación (/zaroz/allocation.json, /zaroz/user-data.json), hasta 10 segundos. Sin él, unit.allocation_delivered llega como evento.
  • if_none: fail (por defecto) responde 409 no-warm-unit con warm_ready, warm_starting y retry_after_seconds. create arranca en frío una unidad nueva ya asignada a ti y responde 202 con la unidad aún arrancando.
  • Una asignación nunca se deshace. La unidad termina por su propia salida, una parada o una destrucción.
  • Si la región no es alcanzable, la asignación se revierte y recibes 503 region-unreachable. Las unidades en marcha siguen sirviendo.

La unidad de la respuesta trae el private_name (<clave>.<slug-del-workload>) y los public_endpoints a los que enviar a los jugadores.

Despliegues al publicar una imagen nueva

replace_idle reemplaza las unidades obsoletas que no están asignadas ni ocupadas, como mucho una cuarta parte a la vez y creando primero la nueva. Las unidades asignadas u ocupadas se reemplazan cuando terminan. next_start no toca las unidades en marcha y aplica el cambio la próxima vez que una unidad arranque. Mira las reglas de despliegue.

Last modified on