0
# Codec System
1
2
The codec system provides request and response encoding/decoding for efficient network serialization with extensible registries for custom data types and protocols.
3
4
## Capabilities
5
6
### Request Data Writer Registry
7
8
Registry system for managing request data encoders that serialize different types of cluster requests into ByteBuf format for network transmission.
9
10
```java { .api }
11
/**
12
* Registry for request data writers that encode requests for network transmission
13
*/
14
public final class RequestDataWriterRegistry {
15
/**
16
* Register a writer for a specific request type
17
* @param type request type constant (e.g., TYPE_PING, TYPE_FLOW)
18
* @param writer entity writer implementation for this type
19
* @return true if writer was registered, false if type already has a writer
20
*/
21
public static <T> boolean addWriter(int type, EntityWriter<T, ByteBuf> writer);
22
23
/**
24
* Get writer for a specific request type
25
* @param type request type constant
26
* @return writer for the type, or null if no writer registered
27
*/
28
public static EntityWriter<Object, ByteBuf> getWriter(int type);
29
30
/**
31
* Remove writer for a specific request type
32
* @param type request type constant to remove
33
* @return true if writer was removed, false if no writer existed
34
*/
35
public static boolean remove(int type);
36
}
37
```
38
39
**Usage Examples:**
40
41
```java
42
import com.alibaba.csp.sentinel.cluster.client.codec.registry.RequestDataWriterRegistry;
43
import com.alibaba.csp.sentinel.cluster.client.ClientConstants;
44
import com.alibaba.csp.sentinel.cluster.codec.EntityWriter;
45
import io.netty.buffer.ByteBuf;
46
47
// Register a custom writer for a new request type
48
EntityWriter<CustomRequestData, ByteBuf> customWriter = new CustomRequestDataWriter();
49
boolean registered = RequestDataWriterRegistry.addWriter(100, customWriter);
50
51
if (registered) {
52
System.out.println("Custom writer registered");
53
} else {
54
System.out.println("Writer for type 100 already exists");
55
}
56
57
// Get writer for existing type
58
EntityWriter<Object, ByteBuf> flowWriter = RequestDataWriterRegistry.getWriter(ClientConstants.TYPE_FLOW);
59
if (flowWriter != null) {
60
// Use writer to encode flow request data
61
}
62
63
// Remove custom writer
64
RequestDataWriterRegistry.remove(100);
65
```
66
67
### Response Data Decoder Registry
68
69
Registry system for managing response data decoders that deserialize network responses from ByteBuf format into Java objects.
70
71
```java { .api }
72
/**
73
* Registry for response data decoders that decode responses from network transmission
74
*/
75
public final class ResponseDataDecodeRegistry {
76
/**
77
* Register a decoder for a specific response type
78
* @param type response type constant (e.g., TYPE_PING, TYPE_FLOW)
79
* @param decoder entity decoder implementation for this type
80
* @return true if decoder was registered, false if type already has a decoder
81
*/
82
public static boolean addDecoder(int type, EntityDecoder<ByteBuf, ?> decoder);
83
84
/**
85
* Get decoder for a specific response type
86
* @param type response type constant
87
* @return decoder for the type, or null if no decoder registered
88
*/
89
public static EntityDecoder<ByteBuf, Object> getDecoder(int type);
90
91
/**
92
* Remove decoder for a specific response type
93
* @param type response type constant to remove
94
* @return true if decoder was removed, false if no decoder existed
95
*/
96
public static boolean removeDecoder(int type);
97
}
98
```
99
100
**Usage Examples:**
101
102
```java
103
import com.alibaba.csp.sentinel.cluster.client.codec.registry.ResponseDataDecodeRegistry;
104
import com.alibaba.csp.sentinel.cluster.codec.EntityDecoder;
105
import io.netty.buffer.ByteBuf;
106
107
// Register custom decoder
108
EntityDecoder<ByteBuf, CustomResponseData> customDecoder = new CustomResponseDataDecoder();
109
boolean registered = ResponseDataDecodeRegistry.addDecoder(200, customDecoder);
110
111
// Get decoder for ping responses
112
EntityDecoder<ByteBuf, Object> pingDecoder = ResponseDataDecodeRegistry.getDecoder(ClientConstants.TYPE_PING);
113
if (pingDecoder != null) {
114
// Use decoder to parse ping response
115
}
116
117
// Remove custom decoder
118
ResponseDataDecodeRegistry.removeDecoder(200);
119
```
120
121
### Built-in Request Writers
122
123
The system includes several built-in writers for standard request types that are automatically registered during initialization.
124
125
**Flow Request Writer:**
126
- **Type**: `ClientConstants.TYPE_FLOW`
127
- **Data**: `FlowRequestData` containing flow rule ID, token count, and priority
128
- **Usage**: Regular flow control token requests
129
130
**Parameterized Flow Request Writer:**
131
- **Type**: `ClientConstants.TYPE_PARAM_FLOW`
132
- **Data**: `ParamFlowRequestData` containing flow rule ID, token count, and parameters
133
- **Usage**: Parameter-specific flow control token requests
134
- **Configuration**: Supports max parameter byte size limits
135
136
**Ping Request Writer:**
137
- **Type**: `ClientConstants.TYPE_PING`
138
- **Data**: Ping data for server connectivity checks
139
- **Usage**: Health checks and connectivity monitoring
140
141
**Writer Usage Examples:**
142
143
```java
144
import com.alibaba.csp.sentinel.cluster.request.data.FlowRequestData;
145
import com.alibaba.csp.sentinel.cluster.request.data.ParamFlowRequestData;
146
import java.util.Arrays;
147
148
// Flow request data
149
FlowRequestData flowData = new FlowRequestData()
150
.setFlowId(12345L)
151
.setCount(1)
152
.setPriority(false);
153
154
// Parameterized flow request data
155
ParamFlowRequestData paramData = new ParamFlowRequestData()
156
.setFlowId(67890L)
157
.setCount(2)
158
.setParams(Arrays.asList("user123", "premium"));
159
160
// These data objects are automatically encoded by registered writers
161
```
162
163
### Built-in Response Decoders
164
165
The system includes built-in decoders for standard response types.
166
167
**Flow Response Decoder:**
168
- **Types**: `ClientConstants.TYPE_FLOW`, `ClientConstants.TYPE_PARAM_FLOW`
169
- **Data**: `FlowTokenResponseData` containing remaining count and wait time
170
- **Usage**: Decoding flow control token responses
171
172
**Ping Response Decoder:**
173
- **Type**: `ClientConstants.TYPE_PING`
174
- **Data**: Ping response data for connectivity confirmation
175
- **Usage**: Health check response processing
176
177
### Netty Pipeline Codecs
178
179
The codec system integrates with Netty pipeline handlers for seamless request/response processing.
180
181
```java { .api }
182
/**
183
* Netty encoder for outgoing cluster requests
184
*/
185
public class NettyRequestEncoder extends MessageToByteEncoder<ClusterRequest> {
186
// Automatically encodes ClusterRequest objects using registered writers
187
}
188
189
/**
190
* Netty decoder for incoming cluster responses
191
*/
192
public class NettyResponseDecoder extends ByteToMessageDecoder {
193
// Automatically decodes network data into ClusterResponse objects using registered decoders
194
}
195
```
196
197
**Pipeline Integration:**
198
199
```java
200
// The codec system is automatically integrated into the Netty pipeline:
201
// 1. LengthFieldBasedFrameDecoder - handles message framing
202
// 2. NettyResponseDecoder - decodes responses using registry
203
// 3. LengthFieldPrepender - adds length headers
204
// 4. NettyRequestEncoder - encodes requests using registry
205
// 5. TokenClientHandler - handles request/response correlation
206
```
207
208
### Entity Provider System
209
210
The codec system uses an entity provider pattern for accessing writers and decoders through SPI loading.
211
212
```java { .api }
213
/**
214
* Provider for entity codecs using SPI loading mechanism
215
*/
216
public final class ClientEntityCodecProvider {
217
/**
218
* Get the configured request entity writer
219
* @return request entity writer instance, or null if not configured
220
*/
221
public static RequestEntityWriter getRequestEntityWriter();
222
223
/**
224
* Get the configured response entity decoder
225
* @return response entity decoder instance, or null if not configured
226
*/
227
public static ResponseEntityDecoder getResponseEntityDecoder();
228
}
229
```
230
231
**Usage Examples:**
232
233
```java
234
import com.alibaba.csp.sentinel.cluster.client.codec.ClientEntityCodecProvider;
235
import com.alibaba.csp.sentinel.cluster.codec.request.RequestEntityWriter;
236
import com.alibaba.csp.sentinel.cluster.codec.response.ResponseEntityDecoder;
237
238
// Get configured codecs
239
RequestEntityWriter writer = ClientEntityCodecProvider.getRequestEntityWriter();
240
ResponseEntityDecoder decoder = ClientEntityCodecProvider.getResponseEntityDecoder();
241
242
if (writer != null) {
243
System.out.println("Request writer available: " + writer.getClass().getName());
244
} else {
245
System.out.println("No request writer configured via SPI");
246
}
247
```
248
249
### Custom Codec Implementation
250
251
You can implement custom codecs for new request/response types.
252
253
**Custom Request Writer:**
254
255
```java
256
import com.alibaba.csp.sentinel.cluster.codec.EntityWriter;
257
import io.netty.buffer.ByteBuf;
258
259
public class CustomRequestDataWriter implements EntityWriter<CustomRequestData, ByteBuf> {
260
@Override
261
public void writeTo(ByteBuf target, CustomRequestData source) throws Exception {
262
// Write custom data fields to ByteBuf
263
target.writeInt(source.getId());
264
target.writeLong(source.getTimestamp());
265
266
byte[] nameBytes = source.getName().getBytes("UTF-8");
267
target.writeInt(nameBytes.length);
268
target.writeBytes(nameBytes);
269
}
270
}
271
272
// Register the custom writer
273
RequestDataWriterRegistry.addWriter(CUSTOM_TYPE, new CustomRequestDataWriter());
274
```
275
276
**Custom Response Decoder:**
277
278
```java
279
import com.alibaba.csp.sentinel.cluster.codec.EntityDecoder;
280
import io.netty.buffer.ByteBuf;
281
282
public class CustomResponseDataDecoder implements EntityDecoder<ByteBuf, CustomResponseData> {
283
@Override
284
public CustomResponseData decode(ByteBuf source) throws Exception {
285
// Read custom data fields from ByteBuf
286
int id = source.readInt();
287
long timestamp = source.readLong();
288
289
int nameLength = source.readInt();
290
byte[] nameBytes = new byte[nameLength];
291
source.readBytes(nameBytes);
292
String name = new String(nameBytes, "UTF-8");
293
294
return new CustomResponseData(id, timestamp, name);
295
}
296
}
297
298
// Register the custom decoder
299
ResponseDataDecodeRegistry.addDecoder(CUSTOM_TYPE, new CustomResponseDataDecoder());
300
```
301
302
### Initialization and Setup
303
304
The codec system is automatically initialized through the `DefaultClusterClientInitFunc` class during Sentinel startup.
305
306
```java { .api }
307
/**
308
* Initialization function for default cluster client components
309
* Automatically registers default codecs for built-in request/response types
310
*/
311
@InitOrder(0)
312
public class DefaultClusterClientInitFunc implements InitFunc {
313
/**
314
* Initialize default entity writers and decoders
315
* @throws Exception if initialization fails
316
*/
317
public void init() throws Exception;
318
}
319
```
320
321
**Automatic Registration Process:**
322
323
```java
324
// The initialization process automatically registers:
325
326
// Request writers
327
RequestDataWriterRegistry.addWriter(ClientConstants.TYPE_PING, new PingRequestDataWriter());
328
RequestDataWriterRegistry.addWriter(ClientConstants.TYPE_FLOW, new FlowRequestDataWriter());
329
330
// Parameterized flow writer with optional size limit
331
Integer maxParamByteSize = ClusterClientStartUpConfig.getMaxParamByteSize();
332
if (maxParamByteSize == null) {
333
RequestDataWriterRegistry.addWriter(ClientConstants.TYPE_PARAM_FLOW, new ParamFlowRequestDataWriter());
334
} else {
335
RequestDataWriterRegistry.addWriter(ClientConstants.TYPE_PARAM_FLOW, new ParamFlowRequestDataWriter(maxParamByteSize));
336
}
337
338
// Response decoders
339
ResponseDataDecodeRegistry.addDecoder(ClientConstants.TYPE_PING, new PingResponseDataDecoder());
340
ResponseDataDecodeRegistry.addDecoder(ClientConstants.TYPE_FLOW, new FlowResponseDataDecoder());
341
ResponseDataDecodeRegistry.addDecoder(ClientConstants.TYPE_PARAM_FLOW, new FlowResponseDataDecoder());
342
```
343
344
### Configuration Parameters
345
346
The codec system supports configuration parameters for customization.
347
348
**Parameter Serialization Limits:**
349
350
```java
351
import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientStartUpConfig;
352
353
// Configure maximum parameter byte size
354
Integer maxParamBytes = ClusterClientStartUpConfig.getMaxParamByteSize();
355
if (maxParamBytes != null) {
356
// Use custom limit for parameter serialization
357
ParamFlowRequestDataWriter writer = new ParamFlowRequestDataWriter(maxParamBytes);
358
RequestDataWriterRegistry.addWriter(ClientConstants.TYPE_PARAM_FLOW, writer);
359
}
360
361
// System property: -Dcsp.sentinel.cluster.max.param.byte.size=2048
362
```
363
364
### Thread Safety
365
366
All registry operations are thread-safe and can be called from multiple threads simultaneously. However, it's recommended to register custom codecs during application initialization before starting the cluster client.
367
368
### Performance Considerations
369
370
**Codec Efficiency:**
371
- Use efficient serialization formats for custom codecs
372
- Avoid unnecessary object allocation during encoding/decoding
373
- Consider using object pooling for frequently used data structures
374
375
**Registry Lookup:**
376
- Registry lookups are O(1) HashMap operations
377
- Cache codec instances when possible
378
- Register codecs once during initialization rather than repeatedly