1. 什么是微服务
微服务是一种服务架构,它提倡将单一应用拆分为一些可独立运行、可协同工作的小服务,在微服务架构中,每个服务都拥有独立的进程,微服务的拆分一般是围绕着业务能力构架的,然后通过全自动部署流程,独立部署在docker容器上,同时这些小服务可以使用不同的技术栈(编程技术、数据存储)
总结特点如下:
- 轻量级可独立运行:独立开发、独立部署、独立工作的小系统(小服务)
- 可协同工作:微服务之间彼此通过rpc的方式来协同工作
- 分治:一个复杂业务拆分为多个子业务。这使得每个子业务更加高内聚、低耦合,从而能聚焦自身的功能。
2. 演进路径
演进方向为:单体应用 -> 服务化 -> 微服务架构。在演化过程中,架构越来越复杂,一个应用被拆分的服务也越来越细。
2.1 单体应用
典型的单体应用架构:
- LAMP(Linux + Apache + MySQL + PHP)
- MVC(Spring + iBatis/Hibernate + Tomcat)
优点:技术栈简单,上手快,部署容易
缺点:随着业务越来越复杂,开发团队规模不断扩张,单体应用架构就难以适应开发迭代节奏,表现如下:
1. 构建、部署效率低:代码越多,依赖资源越多,每次改动一个小点也需要全量构建
2. 团队协作成本高:开发人员越来越多,在一个工程中,开发上线沟通成本高
3. 可用性差:在一个进程中,一旦某个功能有问题,可能会导致整个应用服务挂掉
2.2 服务化
本地方法调用 转为 远程方法调用(RPC)
微服务和服务化的差异:
- 服务拆分粒度更细
- 服务独立部署、维护
- 服务治理要求高
2.3 微服务
微服务就是将庞杂臃肿的单体应用拆分成细粒度的服务,独立部署,并交给各个中小团队来负责开发、测试、上线和运维。
- 服务拆分粒度更细:根据业务拆分。
- 独立部署:每个服务在物理上相互隔离,互不影响
- 独立维护:根据组织架构拆分,分团队维护
- 服务治理:服务数量变多,需要有统一的服务治理平台
3. 如何拆分微服务
3.1 拆分的维度
有以下几个拆分的维度:
- 业务维度:业务和数据关系密切的应该拆分为一个微服务,而功能相对比较独立的业务适合单独拆分为一个微服务。
- 功能维度:公共功能聚合为一个服务。标准是是否被多个其他服务调用,且依赖的资源独立不与其他业务耦合。
- 组织架构维度:根据实际的组织架构,每个团队独立维护若干微服务
注意:微服务不是拆的越细越好,过度的拆分反而会让服务数据量越多变的难以管理,因此找到符合自己业务现状和团队人员技术水平的粒度才是可取的。
3.2 拆分的原则
- 单一原则:高内聚,低耦合
- 先粗后细,逐步优化
- 考虑并设计扩展性
3.3 拆分的前置条件
只有满足了以下几个条件,微服务才能去进行拆分:
- 服务如何定义
- 服务名,协议,ip,端口
- 接口名,参数,返回
- 服务如何订阅和发布
- 发布:暴露自己让别人调用
- 订阅:知道别人,然后调用别人
- 服务如何监控
- QPS(调用量)
- AvgTime(平均耗时)
- P999(99.9% 的请求性能在多少毫秒以内)
- 服务如何治理
- 限流
- 熔断
- 故障如何定位
- trace
- 链路追踪
4. 服务的容量规划
根据各个微服务部署集群的最大容量和线上实际运行的负荷,来决定各个微服务是否需要弹性扩缩容,以及需要扩缩容多少台机器。
4.1 如何评估容量
- 通过压测去评估
- 选择合适的压测指标
- 系统类指标 - CPU 使用率、内存占有量、I/O 使用率、网卡带宽等
- 服务类指标 - 接口响应的平均耗时、P999 耗时、错误率等
- 单机压测:日志回放,调用模拟
- 集群压测:一般做法是通过不断把线上集群的节点摘除,以减少机器数的方式,来增加线上节点单机的流量,从而达到压测的目的。
- 选择合适的压测指标
- 实时获取集群的运行负荷
4.2 扩容和缩容
伸缩容量的一种参考方式是使用水位线来决策扩容或是缩容。水位线就是集群的最大容量除以集群的实际运行负荷,可以实时监控集群的水位线。
- 当运行负荷超过水位线后,进行扩容(按数量、按比例)
- 当运行负荷小于水位线后,进行缩容(为了避免抖动,缩容不应该一次性完成,而应该按比例逐步完成)
5. 微服务的核心组件
5.1 服务定义
描述一个微服务所负责的scope,提供了哪些能力,暴露了哪些接口
- 服务名称
- 服务ip和端口
- 能力接口
- 接口的request和response
常见的服务定义可以通过以下三种方式:
- Rest API:通常用于 HTTP 协议的服务定义,并且常用 Wiki 或者Swagger来进行管理。
- XML - XML 配置方式多用作 RPC 协议的服务定义,通过 *.xml 配置文件来定义接口名、参数以及返回值类型等。
- IDL - IDL 文件方式通常用作 Thrift 和 gRPC 这类跨语言服务调用框架中,比如 gRPC 就是通过 Protobuf 文件来定义服务的接口名、参数以及返回值的数据结构。
5.2 注册中心
服务提供者 需要将自己注册到注册中心,然后服务消费者就可以从注册中心拉取到提供服务的机器,并进行调用。
步骤如下:
- 服务提供者在启动时,根据服务发布文件中配置的发布信息向注册中心注册自己。
- 服务消费者在启动时,根据消费者配置文件中配置的服务信息向注册中心订阅自己所需要的服务。
- 注册中心返回服务提供者地址列表给服务消费者。
- 当服务提供者发生变化,比如有节点新增或者销毁,注册中心将变更通知给服务消费者。
5.3 服务调用
服务调用就是指:服务消费者在订阅到服务提供者,当使用到服务提供者的能力后,调用服务提供者提供的接口并获取数据的过程。
核心流程包括:
- 服务通信采用什么协议进行网络通信: TCP、UDP 、HTTP 协议
- 数据传输采用什么方式:同步 or 异步;单连接上传输 or 多路复用
- 序列化方式:JSON、java序列化、protobuf、thrift等
5.4 服务监控
- 调用链路追踪并采集数据
- 数据处理:计算,产出各种指标数据
- 数据看板展示:各种指标的展示、聚合
- 监控和报警:提供各种维度的报警,峰值、最小值、平均值、同比,环比,智能预测等
5.5 服务治理
发现问题:服务监控
定位问题:链路追踪
解决问题:服务治理
见: