本专题所写所感所得,来自转转首席架构师和字节架构团队,此致,敬礼。。
一、引言
邓宁-克鲁格效应是指的是能力欠缺的人在自己欠考虑的决定的基础上得出错误结论,但是无法正确认识到自身的不足,辨别错误行为,是一种认知偏差现象。这些能力欠缺者们沉浸在自我营造的虚幻的优势之中,常常高估自己的能力水平,却无法客观评价他人的能力。
这种现象称为「邓宁克鲁格效应」。
邓宁将这种效应归纳为:「如果你没有能力,你就不会知道自己没有能力。」
中国的绝大多数研发人员处于第一阶段,不知道高层级的架构知识自己不知道。本专题的目的是把架构师从愚昧之巅推向绝望之谷,之后能到哪里,全是造化全是命,师傅领进门,修行靠个人。。
本场 Chat 主要内容:
- 互联网发展三阶段
- 互联网架构演进之路
- 单体架构设计与实践
- 水平分层架构设计与实践
- 面向服务架构设计与实践
- 微服务架构设计与实践
- 服务网格架构设计与实践
- 千亿级真实案例实践
二、互联网发展三个阶段
2.1 概念
- PC互联网(静态化)
让数据可以在一定范围内在线化。 - 移动互联网(动态化)
让人越来越多的数据被记录被联通,让数据智能成为可能。 - 物联网(万物连接)
让网络协同从人到万物。
2.2 场景
以互动形式作为三个阶段的场景为例:
2.3 特点
- 业务功能越来越多、越来越复杂
- 万物互联数据量越来越大
- 请求量越来越大、更高的用户体验要求
- 业务快速迭代持续交付的能力
三、互联网架构演进
互联网架构演进经历了单体架构、水平架构、面向服务架构、微服务架构、服务网格架构等演进过程。大致的演进方向如下图所示:
本文按照演进的模型顺序来介绍架构的演进。
3.1 单体架构
以某一商业系统为例,它接受客户的订单,验证库存和货款,然后发货。系统大致可以分为三个核心模块(账户模块、库存模块、配送运输模块)。将三个核心模块封装到一个war包内部署。
3.1.1 优点
- 开发简单
- 测试简单
- 部署简单
- 扩展简单
3.1.2 适用场景
- 业务场景简单、功能不复杂、研发人员少
- 创业公司初期
- 性能要求极其苛刻
3.1.3 缺点
- 系统耦合性高
- 技术选型单一
- 开发效率越来越低下
3.1.4 问题改进
数据库数据量大,查询效率低肿么办?
答:拆分。垂直拆分(分库)、水平拆分(分表)
业务逻辑逐渐复杂,系统臃肿肿么办?
答:拆分。垂直方向拆分(业务纬度)、水平拆分(功能纬度)
3.2 水平分层架构
水平分层架构按功能纬度水平分层,每层之间逻辑解耦。可分为网关层、业务逻辑层、数据访问层、数据存储层。
3.2.1 网关层
网关层主要提供通用的功能,与业务逻辑相关性不强。大致分为以下几个功能:
- 请求鉴权
登陆鉴权、黑白名单等 - 数据完整性检查
数据包header、body完整性、正确性检查,是否被窜改等 - 协议转换
json->hashmap、pb->json等 - 路由转发
根据cmd转发到不同的业务逻辑层 - 服务治理
限流、降级、熔断等
3.2.1.1 网关实现
IO模型详解参考:Linux IO模式及 select、poll、epoll详解
3.2.2 业务逻辑层
- 库存模块
库存量加减、库存是否充足判断、是否需要补充库存等。 - 配送模块
配送管理、订单管理、物流信息等。
3.2.3 数据访问层
3.2.3.1 CURD
程序员日常工作,业务的增删改查
3.2.3.2 ORM
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
对比纬度 | mybatis | hibernate |
---|---|---|
难易度 | 相对容易上手 | 重量级,掌握难度大些 |
工作量 | 手写SQL,需要维SQL和结果映射 | 封装、简洁 |
可移植性 | SQL是依赖数据库书写的,所以扩展性差,可移植性比较差 | 可移植性强,Hibernate与数据库具体的关联都在XML配置中 |
缓存机制 | 缓存机制不佳,脏数据会给系统带来很大的隐患 | Hibernate用户无需关心SQL,二级缓存出现脏数据系统会报错 |
使用场景 | 都适用 | 单一业务高并发下不建议使用 |
3.2.3.3 分库分表
对比纬度 | Mycat | Sharding-JDBC | Sharding-Proxy | Sharding-Sidecar |
---|---|---|---|---|
官方文档 | Mycat 权威指南 | 官方文档 | 官方文档 | 官方文档 |
开发语言 | Java | Java | Java | Java |
开源协议 | GPL-2.0/GPL-3.0 | Apache-2.0 | Apache-2.0 | Apache-2.0 |
数据库 | MySQL、Oracle、SQL Server、PostgreSQL、DB2、MongoDB、SequoiaDB | MySQL、Oracle、SQLServer、PostgreSQL、任何遵循 SQL92 标准的数据库 | MySQL/PostgreSQL | MySQL/PostgreSQL |
连接数 | 低 | 高 | 低 | 高 |
应用语言 | 任意 | Java | 任意 | 任意 |
代码入侵 | 无 | 需要修改代码 | 无 | 无 |
性能 | 损耗略高 | 损耗低 | 损耗略高 | 损耗低 |
无中心化 | 否 | 是 | 否 | 是 |
静态入口 | 有 | 无 | 有 | 无 |
管理控制台 | Mycat-web | Sharding-UI | Sharding-UI | Sharding-UI |
分库分表 | 单库多表/多库单表 | ✔️ | ✔️ | ✔️ |
多租户方案 | ✔️ | -- | -- | -- |
读写分离 | ✔️ | ✔️ | ✔️ | ✔️ |
分片策略定制化 | ✔️ | ✔️ | ✔️ | ✔️ |
分布式主键 | ✔️ | ✔️ | ✔️ | ✔️ |
标准化事务接口 | ✔️ | ✔️ | ✔️ | ✔️ |
XA强一致事务 | ✔️ | ✔️ | ✔️ | ✔️ |
柔性事务 | -- | ✔️ | ✔️ | ✔️ |
配置动态化 | 开发中 | ✔️ | ✔️ | ✔️ |
编排治理 | 开发中 | ✔️ | ✔️ | ✔️ |
数据脱敏 | -- | ✔️ | ✔️ | ✔️ |
可视化链路追踪 | -- | ✔️ | ✔️ | ✔️ |
弹性伸缩 | 开发中 | 开发中 | 开发中 | 开发中 |
多节点操作 | 分页、去重、排序、分组、聚合 | 分页、去重、排序、分组、聚合 | 分页、去重、排序、分组、聚合 | 分页、去重、排序、分组、聚合 |
跨库关联 | 跨库 2 表 Join ER Join、基于 caltlet 的多表 Join | -- | -- | -- |
IP 白名单 | ✔️ | -- | -- | -- |
SQL 黑名单 | ✔️ | -- | -- | -- |
存储过程 | ✔️ | -- | -- | -- |
放弃吧,小伙伴,分库分表多麻烦呀,有条件的话,直接上ti-db吧
3.2.3.4 屏蔽底层存储差异性
- mysql/mongodb
- redis/memcached
- leveldb/rocksdb/hbase
- ti-db
3.2.4 同步架构 or 异步架构
3.2.4.1 同步架构
同步架构是以串行的方式实现业务服务的响应。
全流程解析如下图:
3.2.4.2 异步架构
异步架构是通过消息队列mq异步提高吞吐量。
3.2.5 分层设计
水平分层设计过多或者过少有啥缺点?
答:
1.过多:请求路径变长、平均响应延时变高、定位问题复杂、运维成本高。
2.过少:变成单体架构了。
水平分层设计几层合适?
答:
1.同步架构(四层):网关层、业务逻辑层、数据访问层、数据存储层。
2.异步架构(五层):网关层、异步消息队列层、业务逻辑层、数据访问层、数据存储层。
3.3 面向服务架构(SOA)
面向服务架构是垂直分层。不同功能模块通过定义好的接口关联,接口采用中立的方式定义,独立于硬件平台、操作系统、编译语言。其主要特点是:
- 多个独立服务
-
通过esb交互
3.3.1 缺点
- 业务垂直,每个服务都是一个单体架构
- 严重依赖于esb消息总线
3.4 微服务架构
微服务架构是微服务可以在“自己的程序”中运行,并通过“轻量级设备与HTTP型API进行沟通”。关键在于该服务可以在自己的程序中运行。通过这一点我们就可以将服务公开与微服务架构(在现有系统中分布一个API)区分开来。在服务公开中,许多服务都可以被内部独立进程所限制。如果其中任何一个服务需要增加某种功能,那么就必须缩小进程范围。在微服务架构中,只需要在特定的某种服务中增加所需功能,而不影响整体进程的架构。
说人话:就是把水平分层架构的每一次再拆分出更细粒度的微服务。
3.4.1 举个例子
服务被拆分成酱紫:
- 网关层
1个 - 业务逻辑层
N个 - 数据访问层
N个 -
DB/Cache
N个
3.4.2 缺点
各个大厂都在用,优点太多,罄竹难书,不讲了。咱们反而道而行之,只讲缺点:
-
迭代速度变慢
业务需关注服务间通信,所以迭代速度变慢。
-
基础组件升级困难
-
存在多语言通信问题,业务每种语言有一套基础设施,成本大
3.5 服务网格架构(service mesh)
服务网格是一个基础设施层,用于处理服务间通信。云原生应用有着复杂的服务拓扑,服务网格保证请求可以在这些拓扑中可靠地穿梭。在实际应用当中,服务网格通常是由一系列轻量级的网络代理组成的,它们与应用程序部署在一起,但应用程序不需要知道它们的存在。
3.5.1 优点
- 独立进程、独立升级
- 业务只关注业务逻辑本身
- 一套基础设施支持多语言开发
- 业务团队和基础设施团队物理解耦
3.5.2 Istio
要聊ServiceMesh,就不得不提Istio,它是ServiceMesh目前最流行的实践,今天说说Istio是干啥的。
- Istio服务网格逻辑上分为数据面、控制面。
- 数据面由一组智能代理(Envoy)组成,代理部署为sidecar,调解和控制微服务所有的网络通信。
- 控制面负责管理和配置代理来路由,以及运行时策略。
3.5.2.1 数据面Envoy
Envoy的核心职责是高效转发,主要有以下功能:
(1)服务发现
(2)负载均衡
(3)安全传输
(4)多协议支持,例如HTTP/2,gRPC
(5)断路器(Circuit breakers)
(6)健康检查
(7)百分比分流路由
(8)故障注入(Fault injection)
(9)系统度量
3.5.2.1.1 请求路由
3.5.2.1.2 服务发现和负载均衡
三种负载平衡模式:轮循、随机、带权重。
3.5.2.1.3 断路器
它是软件架构设计中,一个服务自我保护,或者说降级的设计思路。
举个例子:当系统检测出某个接口有大量超时时,断路器策略可以终止对这个接口的调用(断路器打开),经过一段时间后,再次尝试调用,如果接口不再超时,则慢慢恢复调用(断路器关闭)。
主要功能包括
- 超时
- 带超时预算有限重试
- 并发连接数和上有服务请求数限制
- 健康检查
3.5.2.1.4 故障注入
它是软件架构设计中,一种故意引入故障,以扩大测试覆盖范围,保障系统健壮性的方法,主要用于测试。
故障注入的两种类型:
- 延迟:计时故障,模拟增加网络延时或过载的上游服务。
- 中止:模拟上游服务的崩溃故障。中止通用以http错误代码或者tcp连接失败形式表现。
3.5.2.2 控制面
3.5.2.2.1 Mixer
Mixer的一些核心能力是:
(1)跨平台,作为其他组件的adapter,实现Istio跨平台的能力;
(2)和Envoy通讯,实时各种策略
(3)和Envoy通讯,收集各种数据
Mixer的设计核心在于“插件化”,这种模型使得Istio能够适配各种复杂的主机环境,以及后端基础设施。
3.5.2.2.2 Pilot
Pilot作为非常重要的控制平面组件,其核心能力是:
(1)为Envoy提供服务发现能力;
(2)为Envoy提供各种智能路由管理能力,例如A/B测试,灰度发布;
(3)为Envoy提供各种弹性管理能力,例如超时,重试,断路策略;
Pilot的设计核心在于“标准化”,它会将各种流控的控制命令转化为Envoy能够识别的配置,并在运行时,将这些指令扩散到所有的Envoy。Pilot将这些能力抽象成通用配置的好处是,所有符合这种标准的Envoy都能够接入到Pilot来。
潜台词是,任何第三方可以实现自己的proxy,只要符合相关的API标准,都可以和Pilot集成。
3.5.2.2.3 Citadel
Citadel组件,它提供终端用户身份认证,以及服务到服务的访问控制。总之,这是一个和安全相关的组件。
3.6 实践
以某知名互联网公司架构演进为例。
3.6.1 服务架构1.0
服务被拆分为:
- 网关层
1个 - 业务逻辑层
1个 - 数据访问层
N个 -
DB/Cache
N个
娘耶,业务逻辑层粒度太粗,所有业务逻辑耦合到一起,开发效率也低。拆迁队准备就位,垂直方向拆拆拆。。
3.6.2 服务架构2.0
服务被拆分为:
- 网关层
1个 - 业务逻辑层
N个 - 数据访问层
N个 -
DB/Cache
N个
这下好了吧,但公共逻辑和业务逻辑混合在一起,没有解耦。
公共逻辑层
- 组件化:引入jar/sdk包
- 服务化:下层为独立服务
拆迁队继续搞事情,水平方向拆拆拆。。
3.6.3 服务架构3.0
服务被拆分为:
- 网关层
1个 - 业务逻辑层
N个 - 公共逻辑层
N个 - 数据访问层
N个 -
DB/Cache
N个
3.6.4 服务架构4.0
该服务架构的未来是service mesh,没搞没搞。
四、写在最后
以上架构演进都是扯淡,适合自己的才是最好的架构。