alibaba/Sentinel
Ver no GitHub[BUG] 热点参数集群限流,参数为非基本类型时,server 侧decode时data会是null,导致 NPE
Open
#1.906 aberto em 16 de dez. de 2020
area/cluster-flowgood first issuekind/bug
Métricas do repositório
- Stars
- (23.109 stars)
- Métricas de merge de PR
- (Nenhuma PRs mesclada em 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?
编码时跳过参数
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;
}
解码时
public class ParamFlowRequestDataDecoder implements EntityDecoder<ByteBuf, ParamFlowRequestData> {
@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<Object> params = new ArrayList<>(amount);
for (int i = 0; i < amount; i++) {
decodeParam(source, params);
}
requestData.setParams(params);
return requestData;
}
}
return null;
}
public class ParamFlowRequestProcessor implements RequestProcessor<ParamFlowRequestData, FlowTokenResponseData> {
@Override
public ClusterResponse<FlowTokenResponseData> processRequest(ClusterRequest<ParamFlowRequestData> request) {
TokenService tokenService = TokenServiceProvider.getService();
//data为null,报空指针,导致我的令牌请求失败
long flowId = request.getData().getFlowId();
int count = request.getData().getCount();
Collection<Object> args = request.getData().getParams();
TokenResult result = tokenService.requestParamToken(flowId, count, args);
return toResponse(result, request);
}