0
# Session Distribution
1
2
The session distribution system manages WebDriver session creation and routing across available grid nodes, providing load balancing, capacity management, and slot selection strategies.
3
4
## Capabilities
5
6
### Core Distributor Interface
7
8
The main distributor interface handles session creation requests and node management.
9
10
```java { .api }
11
/**
12
* Abstract base class for session distributors
13
*/
14
abstract class Distributor {
15
/** Protected constructor with required dependencies */
16
protected Distributor(Tracer tracer, HttpClient.Factory httpClientFactory, Secret registrationSecret);
17
18
/** Create a new WebDriver session */
19
abstract Either<SessionNotCreatedException, CreateSessionResponse> newSession(SessionRequest request);
20
21
/** Add a node to the grid */
22
abstract Distributor add(Node node);
23
24
/** Drain sessions from a node (stop accepting new sessions) */
25
abstract boolean drain(NodeId nodeId);
26
27
/** Remove a node from the grid */
28
abstract void remove(NodeId nodeId);
29
30
/** Get current distributor status and statistics */
31
abstract DistributorStatus getStatus();
32
}
33
```
34
35
### Local Distributor Implementation
36
37
Default in-process distributor implementation with full session management.
38
39
```java { .api }
40
/**
41
* Local distributor implementation for single-process or hub deployments
42
*/
43
@ManagedService
44
class LocalDistributor extends Distributor {
45
/** Factory method to create distributor from configuration */
46
static Distributor create(Config config);
47
48
// Implement all abstract methods from Distributor
49
Either<SessionNotCreatedException, CreateSessionResponse> newSession(SessionRequest request);
50
Distributor add(Node node);
51
boolean drain(NodeId nodeId);
52
void remove(NodeId nodeId);
53
DistributorStatus getStatus();
54
55
// JMX management attributes
56
@ManagedAttribute
57
int getNodeCount();
58
59
@ManagedAttribute
60
int getSessionCount();
61
62
@ManagedAttribute
63
long getSessionsCreated();
64
65
@ManagedAttribute
66
Map<String, Object> getSlotStereotypes();
67
}
68
```
69
70
**Usage Example:**
71
72
```java
73
Config config = new MemoizedConfig(new MapConfig(Map.of(
74
"distributor", Map.of(
75
"reject-unsupported-caps", true,
76
"healthcheck-interval", "120s"
77
)
78
)));
79
80
Distributor distributor = LocalDistributor.create(config);
81
82
// Add nodes to the distributor
83
Node chromeNode = createChromeNode();
84
Node firefoxNode = createFirefoxNode();
85
86
Distributor updatedDistributor = distributor
87
.add(chromeNode)
88
.add(firefoxNode);
89
90
// Create a new session
91
SessionRequest request = new SessionRequest(
92
new RequestId(UUID.randomUUID()),
93
Instant.now().plus(Duration.ofMinutes(5)), // timeout
94
Set.of(W3C), // dialects
95
new ImmutableCapabilities("browserName", "chrome")
96
);
97
98
Either<SessionNotCreatedException, CreateSessionResponse> result =
99
updatedDistributor.newSession(request);
100
101
if (result.isRight()) {
102
CreateSessionResponse response = result.right();
103
System.out.println("Session created: " + response.getSession().getId());
104
} else {
105
SessionNotCreatedException error = result.left();
106
System.err.println("Session creation failed: " + error.getMessage());
107
}
108
```
109
110
### Slot Selection Strategy
111
112
Functional interface for customizing how slots are selected for session creation.
113
114
```java { .api }
115
/**
116
* Strategy interface for selecting appropriate slots for session requests
117
*/
118
@FunctionalInterface
119
interface SlotSelector {
120
/**
121
* Select slots that can handle the requested capabilities
122
* @param capabilities The desired session capabilities
123
* @param nodes Available nodes with their current status
124
* @param slotMatcher Function to test capability matching
125
* @return Set of slot IDs that can fulfill the request
126
*/
127
Set<SlotId> selectSlot(Capabilities capabilities, Set<NodeStatus> nodes, SlotMatcher slotMatcher);
128
}
129
130
/**
131
* Default slot selection implementation using round-robin with load balancing
132
*/
133
class DefaultSlotSelector implements SlotSelector {
134
Set<SlotId> selectSlot(Capabilities capabilities, Set<NodeStatus> nodes, SlotMatcher slotMatcher);
135
}
136
```
137
138
**Custom Slot Selector Example:**
139
140
```java
141
// Custom selector that prefers nodes with lower load
142
SlotSelector loadBasedSelector = (capabilities, nodes, slotMatcher) -> {
143
return nodes.stream()
144
.filter(node -> node.hasCapacity(capabilities, slotMatcher))
145
.sorted(Comparator.comparing(NodeStatus::getLoad))
146
.flatMap(node -> node.getSlots().stream())
147
.filter(slot -> slot.isSupporting(capabilities, slotMatcher))
148
.map(Slot::getId)
149
.limit(1)
150
.collect(Collectors.toSet());
151
};
152
```
153
154
### Remote Distributor Client
155
156
Client for accessing distributors running in remote processes.
157
158
```java { .api }
159
/**
160
* Remote distributor client for distributed grid deployments
161
*/
162
class RemoteDistributor extends Distributor {
163
RemoteDistributor(Tracer tracer, HttpClient.Factory httpClientFactory,
164
URI distributorUri, Secret registrationSecret);
165
166
// Implement all abstract methods via HTTP calls
167
Either<SessionNotCreatedException, CreateSessionResponse> newSession(SessionRequest request);
168
Distributor add(Node node);
169
boolean drain(NodeId nodeId);
170
void remove(NodeId nodeId);
171
DistributorStatus getStatus();
172
}
173
```
174
175
### Configuration Options
176
177
Configuration settings specific to the distributor component.
178
179
```java { .api }
180
/**
181
* Configuration options for distributor behavior
182
*/
183
class DistributorOptions {
184
static final String DISTRIBUTOR_SECTION = "distributor";
185
186
/** Get implementation class for the distributor */
187
String getDistributorImplementation(Config config);
188
189
/** Get health check interval for nodes */
190
Duration getHealthCheckInterval(Config config);
191
192
/** Whether to reject requests with unsupported capabilities */
193
boolean shouldRejectUnsupportedCaps(Config config);
194
195
/** Get slot matcher implementation */
196
SlotMatcher getSlotMatcher(Config config);
197
198
/** Get slot selector implementation */
199
SlotSelector getSlotSelector(Config config);
200
}
201
202
/**
203
* Command-line flags for distributor configuration
204
*/
205
class DistributorFlags {
206
@Parameter(names = {"--reject-unsupported-caps"},
207
description = "Reject session requests with unsupported capabilities")
208
Boolean rejectUnsupportedCaps;
209
210
@Parameter(names = {"--healthcheck-interval"},
211
description = "How often to check node health")
212
int healthCheckInterval = 120;
213
214
@Parameter(names = {"--slot-matcher"},
215
description = "Full class name of SlotMatcher implementation")
216
String slotMatcher = "org.openqa.selenium.grid.data.DefaultSlotMatcher";
217
218
@Parameter(names = {"--slot-selector"},
219
description = "Full class name of SlotSelector implementation")
220
String slotSelector = "org.openqa.selenium.grid.distributor.selector.DefaultSlotSelector";
221
}
222
```
223
224
## Request/Response Models
225
226
```java { .api }
227
/**
228
* Request to create a new WebDriver session
229
*/
230
class SessionRequest {
231
SessionRequest(RequestId requestId, Instant enqueued, Set<Dialect> downstreamDialects, Capabilities desiredCapabilities);
232
RequestId getRequestId();
233
Instant getEnqueued();
234
Set<Dialect> getDownstreamDialects();
235
Capabilities getDesiredCapabilities();
236
}
237
238
/**
239
* Response containing created session information
240
*/
241
class CreateSessionResponse {
242
CreateSessionResponse(Session session, byte[] downstreamEncodedResponse);
243
Session getSession();
244
byte[] getDownstreamEncodedResponse();
245
}
246
247
/**
248
* Current status of the distributor
249
*/
250
class DistributorStatus {
251
DistributorStatus(Set<NodeStatus> nodes);
252
Set<NodeStatus> getNodes();
253
boolean hasCapacity();
254
boolean hasCapacity(Capabilities capabilities);
255
}
256
```
257
258
## Error Handling
259
260
```java
261
// Session creation can fail for several reasons
262
Either<SessionNotCreatedException, CreateSessionResponse> result = distributor.newSession(request);
263
264
if (result.isLeft()) {
265
SessionNotCreatedException error = result.left();
266
267
// Common reasons for failure:
268
// - No nodes available with matching capabilities
269
// - All matching nodes at capacity
270
// - Request timeout exceeded
271
// - Node health check failure
272
273
System.err.println("Session creation failed: " + error.getMessage());
274
}
275
```