传统编码方式转 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). ...
随机推荐
- Node.js学习笔记----day03
认真学习,认真记录,每天都要有进步呀!!! 加油叭!!! 一.Node中的模块系统 使用Node编写应用程序主要就是在使用 EcmaScript 和浏览器不一样的是,在Node中没有BOM.DOM 核 ...
- 【HMS Core】使用机器学习服务和搜索服务识别植物
1.介绍 总览 机器学习服务(ML Kit)为开发者提供简单易用.服务多样.技术领先的机器学习能力,助力开发者更快更好地开发各类AI应用.同时,搜索服务(Search Kit)通过端侧SDK和云侧A ...
- python学习第三周总结
文件操作 文件的读写模式 文件的操作模式 文件相关操作 文件内光标移动 文件内容修改 函数前戏 函数的语法结构 函数的定义和调用 函数的分类 函数的返回值 函数的参数 函数参数之位置参数 默认参数 可 ...
- STM32F4寄存器初始化系列:时钟开启
1 static void RCC_Init(void) 2 { 3 RCC->APB1ENR|=1<<17; //使能串口2时钟 4 RCC->APB1ENR|=1<& ...
- 【Go语言基础】slice
一.概述 数组(Array)的长度在定义之后无法再次修改:数组是值类型,每次传递都将产生一份副本. 显然这种数据结构无法完全满足开发者的真实需求.Go语言提供了数组切片(slice)来弥补数组的不足. ...
- Solon2 之基础:一、常用应用配置说明
约定参考: //资源路径约定(不用配置:也不能配置) resources/app.yml( 或 app.properties ) #为应用配置文件 resources/WEB-INF/static/ ...
- CPU AMX 详解
CPU AMX 详解 CPU AMX 详解 概述 算力如何 问题定义 AVX如何解决矩阵乘问题 AMX如何解决矩阵乘问题 如何实现的 计算部分 数据部分 路才开始 概述 2016 年开始,随着 NV ...
- 如何获取win10用户最高权限
第五步,在(输入对象名称)方框中输入"System Managed Accounts Group",再点击"检查名称" 转载: 百度经验: https: ...
- HACKNOS: RECONFORCE (V1.1)
HACKNOS: RECONFORCE (V1.1) 目录 HACKNOS: RECONFORCE (V1.1) 1 信息收集 1.1 端口扫描 1.2 ftp分析 1.3 后台目录扫描 1.2.1 ...
- Postgresql临时表(TEMPORARY TABLE)
一.简介 PostgreSQL中的临时表分两种,一种是会话级临时表,一种是事务级临时表.在会话级临时表中,数据可以存在于整个会话的生命周期中,在事务级临时表中的数据只能存在于事务的生命周期中.默认创建 ...