传统编码方式转 gRPC 注意事项
# 赋值编码:
1.pbBuilder 设置值时不能为 null
2.pb 定义的类是不可变类,赋值时需要使用 Builder 模式,且每次 builder 都会 new 一个新对象,所以赋值时需要特别留意
3.pbData.setList(),原有 list 属性不会被覆盖,需要手动清除 pbData.clean()
4.entity A 与 pb 类互相拷贝属性时,如果 A 中包含类 B 是不会拷贝的,需要手动处理
5.Controller 接口参数使用 pbBuilder 类模式才能接收到值
# 业务影响:
1.pb 属性都会有默认值,所以业务字段上0,空字符串这些判断处理时需要特别处理
# 框架整合
1.整合 skywalking 时,因为异步调用原因,客户端不能透传 traceId 到服务端,导致服务端日志文件不能输出 traceId,目前采用 grpc 客户端、服务端拦截 + MDC 方式处理
@Component
public class GrpcClientLogInterceptor implements ClientInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(GrpcClientLogInterceptor.class); @Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
String traceId = MDC.get(LogConstants.MDC_GRPC_TRACE_KEY); if (StringUtils.isBlank(traceId)) {
traceId = UuidUtils.randomUUIDStr32();
LOGGER.debug("调用方法前未获取 traceId,生成新的 traceId:[{}],methodName:[{}]", traceId, method.getFullMethodName());
}
headers.put(LogConstants.REQUEST_KEY, traceId); super.start(responseListener, headers);
}
};
}
} @Component
public class GrpcServerLogInterceptor implements ServerInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(GrpcServerLogInterceptor.class); @Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata,
ServerCallHandler<ReqT, RespT> serverCallHandler) {
final long startTime = System.currentTimeMillis();
String fullMethodName = serverCall.getMethodDescriptor().getFullMethodName(); String traceId = metadata.get(LogConstants.REQUEST_KEY);
if (StringUtils.isBlank(traceId)) { traceId = UuidUtils.randomUUIDStr32();
LOGGER.debug("调用方法前未获取 traceId,生成新的 traceId: [{}],methodName:[{}]", traceId, fullMethodName);
} MDC.put(LogConstants.MDC_GRPC_TRACE_KEY, traceId); LOGGER.debug("server recive traceId: {}", traceId);
LOGGER.debug("Before request [method={}]", fullMethodName);
LOGGER.debug("GRPC Metadata: {}", metadata); ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT> serverCall1 =
new ForwardingServerCall.SimpleForwardingServerCall(serverCall) {
@Override
public void sendMessage(Object message) {
super.sendMessage(message);
}
}; ServerCall.Listener<ReqT> listener = serverCallHandler.startCall(serverCall1, metadata); final String finalTraceId = traceId;
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(listener) {
@Override
public void onMessage(ReqT message) {
LOGGER.debug("GRPC Request: {}", message);
super.onMessage(message);
} @Override
public void onComplete() {
LOGGER.debug("After request [method={}],grpc request elapsed time:{}ms.", fullMethodName, (System.currentTimeMillis() - startTime));
super.onComplete(); MDC.remove(LogConstants.MDC_GRPC_TRACE_KEY);
LOGGER.debug("After request [method={}], 删除 MDC 中 traceId [{}].", fullMethodName, finalTraceId);
}
};
}
} public class LogConstants { // grpc head key
public static final String GRPC_REQUEST_ID = "request-id-bin";
public static final String UTF_8 = "UTF-8";
public static final String MDC_GRPC_TRACE_KEY = "GTID"; /**
* 公共 key,透传 traceid 时的 key
*/
public static final Metadata.Key<String> REQUEST_KEY = Metadata.Key.of(GRPC_REQUEST_ID,
new Metadata.BinaryMarshaller<String>() {
@Override
public byte[] toBytes(String value) {
try {
return value.getBytes(UTF_8);
} catch (UnsupportedEncodingException e) {
return null;
}
} @Override
public String parseBytes(byte[] serialized) {
try {
return new String(serialized, UTF_8);
} catch (UnsupportedEncodingException e) {
return null;
}
}
});
}
2.Quartz 框架整合 skywalking,不能输出 traceId,处理方案同上面
3.Qrartz 框架的 Job 类因为是采用 AdaptableJobFactory.createJobInstance 方式生成示例,导致不能直接注入 grpc 服务类。
解决方案:业务处理放入到 Spring bean 业务类中,再依赖注入到 Job 实例
传统编码方式转 gRPC 注意事项的更多相关文章
- Oracle EBS在编码方式为AL32UTF8时的注意事项
现如今的EBS系统中,为了推进国际化的进程,以及系统向全球化的扩展,在Oracle数据库的编码方式上渐渐从支持中国本土简体中文的ZHS16GBK转向了更趋于国际化的AL32UTF8编码方式.但随之而来 ...
- Redis与KV存储(RocksDB)融合之编码方式
Redis与KV存储(RocksDB)融合之编码方式 简介 Redis 是目前 NoSQL 领域的当红炸子鸡,它象一把瑞士军刀,小巧.锋利.实用,特别适合解决一些使用传统关系数据库难以解决的问题.Re ...
- 【python】python编码方式,chardet编码识别库
环境: python3.6 需求: 针对于打开一个文件,可以读取到文本的编码方式,根据默认的文件编码方式来获取文件,就不会出现乱码. 针对这种需求,python中有这个方式可以很好的解决: 解决策略: ...
- MIME协议(五) -- MIME邮件的编码方式
5 MIME邮件的编码方式 由于每个ASCII码字符只占用一个字节(8个bit位),且最高bit位总为0,即ASCII码字符中的有真正意义的信息只是后面的7个低bit位,而传统的SMTP协议又是基于 ...
- VUE 开发报表,非编码方式
官网:http://doc.sougn.com 下载地址:https://pan.baidu.com/share/init?surl=P0O9sjfzC8nuQxirDfjW1A 密码:4oev 先 ...
- Java不同编码方式,中英文字符所占字节数
测试代码 public class Test { public static void main(String[] args){ String[] charsetNames={ "UTF-8 ...
- form表单编码方式设置为multipart/form-data,后台参数出现乱码情况
一般在上传图片过程中,form中的编码方式一般采用multipart/form-data方式编码,但是后台这取参数时,可能会出现乱码情况:这里后台要采用转换编码方式: 页面: 后台:获取表单元素时,
- servlet获取表单数据的方式和编码方式
.在servlet中获取表单的数据的几种方式 1>request.getParameter(“name”)://获取指定名称的值,返回值类型是一个字符串 2>request.getPa ...
- python 改变字符串的编码方式
字符串str的编码方式为utf-8,转化为gbk,分为两步 1. str=str.decode('utf-8') 2. str=str.encode('gbk')
- [No000040]取得一个文本文件的编码方式
using System; using System.IO; using System.Text; /// <summary> /// 用于取得一个文本文件的编码方式(Encoding). ...
随机推荐
- drf-day5——反序列化类校验部分源码分析、断言、drf请求、drf响应、视图组件及两个视图基类、基于GenericAPIView+5个视图扩展类
目录 一.反序列化类校验部分源码解析(了解) 二.断言 三.drf之请求 3.1 Request能够解析的前端传入的编码格式 3.2 Request类有哪些属性和方法(学过) 常用参数 Respons ...
- 多线程之Semaphore登录限流示例
public static void main(String[] args) { //允许最大的登录数 int slots=10; ExecutorService executorService = ...
- FreeBSD 安装 fcitx5的配置
link: Chinese Pinyin Package for typing Chinese sudo pkg install -y zh-CJKUnifonts sudo pkg install ...
- .NET WebAPI 跨域问题(has been blocked by CORS policy:No Access-Control-Allow-Ogigin header is present on the requested resource)
一.什么是跨域 1. 跨域解释 跨域指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器施加的安全限制. 同源指的是:域名,协议,端口均相同. 2. 什么情况下会导致跨域 2.1 ...
- 使用brew安装历史版本的几种方式
背景 在 mac osx 下, 大部分的软件都是使用 homebrew 进行管理的, 可以方便的进行软件的安装,更新,删除等等, 大部分情况下 homebrew 的仓库只会存在一份最新的软件版本, 有 ...
- JZOJ 【2021.11.10NOIP提高组联考】
简要题解 这套题比较 \(H_2O\) 建议题目背景美文共赏 \(\text{T1}\) 显然一个 \(O(n^3)\) 不能过的 \(dp\) 然而过了?! 用心在该卡时间的地方卡一卡 \(\tex ...
- Can not use keyword ‘await’ outside an async function
- vue中引入静态图片
vue+webpack中,可以使用require imageList: [ { url: require('../image/pig.png') } ] vue+vite没有require方法 // ...
- day12_内部类&API
1.参数传递 1.1 类名作为形参和返回值 类名--方法形参 方法的形参是类名,需要的是该类的对象:实际传递的是该对象的地址值 类名--返回值 方法的返回值是类名,返回的是该类的对象: ...
- 4. Lighting 窗口
Lighting 实现烘焙或者实时渲染都在这里设置,其他灯光或者反射探头的作用相当于允许 Lighting (窗口)烘焙或者实时渲染. 0bject: Lightmap Static: 把烘焙的对象设 ...