如何自訂背景工作角色為最佳背景工作角色模式排名的方式
best-worker
散發模式會先選擇最能處理作業的背景工作角色。 您可以使用運算式或 Azure 函式來比較兩個背景工作角色,以自訂排名背景工作角色的邏輯。 下列範例示範如何使用您自己的 Azure 函式來自訂此邏輯。
案例:最佳背景工作角色分配模式中的自訂評分規則
我們想將供應項目散發在與佇列相關的背景工作角色之間。 背景工作角色會根據其標籤和技能集獲得分數。 具有最高分數的背景工作角色應取得第一個供應項目 (BestWorker 散發模式)。
情況
- 作業已建立並分類。
- 作業具有下列與其相關聯的標籤
- ["CommunicationType"] = "Chat"
- ["IssueType"] = "XboxSupport"
- ["Language"] = "en"
- ["HighPriority"] = true
- ["SubIssueType"] = "ConsoleMalfunction"
- ["ConsoleType"] = "XBOX_SERIES_X"
- ["Model"] = "XBOX_SERIES_X_1TB"
- 作業具有下列與其相關聯的 WorkerSelectors
- ["English"] >= 7
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- 作業具有下列與其相關聯的標籤
- 作業目前處於「已排入佇列」的狀態;在 Xbox 硬體支援佇列 中加入佇列,等待符合的背景工作角色。
- 多個背景工作角色同時可供使用。
- 背景工作角色 1 已建立,具有下列標籤
- ["HighPrioritySupport"] = true
- ["HardwareSupport"] = true
- ["Support_XBOX_SERIES_X"] = true
- ["English"] = 10
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- 背景工作角色 2 已建立,具有下列標籤
- ["HighPrioritySupport"] = true
- ["HardwareSupport"] = true
- ["Support_XBOX_SERIES_X"] = true
- ["Support_XBOX_SERIES_S"] = true
- ["English"] = 8
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- 背景工作角色 3 已建立,具有下列標籤
- ["HighPrioritySupport"] = false
- ["HardwareSupport"] = true
- ["Support_XBOX"] = true
- ["English"] = 7
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- 背景工作角色 1 已建立,具有下列標籤
期望
在我們希望在為背景工作角色評分時有下列行為,以選取哪些背景工作角色取得第一個供應項目。
決策流程 (如上述) 如下所示:
如果作業不是 HighPriority:
- 具有下列標籤的背景工作角色:["Support_XBOX"] = true;取得 100 的分數
- 否則,取得 1 的分數
如果作業為 HighPriority:
- 具有下列標籤的背景工作角色:["HighPrioritySupport"] = false;取得 1 的分數
- 否則,如果 [「HighPrioritySupport」] = true:
- 背景工作角色是否專用於主控台類型 - > 背景工作角色是否有標籤:["Support_<jobLabels.ConsoleType>"] = true? 如果為 true,則背景工作角色會取得 200 的分數
- 否則,取得 100 的分數
建立 Azure 函式
在進一步進行流程之前,讓我們先定義評分背景工作角色的 Azure 函式。
注意
下列 Azure 函式使用的是 JavaScript。 如需詳細資訊,請參閱快速入門:使用 Visual Studio Code 在 Azure 中建立 JavaScript 函式
背景工作角色 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
}
}
範例實作:
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
};
}
背景工作角色 1的輸出
200
透過上述實作,針對指定的作業,我們會取得下列背景工作角色分數:
工作人員 | 分數 |
---|---|
背景工作角色 1 | 200 |
背景工作角色 2 | 200 |
背景工作角色 3 | 1 |
根據最佳背景工作角色模式散發供應項目
現在 Azure 函數應用程式已就緒,讓我們使用路由器 SDK 建立 BestWorkerDistribution 模式的執行個體。
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());
輸出
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.