开始前必读:基于grpc从零开始搭建一个准生产分布式应用(0) - quickStart
本来笔者并不想开设这个系列,因为工作量比较大,另外此专题的技术点也偏简单。最近复盘了下最近的工作,发现一个问题就是各个互联网大厂一般都会有专门的部门开发专用的框架,所有发布出来的文章也是基于这些内部框架来写的,可能导致未进过大厂的同学很难更深入的理解也没法实际应用起来。
另外很容易形成一个误区,就是开源的框架不经过二次封装是否可直接用到生产环境。这里笔者想说如果换成8、9年前答案是不可以,但现在随着三方框架的完善完全可以不经过二开直接应用到生产环境中。笔者最近就在实际工作中采用了全开源的框架构建了一个生产系统,运行过程中也还算OK,所以整理一下过程写成这个专题。笔者以一个DEMO为主线,然后围绕实现过程展开各分层技术的必要知识点。
之所以系列标题叫“准生产应用”原因是,一个生产环境除了应用代码外还包含比如集群和监控等内容,不过也没多大问题因为集群和监控一般都可以后期配置并不影响应用代码。此系列主要还是面向后端开发同学。
一、准备工作
笔者的开发环境如下,建议读者也最好在开发前提前准备好,也可以按此专题的顺序来安装,在进入下一小节时建设读者必须安装好以下标为红色的软件。
- 开发环境:Macos 11.6.5、Intellij IDEA 2022.1.2、JDK 1.8.0_144、Maven 3、Git、
- 测试环境:Ubuntu
- 部署方式:Docker
- 中间件:MySQL8.0.23、Redis6.2.6、RocketMq
二、DEMO介绍
在一些应用中一般都会把重要的操作记录在数据表以供后续审记,比如付款记录或是登陆记录等。这里笔者选了一个通用的日志记录功能的demo,后续会逐步实现这个需求。PS:这里虽然说是demo,但是实现后的代码是可以直接应用到生产环境中的。只是由于一些涉密的原因,没法把一些复杂的真实需求摆到网上。
此需求比较简单:提供一个通用的操作日志记录和列表查询功能,并担任GRPC和HTTP两种API接口。分解后需求如下:
需求名称 | 接口类型 | 功能描述 |
增加操作记录 | HTTP、GRPC | 添加一条操作记录 |
列表查询操作记录 | HTTP、GRPC | 根据操作用户、业务类型等条件查询操作记录集合 |
数据库表结构:
CREATE TABLE `t_sys_record` (
`id` bigint(20) NOT NULL,
`biz_id` bigint(20) NULL DEFAULT NULL COMMENT '业务ID',
`user_id` bigint(20) NULL DEFAULT NULL COMMENT '操作用户ID',
`track_uid` varchar(255) NULL DEFAULT NULL COMMENT '链路ID',
`code` int(11) NULL DEFAULT NULL COMMENT '操作代码',
`custom_code` int(11) NULL DEFAULT NULL COMMENT '操作2级代码',
`state` int(11) NULL DEFAULT NULL COMMENT '记录状态:1可查询,0不可查询',
`ctime` datetime NULL DEFAULT NULL,
`utime` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
三、应用整体架构设计
3.1、整体设计
这是整体的架构设计图,后续我们会一点点拆解这个架构来一步步实现第二章中的需求,最终实现整个架构实可以实现部署,并达到一个准生产的水平,也可以说接下来的文章都是围绕下面这张图展形的。
这里只是简单介绍一下,以便有个全局的认知,方便后续章节的学习。
3.1.1、分层详解
整体架构分为5层,我们只会服务层(4层),不会实现client端。详细的层次解释如下:
- APP层:指供终端用户使用的客户端程序,可以是web也可以是app,anywhere这不是本专题的内容所以不再细说了;
- OpenApi层:提供给APP端使用的API接口,在本专题中会实现Http接口,网关是介于APP和OpenApi中的一个中间组件,一般不是SAAS这样的平台并不需要网关层。本专题中并不会实现一个网关,上图中只是为了表述完整指出了网关层的位置;
- Server-API:其实也可认为它是Open Api的一种实现方式,可以供APP层直接调用。因为规范的原因在笔者的部门最终决定并不对APP暴露,所以在架构上下沉了一层;
- Server-Server:这没啥好说的,是Server-API的实现,内部分为两层Grpc和Server。可以把Grpc简单理解为门面。Server才是核心的实现;
- Persistence:存储层,在本专题中只用了mysql存储;
3.1.2、涉及的三方库
- google proto:一种跨语言的定义脚本语言;
- spring boot:
- spring mvc:
- mybatisPlus:一个数据库持久框架;
- mapStruct:Bean深拷贝框架;
3.2、层次调用
下面放出两张图,左图是笔者部门的规范用法,右图的调用方法也是被允许的也可以用于实际生产环境中。
3.2.1、调用链路分析
- App-Http-Grpc-Server-Dao:适用于单机和小型应用,比较规范,强调了Http和Grpc的职责;
- App-Http-Server-Dao:适用于单机和小型应用,会省略很多代码,适合http和grpc在同一应用中的设计,但同样也会带来后续拆分的问题;
- App-SDK-Grpc-Server-Dao:适合单机应用,在分布式应用中不建议用这种设计;
- App-Grpc-Server-Dao:适合大型分布式应用;
上面按适用场景拆分4条调用链路,这里总结说下在上述设计中:1、http就适用于大型应用的主要原因是性能比较慢,如果真要开放http接口不如直接用网关来代替。2、SDK这种交互方式只一点耦合改动的问题就非常建议如果没必要不要采用这种设计方式;但有一种弱SDK的方式是在序列化包提供一些工具类用来做API接口的辅助置换(前提是做好兼容性,但也要谨慎使用)。
下一节会描述下工程的构建