[BUG] 热点参数集群限流,参数为非基本类型时,server 侧decode时data会是null,导致 NPE
- Dominant language
- Java
- Stars
- 23.1k
- Forks
- 8.1k
- PR merge metrics
- No merged PRs in 30d
Description
## Issue Description
热点参数集群限流,如果参数是一个对象,因为netty在encode时会过滤掉,在tokenserver那解码时data会是null,导致空指针
### Describe what happened (or what feature you want)
我在使用@sentinelresource注解时,使用了对象为参数,测试热点集群限流,希望可以总体阈值生效,但是metric日志总是不生效
### Describe what you expected to happen
### How to reproduce it (as minimally and precisely as possible)

### Tell us your environment
jdk1.8
sentinel1.8
### Anything else we need to know?
编码时跳过参数
```java
int calculateParamTransportSize(Object value) {
if (value == null) {
return 0;
}
// Layout for primitives: |type flag(1)|value|
// size = original size + type flag (1)
if (value instanceof Integer || int.class.isInstance(value)) {
return 5;
} else if (value instanceof String) {
// Layout for string: |type flag(1)|length(4)|string content|
String tmpValue = (String) value;
byte[] tmpChars = tmpValue.getBytes();
return 1 + 4 + tmpChars.length;
} else if (boolean.class.isInstance(value) || value instanceof Boolean) {
return 2;
} else if (long.class.isInstance(value) || value instanceof Long) {
return 9;
} else if (double.class.isInstance(value) || value instanceof Double) {
return 9;
} else if (float.class.isInstance(value) || value instanceof Float) {
return 5;
} else if (byte.class.isInstance(value) || value instanceof Byte) {
return 2;
} else if (short.class.isInstance(value) || value instanceof Short) {
return 3;
} else {
// Ignore unexpected type.
return 0;
}
```
解码时
```java
public class ParamFlowRequestDataDecoder implements EntityDecoder {
@Override
public ParamFlowRequestData decode(ByteBuf source) {
if (source.readableBytes() >= 16) {
ParamFlowRequestData requestData = new ParamFlowRequestData()
.setFlowId(source.readLong())
.setCount(source.readInt());
int amount = source.readInt();
//因为amount为0,所以跳出判断,返回一个null
if (amount > 0) {
List params = new ArrayList<>(amount);
for (int i = 0; i < amount; i++) {
decodeParam(source, params);
}
requestData.setParams(params);
return requestData;
}
}
return null;
}
```
```java
public class ParamFlowRequestProcessor implements RequestProcessor {
@Override
public ClusterResponse processRequest(ClusterRequest request) {
TokenService tokenService = TokenServiceProvider.getService();
//data为null,报空指针,导致我的令牌请求失败
long flowId = request.getData().getFlowId();
int count = request.getData().getCount();
Collection args = request.getData().getParams();
TokenResult result = tokenService.requestParamToken(flowId, count, args);
return toResponse(result, request);
}
```
Contributor guide
Research direction
Start with ParamFlowRequestDataDecoder.decode and ParamFlowRequestProcessor.processRequest, then trace how calculateParamTransportSize handles non-primitive parameters. Verify that a request containing an object parameter is decoded into usable request data and reaches tokenService.requestParamToken without a null-data failure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, distributed-systems
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100