因为发展新的业务线,需要对现有的服务进行拆分,同时在目前使用微服务架构的过程中也遇到了许多问题,这让我们对现有项目中使用的微服务架构也产生了疑惑,是否应该继续使用微服务架构,还是回归单体。带着微服务到底是什么以及服务该如何拆分两个问题进行探究。
所有的新技术产生以及兴起,必然是在旧的技术栈无法满足当前需求。
单体应用
业务代码运行都集中在一个进程中,各种方法调用都属于进程内调用,往往是一个war包包含了项目的全部功能。
单体应用技术栈
---LAMP(Linux + Apache + MySQL +PHP)
---MVC(Spring + iBatis/Hibernate + Tomcat)
早期在业务规模不大、开发团队人员规模较小的时候,采用单体应用架构,团队的开发和运维成本都可控。
然而当业务规模不断扩大,开发团队不断扩张,单体应用架构就会出现问题。
1、部署效率低下-协同开发问题无法回避。
2、系统高可用性差-局部影响整体功能。往往可能因为某个影响造成整个应用的不可用。
3、线上发布变慢-服务启动时间加长。存在一个小小的功能点上线,整个项目都需要重新部署。
4、系统扩展性差。在新增业务时,代码层面会考虑在不影响现有的业务基础上编写代码,提高了代码的复杂性。
服务化
从单体应用发展到微服务架构,过程中伴随这个一个概念的演进--服务化。
服务化就是把传统的单机应用中通过 JAR 包依赖产生的本地方法调用,改造成通过 RPC 接口产生的远程方法调用。
一般在编写业务代码时,对于一些通用的业务逻辑,尽力把它抽象并独立成为专门的模块,因为这对于代码复用和业务理解都大有裨益。
什么是微服务
得益于以 Docker 为代表的容器化技术的成熟以及 DevOps 文化的兴起,服务化的思想进一步演化,演变为今天我们所熟知的微服务。
移动互联网规模不断扩大、敏捷开发、持续交付、DevOps理论发展和实践,以及容器化技术的成熟,让微服务真正兴起。
微服务与服务化对比
1、服务拆分粒度更细。只要该模块依赖的资源与其他模块都没有关系,那么就可以拆分为一个微服务。
2、服务独立部署。每个微服务都严格遵循独立打包部署的准则,互不影响。
3、服务独立维护。每个微服务都可以交由一个小团队甚至个人来开发、测试、发布和运维,并对整个生命周期负责。
4、服务治理能力要求高。因为拆分为微服务之后,服务的数量变多,因此需要有统一的服务治理平台,来对各个服务进行管理。
单体到微服务过度
什么时候进行服务拆分
项目第一阶段的主要目标->快速开发和验证想法,证明产品思路是否可行。此时,功能设计通常都比较简单,开发采用快速迭代的方式,开发人员的投入量有限,项目部署、测试、运维等都采用最简单的方式,这个时候对于单体应用来说足够支撑。
而当项目在迭代中不断增加许多的新特性,投入开发人员的规模也在不断扩大,项目部署、测试、运维等也会可能因为功能之间的相互影响而导致持续迭代的投入价值增加,此时可以考虑对项目进行服务拆分。
横向拆分和纵向拆分
纵向拆分。是从业务维度进行拆分。标准是按照业务的关联程度来决定,关联比较密切的业务适合拆分为一个微服务,而功能相对比较独立的业务适合单独拆分为一个微服务。
横向拆分。是从公共且独立功能维度拆分。标准是按照是否有公共的被多个其他服务调用,且依赖的资源独立不与其他业务耦合。
服务拆分的前置条件
服务如何定义。每个服务都运行在各自的进程中,那么服务如何向外传递自己的信息。-》接口形式:http/rpc。
服务如何发布和订阅。从进程间调用到跨进程调用,微服务需要面对的问题。
1、服务调用者如何查询所需要调用服务提供者的地址。
2、服务提供者如何登记自己的地址。
服务如何监控。QPS(调用量)、AvgTime(平均耗时)、P999(99.9% 的请求性能在多少毫秒以内)这些指标。
1、业务埋点
2、数据收集
3、数据处理
4、数据展示
服务如何治理。熔断
故障如何定位。如何标记一次请求的完整路径。
微服务架构模块
首先服务提供者(就是提供服务的一方)按照一定格式的服务描述,向注册中心注册服务,声明自己能够提供哪些服务以及服务的地址是什么,完成服务发布。
接下来服务消费者(就是调用服务的一方)请求注册中心,查询所需要调用服务的地址,然后以约定的通信协议向服务提供者发起请求,得到请求结果后再按照约定的协议解析结果。
而且在服务的调用过程中,服务的请求耗时、调用量以及成功率等指标都会被记录下来用作监控,调用经过的链路信息会被记录下来,用于故障定位和问题追踪。在这期间,如果调用失败,可以通过重试等服务治理手段来保证成功率。
基础组建
服务描述
服务描述主要解决服务如果对外描述的问题。解决跨进程调用问题,从调用本地api到rpc远程方法调用。
1、对外的服务名是什么
2、调用该服务需要哪些信息
3、返回的结果是什么
4、如何解析该结果
常见实现对外描述的方式,RESTful API、XML 配置以及 IDL (interface description language)文件(Thrift 和 gRPC)三种。
注册中心
注册中心主要解决服务的发布和订阅问题。一般来讲,注册中心的工作流程是:
1、服务提供者在启动时,根据服务发布文件中配置的发布信息向注册中心注册自己的服务。
2、服务消费者在启动时,根据消费者配置文件中配置的服务信息向注册中心订阅自己所需要的服务。
3、注册中心返回服务提供者地址列表给服务消费者。
4、当服务提供者发生变化,比如有节点新增或者销毁,注册中心将变更通知给服务消费者。
服务框架
1、服务通信采用什么协议?TCP、UDP 协议,还是采用七层 HTTP 协议 or其他
2、数据传输采用什么方式?同步还是异步,是在单连接上传输,还是多路复用。
3、数据压缩采用什么格式?JSON 序列化、Java 对象序列化以及Protobuf 序列化等
服务监控
一旦服务消费者与服务提供者之间能够正常发起服务调用,你就需要对调用情况进行监控,以了解服务是否正常。通常来讲,服务监控主要包括三个流程。
指标收集。就是要把每一次服务调用的请求耗时以及成功与否收集起来,并上传到集中的数据处理中心。
数据处理。有了每次调用的请求耗时以及成功与否等信息,就可以计算每秒服务请求量、平均耗时以及成功率等指标。
数据展示。数据收集起来,经过处理之后,还需要以友好的方式对外展示,才能发挥价值。通常都是将数据展示在 Dashboard 面板上,并且每隔 10s 等间隔自动刷新,用作业务监控和报警等。
服务追踪
记录每次跨进程调用的request是否为同一次。request id
服务治理
单机故障。通常遇到单机故障,都是靠运维发现并重启服务或者从线上摘除故障节点。然而集群的规模越大,越是容易遇到单机故障,在机器规模超过一百台以上时,靠传统的人肉运维显然难以应对。而服务治理可以通过一定的策略,自动摘除故障节点,不需要人为干预,就能保证单机故障不会影响业务。
单 IDC 故障。你应该经常听说某某 App,因为施工挖断光缆导致大批量用户无法使用的严重故障。而服务治理可以通过自动切换故障 IDC 的流量到其他正常 IDC,可以避免因为单 IDC 故障引起的大批量业务受影响。
依赖服务不可用。比如你的服务依赖依赖了另一个服务,当另一个服务出现问题时,会拖慢甚至拖垮你的服务。而服务治理可以通过熔断,在依赖服务异常的情况下,一段时期内停止发起调用而直接返回。这样一方面保证了服务消费者能够不被拖垮,另一方面也给服务提供者减少压力,使其能够尽快恢复。
todo
总结
文章内容大部分来自胡忠想老师的《从0开始学微服务》课程笔记。