本篇对微服务相关概念进行梳理总结。
1.为什么要有微服务
在传统的企业架构中,所有的业务逻辑集中在一个应用中,但随着不断的需求增加,如添加不同的业务模块,给前端支持更多的接口模块,会使得单体应用越来越臃肿。由于单体系统部署在一个进程内,部署耗时长,修改了一个小功能,部署上线就会影响其他功能的运行。且扩展能力受限,无法根据业务模块的需要进行伸缩,比如有的模块是计算密集型的需要强劲的CPU,有的模块是IO密集型的需要更多内存。最后传统的架构可靠性差,某个应用bug如死循环、OOM等,就会导致整个应用的崩溃。为了解决单体系统变得臃肿庞大之后产生的难易维护的问题,微服务架构诞生并逐渐获得大家关注。
微服务根据功能划分模块拆分成不同的服务,这些服务能够独立部署和扩展。每个服务都运行在自己进程内,每个服务的更新基本不会影响到其他服务的运行。同时,我们也可以方便的评估单个服务的性能容量,及时发现系统的瓶颈与问题。
2.微服务架构的特点
微服务和微服务架构是不同的概念。Martin Fowler在他的博客中这样描述微服务:
In short, the microservice architectural style [1] is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.
简单翻译就是:微服务的架构风格就是把一个单一的应用演变成一组小服务的形式。每个服务都运行在自己的进程中,并通过轻量级的通信机制保持通信,如HTTP协议这样的API。这些服务要围绕业务场景,并可通过全自动化布署工具进行独立的部署发布。这些服务共用一个非常轻量级的集中式管理来协调这些服务。服务可以使用不同的语言来编写,也可以使用不同的数据存储技术。
微服务的特点总结如下:
- 根据功能来划分服务组件或应用,每个服务只关注特定的功能,符合高内聚的原则
- 每个服务组件可以独立部署并相互隔离,都运行在自己的进程内
- 组件之间通过轻量级的通信协议api来调用,如基于HTTP的RESTful API、轻量级的消息总线如使用AMQP协议的RabbitMQ等
- 服务要保证高可用
- 因为组件较多,一般采取全自动化的持续部署机制
3.微服务的好处
- 按照功能来划分组件后,可以方便的分配团队资源,每个团队负责一个服务。这样业务清晰,开发和维护单个服务相对简单。
- 技术栈不受限。每个组件或应用都可以根据自己的项目业务和团队特点,合理的选用技术,甚至开发语言。
- 局部修改容易部署。一般来说,功能的变更只需修改少数几个组件即可,测试完即可部署上线,部署时间短提高部署效率。
- 可以方便的进行良好的监控,及时发现问题并采取容错机制,提高系统健壮性。
- 可以按需收缩。根据每个组件的业务,可以动态进行扩展,解决系统性能瓶颈。如针对单个服务增加内存,升级CPU或者增加节点。
4.微服务带来的问题
- 微服务在设计之初就要保证良好的边界,相对独立符合服务单一职责和自治原则。如何将微服务按照业务功能划分为多个组件,确定边界与粒度是一个重点和难点,需要有经验技术的架构。
- 对运维要求较高。按功能划分组件后,组件数量成倍增加,要保证几十个组件的正常运行和协作,对运维人员的能力和经验提出了较高要求。系统中出现故障的频率大大提升,虽然有高可用机制的保障,但是也需要做好良好的自动化监控,不断收集各个组件服务情况,及时发现处理问题。微服务开发之初就要实现持续交付平台来支撑整个实施过程,全自动的部署(包括编译 测试 发布)机制(现在流行的有利用jekins来实现持续集成CI,利用docker来部署各个组件)。
- 接口需要良好严格的定义。划分为多组件后,业务的依赖关系由代码上的依赖变为多个组件之间通信接口的调用,因此在一开始接口设计要非常谨慎,制定良好严格的接口规范,遵循开闭原则。否则后期修改一个微服务的API,就会影响到所有使用该接口的微服务。
- 分布式带来的复杂性。使用微服务构建的是分布式系统,这样就会带来系统容错、网络延迟、异步式消息、尤其分布式事务这样的难题。
- 提高了测试复杂性。划分为多个组件后,一个功能涉及到多个组件,要进行集成测试和系统测试,出现问题进行排查,给测试人员和开发人员带来了一定的困难。
- 很多服务可能都会使用到相同的功能,而这个功能又没必要分解为一个单独的微服务,每个服务里都编写这样的逻辑会带来代码的重复。可以通过将这些功能封装成公共组件来解决,需要该功能的微服务引用该组件即可。