背景
后端团队技术栈为 Go 和 Java
Go 服务为微服务架构,使用 gRPC 和 gRPC-Gateway 对 APP 和 H5 提供服务
Java 服务目前没有统一后端协议栈, HTTP 和 gRPC 混用,没有统一的微服务框架
现状
- 营收/PUSH 中台使用 HTTP 协议,基于 Spring MVC
- 支付网关使用 HTTP 协议,基于 Spring Cloud
- UDB 使用 HTTP 协议和 gRPC 协议,基于 Spring MVC 和 gRPC-Java
存在以下问题:
- 开发速度慢, Java 接入 gRPC-Java 方式不友好,目前只用到了 gRPC 的简单模式,却需要写一些模版代码,过于繁琐
( responseObserver.onNext(respData); responseObserver.onCompleted(); )
,另外 gRPC 不支持 BeanCopy,对于服务分层隔离并不友好 - 缺少统一异常机制,微服务中的异常无法优雅的传递,目前不同服务间的异常都是通过错误码传递,每次调用都要捕获错误码,再次抛出,不能携带更多信息,语义不友好+繁琐
- 服务治理能力差
- 缺少负载均衡(目前即使有两个后端进程,也只会连接第一个)
- 缺少错误重试/超时机制(只能全局统一 10s 超时,对应一些高频访问接口故障会有坑)
目标
- 推动 Java 后端统一微服务栈,简化开发模式,加速开发效率
- 推动 Java 后端统一协议,支持 gRPC 和 HTTP,支撑目前的跨团队服务调用
技术需求
-
向 云原生 靠拢,简化运维模型
- 基于 Kubernetes 生态,但是避免深度依赖 Kubernetes API,避免依赖厂商特性
- 不额外维护注册中心
- 不额外维护配置中心
- 不额外维护微服务网关
-
兼容现有协议,支持 gRPC / HTTP, Java 和 Go 通讯,避免重构成本
- 支持 Protocol Buffers 对旧技术栈/跨团队服务进行兼容
- 也需要支持脱离 Protocol Buffers 进行内部调用的快速开发
- 解决方案足够完整,开发模式足够简单,避免繁琐的模版代码和基础架构封装
- 统一异常
- 参数校验
- 服务发现
- 负载均衡
- 服务降级
- 性能
- 快速开发
拆分原则
- 微服务本身具备功能完整性,功能性明确,不需要和其他服务联动
- 某一个微服务支持使用的不同的语言开发
- 微服务需要有自治性,能独立开发,独立测试,独立部署,独立上线,独立升级
候选方案
1. gRPC-Java 原生接入
目前 UDB 接入方案
优点: 可用
缺点: 繁琐
性能:
2. grpc-spring-boot-starter spring boot 集成接入
优点: 配置简单,原生 gRPC 协议
缺点: 还是 gRPC 写法
性能:
3. Dubbo
优点: 有服务治理,简洁
缺点: 架构复杂,可能有坑
特点: 兼容 gRPC,简化了 Java 写法
性能:
4. spring-cloud+gRPC-spring-boot-starter
// 需要和 K8s 深度绑定,配合 K8s 权限,暂不考虑
5. spring-cloud-kubernetes
// 需要和 K8s 深度绑定,配合 K8s 权限,暂不考虑
6. Dubbo 定制 jProtobuf
优点: 支持 Dubbo 现有功能,实现无 IDL 定义快速开发,服务兼容 gRPC 协议,第三方接入时无需重构
缺点: 对 pojo 定义有约束,可能有坑,可能翻车
特点: 使用简单,性能和原生 Dubbo 差不多
性能:
定制内容
采用 Dubbo 定制 jProtobuf 方案
- Dubbo Triple 协议,直接对 C 端提供 gRPC 接口
- 拓展 Triple 协议,集成 jProtobuf ,Java 体系内服务间调用基于 Java 接口方式定义,跨系统调用时基于 IDL
- 定制实现 Dubbo DNS 服务发现,使用 K8s Service 作为注册中心,省略额外的注册中心部署
- 定制 Dubbo 统一异常,服务间异常传递
- 定制 opentelemetry-java-instrumentation,制定上报 Trace
HTTPs://learnku.com/articles/60779