互联网架构演进之路

前言

本文介绍下 互联网架构演进的4个阶段

1、单体架构
2、水平分层和面向服务架构(SOA)
3、微服务架构
4、服务网格架构(Service Mesh)

在此之前先简单介绍一个小知识点

redis做分布式锁弊端

redis实现分布式锁 哨兵模式下 会导致 一个锁同时被多个线程持有

分布式锁是CP模型 Redis是AP模型 用AP实现CP完全错误的

用ZK实现分布式锁 有性能问题

推荐使用etcd来实现分布式锁

互联网发展

  • pc互联网

静态 广播式
  • 移动互联网

动态 互动 比如微博关注
  • 物联网

万物连接 
比如微信群组 将一对一变成一对多 形成了网络

架构演进

单体

优点

开发、测试、部署、扩展 都很方便

扩展

应用场景

  • 功能不复杂 研发人员少

  • 创业初期

  • 性能要求极其苛刻

性能: 吞吐量、平均响应延迟

这里主要指平均响应延迟
比如股票、高频交易 需要及时捕捉到股票市场一些波动

缺点

  • 系统耦合性高

  • 技术选型单一

比如开发语言单一
  • 开发效率越来越低

水平分层

要解决这些问题 咱们先看看数据库是如何破局的 然后再类比到架构上

数据库如何解决单体瓶颈

拆分

  • 按业务垂直分库

比如 用户库 商户库

但还是单表
  • 水平拆分(分表)

比如 模1024 分1024表

db做了拆分 所以要考虑分布式事务

架构同理

水平分层架构设计

  • 垂直方向拆分

按业务维度
  • 水平方向拆分

物理分成多个独立进程

按功能纬度:网关层、业务逻辑层、数据访问层、数据存储层

每层逻辑解耦

数据访问层必须拆分出来 可以屏蔽掉分库分表逻辑和兼容不同的数据库(比如关系型、非关系型、NewSql)

分层设计原则

展示服务和网关服务分离举例

网关返回的发布时间是时间戳格式
展示层(APP)将时间戳转换成具体的日期格式
而非网关返回具体的日期格式

网关层功能

  • 数据完整性检查

app 通过https/http协议 以json字符串的格式

请求包:

1 定长header(uid、sessionId(请求唯一标识、cmd(请求命令号)、body length))

2 变长body

原则:

不会对价格字段做检查(不会处理具体业务语意)

但要做非空检查(通用逻辑)
  • 请求鉴权

    • 粗粒度:ip白名单

    • 细粒度:请求参数中有token,基于过滤器做token验证

1、登陆鉴权是属于具体业务 不属于请求鉴权 放在业务逻辑层

2、鉴权规则配置到配置中心 可视化方式获取
  • 协议转换

请求进入网关之后 不用短连接

传输协议

rpc oven tcp
可以提升传输效率

数据协议

protobuf google
(用json传输量大 pb二进制且压缩)
网关不需要理解具体的业务语意

1、json{k1,v1}转hashmap(string,object)

2、hashmap序列化pb

路由转发

负载均衡

网关开源组件


简单解释:

1、Kong基于nginx(Lua) 写了扩展性脚本

2、BIO是阻塞IO模型

3、Netty 用的NIO(N是New IO:IO复用)

4、epoll (linux具体网络实现,实现NIO)

5、AIO 异步IO模型 (用的不多 业务复杂度很高 性能最好)

6、Zuul 已贡献给 Spring Cloud 推荐Zuul

简单扩展:

1、国际化 在APP启动层做

2、第三方调用的场景用oauth授权 app用oauth意义不大

3、多版本号场景 业务逻辑根据不同版本号做差异

4、不同业务团队用一个网关

5、网关层是无状态的 每一个部署的模块是对等的 不存储数据

6、selct和poll不用 性能较差 epoll用的更多

7、springcloud大公司用的很少
中小型公司用的多
用的是http协议 没有用rpc

8、服务治理每层都要做

9、Zuul尽量少启动 一启动连接就丢了

10、app(混合式: 经常变的页面做成h5(不需要发版本) native)

业务逻辑层功能

数据访问层功能

orm映射 : pb->mysql协议

最难的是Sharding

1 原因:

很多情况 sharding不了

对商品留言功能 几十个亿 分片不了

留言id 留言商品id 留言人 留言时间 留言状态(有没有删除)

未分表 只需要建立index就可以

分表 parditing key只有一个

其他的查询字段要遍历所有表

2 解决方式:

通过映射表 基因法

3、分库分表查询的业务逻辑在业务逻辑层实现

最好的方式是不分片

将分表逻辑下推到db层

数据库进化史

  • rdbms

1、单机关系型数据库 
2、08年之前
3、比如mysql oracle
  • nosql

1、数据量大 互联网事务要求不高 (acid) 分布式非关系型数据库 

2、解决了分库分表

3、一致性解决不好 比如mongodb redis hive hbase

4、mongodb 3.0之前事务性不好 4.0及以后支持事务

newsql

1、金融电信银行 数据量大 事务要求很高 

2、分布式关系型数据库

3、比如国内tidb

a、tidb是强一致性的 支持事务acid

对一致性要求不高的 不用关系型数据库也可以 比如用redis

b、tidb用的是mysql协议 业务不需要升级

c、单机mysql数据存储的下的话 tidb比mysql慢 因为tidb是分布式的

d、异构存储 一致性很难保证

4、用newsql 线上单表 1200多亿 查询只需要4毫秒

同步架构

异步架构


1、为什么用mq做异步

mq顺序写入磁盘 append 追加 效率高
db随机写写磁盘

2、mq要放在网关和业务逻辑层之间变成异步

3、异步目的提升吞吐量

4、推荐使用rocketmq

5、读请求不能用mq
写请求可以用mq


数据一致性要求强:充值 不能用异步 吞吐量不高 低并发

数据一致性要求弱:发朋友圈 社交 可以用异步 吞吐量高 高并发

写场景是异步
读场景不是异步

发朋友圈 缓存到本地 读从本地读 不是从网关->业务逻辑层->数据存储层->db

发好了直接看 解决自己看问题就好了 好多秒之后再看 就已经入DB了

但异步也不定写成功到db

微信怎么办的 有未发送成功的消息

层次划分个数

  • 过多

1、请求路径变长

2、平均响应延迟变高

3、定位问题复杂 分布式请求跟踪系统

4、运维成本增加
  • 过少

单体
  • 适中

缺点

每层粒度过粗

扩展

1、reacter 模型 本质是异步架构 是一个实现手段

2、app和网关长连接 失败了会推给app
若http必须长轮询

3、使用nginx\f5\lvs意义会使请求更加健壮 因为网关会频繁重启

4、nginx反向代理 ip限流

5、mq不适合用udp协议(高性能udp) mq要保证数据可靠性

同步水平分层架构

dns解析 ->静态资源获取->动态资源获取
1、路由器虚拟化 NetGW

2、对象存储

a、fastdfs(规模小)
b、ceph(规模大 运维压力大 快存储、挂硬盘)


面向服务SOA

垂直拆分

1、多个独立服务(每个服务都是单体)

2、通过ESB交互 对ESB依赖严重

3、SOA不是微服务架构

微服务架构

垂直和水平都拆分

1、独立进程

2、围绕业务建模能力

3、独立部署

4、去中心化管理 (网关、业务逻辑
数据访问、存储层 都可以用各种语言写 但会带来很多问题)

1、用zk、consul做注册中心不行 eurka 可以

2、配置中心推荐 appllo 携程开源;不要用disconf(springcloud的生态)

3、交易系统是同步分层架构

4、注册中心不知道哪个服务挂掉 通过熔断可以知道

5、forupdate并发锁 粒度大 量大不行

6、同层之间不调用

本质

两个拆分

垂直(业务)拆分比较难

继续拆分 读、写微服务(按功能拆分 (api))

业务架构

微服务架构是业务架构 不是系统架构

组织架构

事业部制  公司->房产(产品、研发、销售) 招聘(产品、研发、销售) 二手车(产品、研发、销售) 效率高

公司->产品、研发、销售 效率低

应用场景

需求层面

变化频繁 比如内部OA系统 ERP系统 不频繁 微服务意义不大

性能层面

1、吞吐量变高 平均响应延迟变高

2、高频交易 量化交易 不合适微服务

数据一致性层面

一致性分为:
强一致性
和最终一致性(用微服务其实解决这个问题)

多个db 分布式事务解决强一致性问题 性能就没了

往往最终一致性 (分为同步、异步场景)

目的

快速迭代、持续交付

降本(人力、机器)提效(开发、运维、测试)

后记

后续会介绍服务网格架构ServiceMesh
平凡人笔记
我还没有学会写个人说明!
上一篇

知悉、预防、修复:谷歌提出开源软件漏洞治理框架

下一篇

Go工程化(三) 依赖注入框架 wire

你也可能喜欢

评论已经被关闭。

插入图片