Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El modo de distribución best-worker
selecciona primero aquellos trabajos que mejor pueden controlar el trabajo. La lógica para clasificar los trabajadores se puede personalizar, con una expresión o una función de Azure para comparar dos trabajadores. En el ejemplo siguiente se muestra cómo personalizar esta lógica con su propia función de Azure.
Escenario: Regla de puntuación personalizada en el mejor modo de distribución de trabajo
Queremos distribuir ofertas entre sus trabajadores asociados a una cola. A los trabajadores se les dará una puntuación basada en sus etiquetas y en el conjunto de aptitudes. El trabajo con la puntuación más alta debe obtener la primera oferta (modo de distribución BestWorker).
Situación
- Se ha creado y clasificado un trabajo.
- El trabajo tiene las siguientes etiquetas asociadas
- ["CommunicationType"] = "Chat"
- ["IssueType"] = "XboxSupport"
- ["Language"] = "en"
- ["HighPriority"] = true
- ["SubIssueType"] = "ConsoleMalfunction"
- ["ConsoleType"] = "XBOX_SERIES_X"
- ["Model"] = "XBOX_SERIES_X_1TB"
- El trabajo tiene los siguientes workerSelectors asociados a él
- ["English"] >= 7
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- El trabajo tiene las siguientes etiquetas asociadas
- El trabajo se encuentra actualmente en el estado "En cola"; se encuentra en cola en la cola de soporte técnico de hardware de Xbox a la espera de que coincida con un trabajo.
- Varios trabajos están disponibles simultáneamente.
- El trabajo 1 se ha creado con las siguientes etiquetas.
- ["HighPrioritySupport"] = true
- ["HardwareSupport"] = true
- ["Support_XBOX_SERIES_X"] = true
- ["English"] = 10
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- El trabajo 2 se ha creado con las siguientes etiquetas.
- ["HighPrioritySupport"] = true
- ["HardwareSupport"] = true
- ["Support_XBOX_SERIES_X"] = true
- ["Support_XBOX_SERIES_S"] = true
- ["English"] = 8
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- El trabajo 3 se ha creado con las siguientes etiquetas.
- ["HighPrioritySupport"] = false
- ["HardwareSupport"] = true
- ["Support_XBOX"] = true
- ["English"] = 7
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- El trabajo 1 se ha creado con las siguientes etiquetas.
Expectativa
Nos gustaría que el comportamiento siguiente al puntuar los trabajos seleccione qué trabajo obtiene la primera oferta.
El flujo de decisión (como se ha mostrado anteriormente) es el siguiente:
Si un trabajo es NO HighPriority:
- Trabajos con la etiqueta: ["Support_XBOX"] = true; obtienen una puntuación de 100.
- De lo contrario, obtienen una puntuación de 1.
Si un trabajo es HighPriority:
- Trabajos con la etiqueta: ["HighPrioritySupport"] = false; obtienen una puntuación de 1.
- De lo contrario, si ["HighPrioritySupport"] = true:
- ¿El trabajo se especializa en el tipo de consola ->; el trabajo tiene la etiqueta: ["Support_<jobLabels.ConsoleType>"] = true? Si es true, el trabajo obtiene una puntuación de 200.
- De lo contrario, obtienen una puntuación de 100.
Creación de una función de Azure
Antes de continuar con el proceso, vamos a definir primero una función de Azure que puntúa el trabajo.
Nota:
La siguiente función de Azure usa JavaScript. Para más información, vea Inicio rápido: Creación de una función de JavaScript en Azure con Visual Studio Code.
Entrada de ejemplo para el trabajo 1
{
"job": {
"CommunicationType": "Chat",
"IssueType": "XboxSupport",
"Language": "en",
"HighPriority": true,
"SubIssueType": "ConsoleMalfunction",
"ConsoleType": "XBOX_SERIES_X",
"Model": "XBOX_SERIES_X_1TB"
},
"selectors": [
{
"key": "English",
"operator": "GreaterThanEqual",
"value": 7,
"expiresAfterSeconds": null
},
{
"key": "ChatSupport",
"operator": "Equal",
"value": true,
"expiresAfterSeconds": null
},
{
"key": "XboxSupport",
"operator": "Equal",
"value": true,
"expiresAfterSeconds": null
}
],
"worker": {
"Id": "e3a3f2f9-3582-4bfe-9c5a-aa57831a0f88",
"HighPrioritySupport": true,
"HardwareSupport": true,
"Support_XBOX_SERIES_X": true,
"English": 10,
"ChatSupport": true,
"XboxSupport": true
}
}
Ejemplo de implementación:
module.exports = async function (context, req) {
context.log('Best Worker Distribution Mode using Azure Function');
let score = 0;
const jobLabels = req.body.job;
const workerLabels = req.body.worker;
const isHighPriority = !!jobLabels["HighPriority"];
context.log('Job is high priority? Status: ' + isHighPriority);
if(!isHighPriority) {
const isGenericXboxSupportWorker = !!workerLabels["Support_XBOX"];
context.log('Worker provides general xbox support? Status: ' + isGenericXboxSupportWorker);
score = isGenericXboxSupportWorker ? 100 : 1;
} else {
const workerSupportsHighPriorityJob = !!workerLabels["HighPrioritySupport"];
context.log('Worker provides high priority support? Status: ' + workerSupportsHighPriorityJob);
if(!workerSupportsHighPriorityJob) {
score = 1;
} else {
const key = `Support_${jobLabels["ConsoleType"]}`;
const workerSpecializeInConsoleType = !!workerLabels[key];
context.log(`Worker specializes in consoleType: ${jobLabels["ConsoleType"]} ? Status: ${workerSpecializeInConsoleType}`);
score = workerSpecializeInConsoleType ? 200 : 100;
}
}
context.log('Final score of worker: ' + score);
context.res = {
// status: 200, /* Defaults to 200 */
body: score
};
}
Salida del trabajo 1
200
Con la implementación mencionada anteriormente, para el trabajo dado, se obtienen las siguientes puntuaciones para los trabajos:
Trabajador | Score |
---|---|
Trabajo 1 | 200 |
Trabajo 2 | 200 |
Trabajo 3 | 1 |
Distribución de ofertas basadas en el mejor modo de trabajo
Ahora que la aplicación de funciones de Azure está lista, vamos a crear una instancia del modo BestWorkerDistribution mediante el SDK de enrutador.
var administrationClient = new JobRouterAdministrationClient("<YOUR_ACS_CONNECTION_STRING>");
// Setup Distribution Policy
var distributionPolicy = await administrationClient.CreateDistributionPolicyAsync(
new CreateDistributionPolicyOptions(
distributionPolicyId: "BestWorkerDistributionMode",
offerExpiresAfter: TimeSpan.FromMinutes(5),
mode: new BestWorkerMode(scoringRule: new FunctionRouterRule(new Uri("<insert function url>")))
) { Name = "XBox hardware support distribution" });
// Setup Queue
var queue = await administrationClient.CreateQueueAsync(
new CreateQueueOptions(
queueId: "XBox_Hardware_Support_Q",
distributionPolicyId: distributionPolicy.Value.Id
) { Name = "XBox Hardware Support Queue" });
// Create workers
var worker1 = await client.CreateWorkerAsync(new CreateWorkerOptions(workerId: "Worker_1", capacity: 100)
{
Queues = { queue.Value.Id },
Channels = { new RouterChannel(channelId: "Xbox_Chat_Channel", capacityCostPerJob: 10) },
Labels =
{
["English"] = new RouterValue(10),
["HighPrioritySupport"] = new RouterValue(true),
["HardwareSupport"] = new RouterValue(true),
["Support_XBOX_SERIES_X"] = new RouterValue(true),
["ChatSupport"] = new RouterValue(true),
["XboxSupport"] = new RouterValue(true)
}
});
var worker2 = await client.CreateWorkerAsync(new CreateWorkerOptions(workerId: "Worker_2", capacity: 100)
{
Queues = { queue.Value.Id },
Channels = { new RouterChannel(channelId: "Xbox_Chat_Channel", capacityCostPerJob: 10) },
Labels =
{
["English"] = new RouterValue(8),
["HighPrioritySupport"] = new RouterValue(true),
["HardwareSupport"] = new RouterValue(true),
["Support_XBOX_SERIES_X"] = new RouterValue(true),
["ChatSupport"] = new RouterValue(true),
["XboxSupport"] = new RouterValue(true)
}
});
var worker3 = await client.CreateWorkerAsync(new CreateWorkerOptions(workerId: "Worker_3", capacity: 100)
{
Queues = { queue.Value.Id },
Channels = { new RouterChannel(channelId: "Xbox_Chat_Channel", capacityCostPerJob: 10) },
Labels =
{
["English"] = new RouterValue(7),
["HighPrioritySupport"] = new RouterValue(true),
["HardwareSupport"] = new RouterValue(true),
["Support_XBOX_SERIES_X"] = new RouterValue(true),
["ChatSupport"] = new RouterValue(true),
["XboxSupport"] = new RouterValue(true)
}
});
// Create Job
var job = await client.CreateJobAsync(
new CreateJobOptions(jobId: "job1", channelId: "Xbox_Chat_Channel", queueId: queue.Value.Id)
{
Priority = 100,
ChannelReference = "ChatChannel",
RequestedWorkerSelectors =
{
new RouterWorkerSelector(key: "English", labelOperator: LabelOperator.GreaterThanEqual, value: new RouterValue(7)),
new RouterWorkerSelector(key: "ChatSupport", labelOperator: LabelOperator.Equal, value: new RouterValue(true)),
new RouterWorkerSelector(key: "XboxSupport", labelOperator: LabelOperator.Equal, value: new RouterValue(true))
},
Labels =
{
["CommunicationType"] = new RouterValue("Chat"),
["IssueType"] = new RouterValue("XboxSupport"),
["Language"] = new RouterValue("en"),
["HighPriority"] = new RouterValue(true),
["SubIssueType"] = new RouterValue("ConsoleMalfunction"),
["ConsoleType"] = new RouterValue("XBOX_SERIES_X"),
["Model"] = new RouterValue("XBOX_SERIES_X_1TB")
}
});
// Wait a few seconds and see which worker was matched
await Task.Delay(TimeSpan.FromSeconds(5));
var getJob = await client.GetJobAsync(job.Value.Id);
Console.WriteLine(getJob.Value.Assignments.Select(assignment => assignment.Value.WorkerId).First());
Salida
Worker_1 // or Worker_2
Since both workers, Worker_1 and Worker_2, get the same score of 200,
the worker who has been idle the longest will get the first offer.