单体架构
单体,即:一个进程完成全部的后端处理,如果搞不定,就多个进程一起,单体中一般包含:客户端(App、H5、Web)、服务端部署(反向代理、数据库、中间件等),目前市面上大多数项目都还是主流于使用单体结构;
但是,随着 用户量、流量、数据的增长,单体架构出现了瓶颈(即:单台服务器处理能力有限、包括但不限于:并发处理不过来、内存、cpu、磁盘IO等瓶颈),就出现了:垂直、水平拆分,即使用多台服务器均衡请求;
水平、垂直拆分
水平拆分:同一个后端多环境部署,他们都处理相同的内容,使用反向代理来均衡负载;这种也叫集群(多个节点干相同的事儿)
垂直拆分:不同业务拆分为各个节点,反向代理通过路由将请求分发给每个业务节点上;
但是不论是 水平拆分 还是 垂直拆分,都是为了应对并发,使用更多的服务器来处理更多的请求;
分布式和集群
在 水平、垂直拆分时,假设我们的业务节点所产生的日志信息需要统一汇总记录,我们就分离出了一些共用的服务(Service-mini,小服务),供我们的业务层节点请求访问,比如共用的日志处理服务,每个业务节点都需要把自己的日志发送到公共的节点上,这时,慢慢就演变成了,一个业务节点,需要多个业务节点相互配合,最后才将用户的请求返回出去,这种架构,我们称之为:分布式;
关于真正理解 集群 和 分布式 的区别,包括什么是节点、什么是服务实例等,可以参考:这里
CAP:分布式的入门理论,即:C / A / P 这三个不能同时满足,或者说:一致性C、可用性A、分区容错P 不能同时满足;(关于CAP的分区容错P和为什么不能同时满足的更详细解释,点这里)
P:网络之间的的互相请求连接总是有不稳定(包括:丢包、断网、延迟等)的时候;
C和A:在P不满足的条件下,我们不能保证其高可用性、数据的一致性;
分布式事务:在分布式环境下,如何保证事务的一致性,即多节点之间的数据执行过程中,要么都成功、要么都失败;
分布式锁:单体中因为是一个进程,所以上锁是很简单的,比如内部锁lock,但是多进程的话,是很难保证他们之间事务的一致性;
微服务
当分布式的问题都解决掉之后,微服务就出现了;
所谓微服务架构,就是在分布式技术成熟后,使用分布式的方式去完成业务解耦,这种架构风格就是微服务架构(还包括全套的微服务架构组件)
官方含义:微服务架构是一个用分布式服务来拆分业务逻辑,完成解耦的架构模式(架构风格)
微服务架构就是在分布式技术成熟后,通过分布式服务来拆分业务逻辑,完成解耦,并且通过一系列组件和方法论来解决落地问题,这套架构风格+落地标准就是微服务架构!
微服务:每个服务就是方法,调用分布式服务
微服务图如下:
要想实现微服务的落地,必须先完成对服务的拆分!
推荐使用DDD领域驱动设计,来完成服务的拆分,即:按照领域来拆分(按照这种来拆分,每个人最终的结构都会是不一样的,所以,没有确切的结果!)
提示:学习微服务前,最好先了解什么是DDD领域驱动模型,里面的几个大概念需要理清,比如:领域和子领域、领域模型、实体和值对象、聚合和聚合根、领域事件、充血模型和贫血模型等;
微服务的知识体系
核心要求(必须掌握)
服务注册发现——高可用+伸缩性
网关服务治理——在客户端和服务端之间
功能性要求
全链路追踪:skywalking
分布式日志 ELK
Apollo 配置中心
独立鉴权授权中心 SSO
Prometheus+Grafana 监控分析
分布式锁——分布式事务
运维需求
Git+Jenkins+Docker+Kubernetes
微服务的根基(核心要求)
根基包括两点:
服务的高可用:即服务必须保证在线、存活,尽量降低服务不可用的情况;
服务的可伸缩:即服务能根据请求过来的流量、并发数等,去自动增减自身的服务(有些服务压力大,有些服务压力小,那么我们需要通过一种策略去动态地增加压力大的服务实例数量,减少压力小的服务实例数量);
那怎么实现高可用和可伸缩功能呢?即:怎么实现动态检查服务实例状态、动态增减服务实例数量呢?
我们就需要引入一个工具:服务注册发现
服务注册发现
每当每一个微服务实例启动时,都会向 服务注册发现中心 注册,服务注册发现中心 就会保存每个注册过来的服务实例,并向这些服务实例发送心跳、判断对应的服务实例是否正在工作、或者是否出现宕机等;
看上图,服务注册中心保存了已经注册的服务实例,我们在网关这里先去 服务注册中心Consul集群 中获取这些服务实例的信息(比如地址等),再去调用对应的集群中的某个服务实例节点;
现在又有一个问题,我们客户端如果要访问,那么是直接击中到服务实例集群中吗?很显然不是,,这就引出了第二个核心内容:网关服务治理;
网关服务[治理] Gateway
如果我们的客户直接击中服务实例节点,那么将会这样:
缺点:
1、上面只有8个服务实例,就那么乱了,而我们以后项目中部署的服务实例肯定会上百个,如果是这样子的话关系就会更加的复杂化了;
2、服务实例直接暴露给外网,公网IP肯定不够用,资源利用完全不可行;
3、安全性:难道每个微服务都要自己检查其自身的安全性吗?这样工作量太大,以后出现安全性问题也非常难以排查;
我们通过引入网关解决上面3个问题:
首先,客户端访问反向代理Nginx,然后反向代理将请求转发给 网关 ,网关根据请求来的信息,在 服务注册中心 中获取对应的微服务节点信息,然后根据信息找到微服务节点并请求该节点处理业务逻辑;
因为所有的请求都需要听过网关,所以我们可以在网关上做一些特殊的事情,包括但不限于:缓存、鉴权授权、均衡负载、路由转发、Polly(熔断服务、限流、超时和重试)等,我们将这些事情称之为:网关服务治理
Polly 是一种.NET弹性和瞬态故障处理库,允许我们以非常顺畅和线程安全的方式来执诸如重试,断路,超时,故障恢复等策略。