Optimize GrpcUtils to reduce memory and cpu cost (#8593)

This commit is contained in:
liqipeng 2022-06-23 11:12:09 +08:00 committed by GitHub
parent cbda95d014
commit bbbba1f453
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -17,8 +17,6 @@
package com.alibaba.nacos.common.remote.client.grpc; package com.alibaba.nacos.common.remote.client.grpc;
import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;
import com.alibaba.nacos.api.exception.runtime.NacosSerializationException;
import com.alibaba.nacos.api.grpc.auto.Metadata; import com.alibaba.nacos.api.grpc.auto.Metadata;
import com.alibaba.nacos.api.grpc.auto.Payload; import com.alibaba.nacos.api.grpc.auto.Payload;
import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.api.remote.request.Request;
@ -27,15 +25,13 @@ import com.alibaba.nacos.api.remote.response.Response;
import com.alibaba.nacos.api.utils.NetUtils; import com.alibaba.nacos.api.utils.NetUtils;
import com.alibaba.nacos.common.remote.PayloadRegistry; import com.alibaba.nacos.common.remote.PayloadRegistry;
import com.alibaba.nacos.common.remote.exception.RemoteException; import com.alibaba.nacos.common.remote.exception.RemoteException;
import com.fasterxml.jackson.annotation.JsonInclude; import com.alibaba.nacos.common.utils.JacksonUtils;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.protobuf.Any; import com.google.protobuf.Any;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.UnsafeByteOperations;
import java.io.IOException; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
/** /**
* gRPC utils, use to parse request and response. * gRPC utils, use to parse request and response.
@ -45,45 +41,6 @@ import java.nio.charset.StandardCharsets;
*/ */
public class GrpcUtils { public class GrpcUtils {
static ObjectMapper mapper = new ObjectMapper();
static {
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
/**
* Object to json string.
*
* @param obj obj
* @return json string
* @throws NacosSerializationException if transfer failed
*/
private static String toJson(Object obj) {
try {
return mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new NacosSerializationException(obj.getClass(), e);
}
}
/**
* Json string deserialize to Object.
*
* @param json json string
* @param cls class of object
* @param <T> General type
* @return object
* @throws NacosDeserializationException if deserialize failed
*/
public static <T> T toObj(String json, Class<T> cls) {
try {
return mapper.readValue(json, cls);
} catch (IOException e) {
throw new NacosDeserializationException(cls, e);
}
}
/** /**
* convert request to payload. * convert request to payload.
* *
@ -103,9 +60,9 @@ public class GrpcUtils {
// request body . // request body .
request.clearHeaders(); request.clearHeaders();
String jsonString = toJson(request); byte[] jsonBytes = JacksonUtils.toJsonBytes(request);
return payloadBuilder return payloadBuilder
.setBody(Any.newBuilder().setValue(ByteString.copyFrom(jsonString, StandardCharsets.UTF_8))) .setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
.build(); .build();
} }
@ -121,12 +78,12 @@ public class GrpcUtils {
Metadata newMeta = Metadata.newBuilder().setType(request.getClass().getSimpleName()) Metadata newMeta = Metadata.newBuilder().setType(request.getClass().getSimpleName())
.setClientIp(NetUtils.localIP()).putAllHeaders(request.getHeaders()).build(); .setClientIp(NetUtils.localIP()).putAllHeaders(request.getHeaders()).build();
request.clearHeaders(); request.clearHeaders();
String jsonString = toJson(request); byte[] jsonBytes = JacksonUtils.toJsonBytes(request);
Payload.Builder builder = Payload.newBuilder(); Payload.Builder builder = Payload.newBuilder();
return builder return builder
.setBody(Any.newBuilder().setValue(ByteString.copyFrom(jsonString, StandardCharsets.UTF_8))) .setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
.setMetadata(newMeta).build(); .setMetadata(newMeta).build();
} }
@ -138,11 +95,11 @@ public class GrpcUtils {
* @return payload. * @return payload.
*/ */
public static Payload convert(Response response) { public static Payload convert(Response response) {
String jsonString = toJson(response); byte[] jsonBytes = JacksonUtils.toJsonBytes(response);
Metadata.Builder metaBuilder = Metadata.newBuilder().setType(response.getClass().getSimpleName()); Metadata.Builder metaBuilder = Metadata.newBuilder().setType(response.getClass().getSimpleName());
return Payload.newBuilder() return Payload.newBuilder()
.setBody(Any.newBuilder().setValue(ByteString.copyFrom(jsonString, StandardCharsets.UTF_8))) .setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
.setMetadata(metaBuilder.build()).build(); .setMetadata(metaBuilder.build()).build();
} }
@ -155,7 +112,9 @@ public class GrpcUtils {
public static Object parse(Payload payload) { public static Object parse(Payload payload) {
Class classType = PayloadRegistry.getClassByType(payload.getMetadata().getType()); Class classType = PayloadRegistry.getClassByType(payload.getMetadata().getType());
if (classType != null) { if (classType != null) {
Object obj = toObj(payload.getBody().getValue().toString(StandardCharsets.UTF_8), classType); ByteString byteString = payload.getBody().getValue();
ByteBuffer byteBuffer = byteString.asReadOnlyByteBuffer();
Object obj = JacksonUtils.toObj(new ByteBufferBackedInputStream(byteBuffer), classType);
if (obj instanceof Request) { if (obj instanceof Request) {
((Request) obj).putAllHeader(payload.getMetadata().getHeadersMap()); ((Request) obj).putAllHeader(payload.getMetadata().getHeadersMap());
} }