Skip to content

Commit 8eb202c

Browse files
authored
Merge pull request #197369 from williamzhao87/williamzhao/router-distribution-mode-concepts
[JobRouter] Add distribution mode concepts page
2 parents 6c3a6f6 + dc2a60c commit 8eb202c

File tree

4 files changed

+245
-5
lines changed

4 files changed

+245
-5
lines changed

articles/communication-services/.openpublishing.redirection.communication-services.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@
3535
"redirect_url": "/azure/communication-services/quickstarts/ui-library/get-started-composites",
3636
"redirect_document_id": false
3737
},
38-
{
39-
"source_path_from_root": "/articles/communication-services/concepts/router/distribution-concepts.md",
40-
"redirect_url": "/azure/communication-services//concepts/router/matching-concepts",
41-
"redirect_document_id": false
42-
},
4338
{
4439
"source_path_from_root": "/articles/communication-services/concepts/router/azure-function-rule-engine.md",
4540
"redirect_url": "/azure/communication-services/how-tos/router-sdk/customize-worker-scoring",
35 KB
Loading

articles/communication-services/concepts/router/concepts.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ An exception policy controls the behavior of a Job based on a trigger and execut
130130
- [How jobs are matched to workers](matching-concepts.md)
131131
- [Router Rule concepts](router-rule-concepts.md)
132132
- [Classification concepts](classification-concepts.md)
133+
- [Distribution modes](distribution-concepts.md)
133134
- [Exception Policies](exception-policy.md)
134135
- [Quickstart guide](../../quickstarts/router/get-started-router.md)
135136
- [Manage queues](../../how-tos/router-sdk/manage-queue.md)
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
---
2+
title: Distribution mode concepts for Azure Communication Services
3+
titleSuffix: An Azure Communication Services concept document
4+
description: Learn about the Azure Communication Services Job Router distribution mode concepts.
5+
author: williamzhao
6+
manager: bgao
7+
services: azure-communication-services
8+
9+
ms.author: williamzhao
10+
ms.date: 05/06/2022
11+
ms.topic: conceptual
12+
ms.service: azure-communication-services
13+
---
14+
15+
# Distribution modes
16+
17+
[!INCLUDE [Private Preview Disclaimer](../../includes/private-preview-include-section.md)]
18+
19+
When creating a distribution policy, we specify one of the following distribution modes to define the strategy to use when distributing jobs to workers:
20+
21+
## Round robin mode
22+
Jobs will be distributed in a circular fashion such that each available worker will receive jobs in sequence.
23+
24+
## Longest idle mode
25+
Jobs will be distributed to the worker that is least utilized first. If there's a tie, we'll pick the worker that has been available for the longer time. Utilization is calculated as a `Load Ratio` by the following algorithm:
26+
27+
Load Ratio = Aggregate of capacity consumed by all jobs assigned to the worker / Total capacity of the worker
28+
29+
### Example
30+
Assume that each `chat` job has been configured to consume one capacity for a worker. A new chat job is queued into Job Router and the following workers are available to take the job:
31+
32+
```
33+
Worker A:
34+
TotalCapacity = 5
35+
ConsumedScore = 3 (Currently handling 3 chats)
36+
LoadRatio = 3 / 5 = 0.6
37+
LastAvailable: 5 mins ago
38+
39+
Worker B:
40+
TotalCapacity = 4
41+
ConsumedScore = 3 (Currently handling 3 chats)
42+
LoadRatio = 3 / 4 = 0.75
43+
LastAvailable: 3 min ago
44+
45+
Worker C:
46+
TotalCapacity = 5
47+
ConsumedScore = 3 (Currently handling 3 chats)
48+
LoadRatio = 3 / 5 = 0.6
49+
LastAvailable: 7 min ago
50+
51+
Worker D:
52+
TotalCapacity = 3
53+
ConsumedScore = 0 (Currently idle)
54+
LoadRatio = 0 / 4 = 0
55+
LastAvailable: 2 min ago
56+
57+
Workers would be matched in order: D, C, A, B
58+
```
59+
60+
Worker D has the lowest load ratio (0), so Worker D will be offered the job first. Workers A and C are tied with the same load ratio (0.6). However, Worker C has been available for a longer time (7 minutes ago) than Worker A (5 minutes ago), so Worker C will be matched before Worker A. Finally, Worker B will be matched last since Worker B has the highest load ratio (0.75).
61+
62+
## Best worker mode
63+
The workers that are best able to handle the job are picked first. The logic to rank Workers can be customized, with an expression or Azure function to compare two workers by specifying a Scoring Rule. [See example][worker-scoring]
64+
65+
When a Scoring Rule isn't provided, this distribution mode will use the default scoring method instead, which evaluates workers based on how the job's labels and selectors match with the worker's labels. The algorithms are outlined below.
66+
67+
### Default label matching
68+
For calculating a score based on the job's labels, we increment the `Match Score` by 1 for every worker label that matches a corresponding label on the job and then divide by the total number of labels on the job. Therefore, the more labels that matched, the higher a worker's `Match Score`. The final `Match Score` will always be a value between 0 and 1.
69+
70+
##### Example
71+
Job 1:
72+
```json
73+
{
74+
"labels": {
75+
{ "language": "english" },
76+
{ "department": "sales" }
77+
}
78+
}
79+
```
80+
81+
Worker A:
82+
```json
83+
{
84+
"labels": {
85+
{ "language": "english" },
86+
{ "department": "sales" }
87+
}
88+
}
89+
```
90+
91+
Worker B:
92+
```json
93+
{
94+
"labels": {
95+
{ "language": "english" }
96+
}
97+
}
98+
```
99+
100+
Worker C:
101+
```json
102+
{
103+
"labels": {
104+
{ "language": "english" },
105+
{ "department": "support" }
106+
}
107+
}
108+
```
109+
110+
Calculation:
111+
```
112+
Worker A's match score = 1 (for matching english language label) + 1 (for matching department sales label) / 2 (total number of labels) = 1
113+
Worker B's match score = 1 (for matching english language label) / 2 (total number of labels) = 0.5
114+
Worker C's match score = 1 (for matching english language label) / 2 (total number of labels) = 0.5
115+
```
116+
117+
Worker A would be matched first. Next, Worker B or Worker C would be matched, depending on who was available for a longer time, since the match score is tied.
118+
119+
### Default worker selector matching
120+
In the case where the job also contains worker selectors, we'll calculate the `Match Score` based on the `LabelOperator` of that worker selector.
121+
122+
#### Equal/notEqual label operators
123+
If the worker selector has the `LabelOperator` `Equal` or `NotEqual`, we increment the score by 1 for each job label that matches that worker selector, in a similar manner as the `Label Matching` above.
124+
125+
##### Example
126+
Job 2:
127+
```json
128+
{
129+
"workerSelectors": [
130+
{ "key": "department", "labelOperator": "equals", "value": "billing" },
131+
{ "key": "segment", "labelOperator": "notEquals", "department": "vip" }
132+
]
133+
}
134+
```
135+
136+
Worker D:
137+
```json
138+
{
139+
"labels": {
140+
{ "department": "billing" },
141+
{ "segment": "vip" }
142+
}
143+
}
144+
```
145+
146+
Worker E:
147+
```json
148+
{
149+
"labels": {
150+
{ "department": "billing" }
151+
}
152+
}
153+
```
154+
155+
Worker F:
156+
```json
157+
{
158+
"labels": {
159+
{ "department": "sales" },
160+
{ "segment": "new" }
161+
}
162+
}
163+
```
164+
165+
Calculation:
166+
```
167+
Worker D's match score = 1 (for matching department selector) / 2 (total number of worker selectors) = 0.5
168+
Worker E's match score = 1 (for matching department selector) + 1 (for matching segment not equal to vip) / 2 (total number of worker selectors) = 1
169+
Worker F's match score = 1 (for segment not equal to vip) / 2 (total number of labels) = 0.5
170+
```
171+
172+
Worker E would be matched first. Next, Worker D or Worker F would be matched, depending on who was available for a longer time, since the match score is tied.
173+
174+
#### Other label operators
175+
For worker selectors using operators that compare by magnitude (`GreaterThan`/`GreaterThanEqual`/`LessThan`/`LessThanEqual`), we'll increment the worker's `Match Score` by an amount calculated using the logistic function (See Fig 1). The calculation is based on how much the worker's label value exceeds the worker selector's value or a lesser amount if it doesn't exceed the worker selector's value. Therefore, the more worker selector values the worker exceeds, and the greater the degree to which it does so, the higher a worker's score will be.
176+
177+
:::image type="content" source="../media/router/distribution-concepts/logistic-function.png" alt-text="Diagram that shows logistic function.":::
178+
179+
Fig 1. Logistic function
180+
181+
The following function is used for GreaterThan or GreaterThanEqual operators:
182+
```
183+
MatchScore(x) = 1 / (1 + e^(-x)) where x = (labelValue - selectorValue) / selectorValue
184+
```
185+
186+
The following function is used for LessThan or LessThanEqual operators:
187+
188+
```
189+
MatchScore(x) = 1 / (1 + e^(-x)) where x = (selectorValue - labelValue) / selectorValue
190+
```
191+
192+
#### Example
193+
Job 3:
194+
```json
195+
{
196+
"workerSelectors": [
197+
{ "key": "language", "operator": "equals", "value": "french" },
198+
{ "key": "sales", "operator": "greaterThanEqual", "value": 10 },
199+
{ "key": "cost", "operator": "lessThanEqual", "value": 10 }
200+
]
201+
}
202+
```
203+
204+
Worker G:
205+
```json
206+
{
207+
"labels": {
208+
{ "language": "french" },
209+
{ "sales", 10 },
210+
{ "cost", 10 }
211+
}
212+
}
213+
```
214+
215+
Worker H:
216+
```json
217+
{
218+
"labels": {
219+
{ "language": "french" },
220+
{ "sales", 15 },
221+
{ "cost", 10 }
222+
}
223+
}
224+
```
225+
226+
Worker I:
227+
```json
228+
{
229+
"labels": {
230+
{ "language": "french" },
231+
{ "sales", 10 },
232+
{ "cost", 9 }
233+
}
234+
}
235+
```
236+
237+
Calculation:
238+
```
239+
Worker G's match score = (1 + 1 / (1 + e^-((10 - 10) / 10)) + 1 / (1 + e^-((10 - 10) / 10))) / 3 = 0.667
240+
Worker H's match score = (1 + 1 / (1 + e^-((15 - 10) / 10)) + 1 / (1 + e^-((10 - 10) / 10))) / 3 = 0.707
241+
Worker I's match score = (1 + 1 / (1 + e^-((10 - 10) / 10)) + 1 / (1 + e^-((10 - 9) / 10))) / 3 = 0.675
242+
```
243+
244+
All three workers match the worker selectors on the job and are eligible to work on it. However, we can see that Worker H exceeds the "sales" worker selector's value by a margin of 5. Meanwhile, Worker I only exceeds the cost worker selector's value by a margin of 1. Worker G doesn't exceed any of the worker selector's values at all. Therefore, Worker H would be matched first, followed by Worker I and finally Worker G would be matched last.

0 commit comments

Comments
 (0)