微服务是近年来比较热门的服务架构思想,本文根据个人理解聊聊微服务架构,不足之处还请指正。
微服务概述
微服务,顾名思义微小的服务,当传统的单体应用规模和复杂度达到一定程度的时候,应用的管理、扩展、可靠性等方面就会出现瓶颈,一个基本原则就是分而治之,把一个大的复杂应用拆分成多个小的服务,让每个小服务可以单独进行管理、扩展,微服务由此演化而来。
微服务强调拆分后服务的独立性,麻雀虽小,五脏俱全,每个微服务有自己独立的数据库,有自己的业务实现,各自运行在独立的进程中,对外提供设计好的接口,服务间去耦合,通过RPC、HTTP等标准协议进行交互,服务内部功能可以使用任意语言和框架实现,对外是不可见的。
微服务有点像KTV包厢,包厢之间是相互独立的,每个包厢有自己的音响、点歌机,包厢之间仅通过过道和门连通。你可以在KTV包厢里面尽情歌唱都不会影响别人,就像你可以用Java、Python、go等多种语言实现多个微服务,只要接口明确,它们都能很好地协同。
微服务架构特点
1、去中心化
传统的单体应用只有一个服务,这个服务就是系统的中心,而微服务架构是去中心化的,把复杂的系统拆分成多个简单的分布式组件,每个组件都是服务化的,能够独立部署独立升级。
除了业务逻辑去中心化,数据同样也要去中心化,微服务要有自己独有的数据库,每个服务只对自己的数据负责,也不允许直接读写别人的数据库,就像自家的资产只能自己处置,别人不能随便动。
去中心化有利于降低系统内部服务冗余,使组件服务能够灵活地扩展和升级,比如有针对性地对系统某些高频组件进行扩容,就能快速提升系统并发能力,节省成本。
2、专注做好一件事
微服务架构的关键在于业务功能的合理拆分,以最终实现分布式系统的高内聚、低耦合,如果拆分不合理还会导致后期代码维护和功能扩展越发困难。
通常架构设计时尽可能使每个微服务专注做好一件事,合理划分服务边界,使数据结构易于独立,对外接口简洁通用,一个好的设计理念就是领域驱动设计(Domain Driven Design),根据领域的边界设计服务范畴。
3、语言多样性
单体应用通常只能采用单一语言开发,但每种编程语言都有各自优势,协作团队中通常每个人都有各自擅长的语言框架,单体应用限制了这种自由,而在微服务系统中没有这些限制,各个服务相互独立,每个服务都可以用不同的编程语言实现,每个人都可以发挥自己的特长。
事实上,技术的多样性对一个系统的健壮性也大有裨益,除了可以发挥多种语言框架的优势,还可以逐步引入新技术,有利于系统的演进升级。
4、RESTful无状态
微服务架构很好地实现了服务解耦和水平扩展,服务接口做成RESTful无状态的,业务逻辑与数据分离,服务间通过RESTful API交互,这样服务实例就可以按需进行弹性伸缩。
5、服务容错保护
我们知道在分布式系统中,节点失效应被视作常态而不是意外,即节点失效是一定会发生的,要实现系统高可用,必须要提前做好预备措施。微服务体系中,由于服务间错综复杂的依赖关系,对微服务进行容错保护是很有必要的,当某个服务实例出错时及时进行降级、隔离,既能提高响应速度,还能防止请求积压造成雪崩。
服务容错保护和业内常提的异地多活、Design For Failure 等思想一脉相承,一方面是服务提供方的多实例冗余,另一方面是服务消费方的容错保护,都是为分布式系统的高可用所做的预备措施。
当然任何系统都很难保证绝对可用,前不久就连AWS和Google Cloud都发生过服务中断事件,这在互联网系统中都是灾难性的,我们只能通过各种容错手段尽量避免此类事件发生。
6、开发运维一体化
开发运维一体化即流行的DevOps,谁开发的谁运维,这样开发人员能更快地响应业务需求,更好地保障服务后续运行和升级,同时避免团队间大量的无效沟通和摩擦。
现在流行的各种CI/CD、自动化运维技术也在促进开发运维一体化。
7、拥抱容器技术
有人说容器和微服务简直是天生一对,容器的轻巧高效恰好匹配微服务的灵活多变,结合Docker容器技术和微服务架构有助于应用的持续集成、持续交付和持续部署,目前备受追捧的云原生技术就是直接把微服务构建在容器基础设施上。
随着Kubernetes等容器基础设施的日趋成熟,容器逐渐成为微服务的标准载体,在容器基础设施上构建运行高可用、高可扩展的微服务将越来越简单。
微服务的挑战
微服务作为近年来流行的软件架构风格,它能帮助我们实现系统的高可用和高可扩展性,但微服务也会有各种挑战。
应用的挑战
由于微服务将整个系统进行拆分,所以系统的架构、开发工作量和复杂度会增加不少;
原来的单体应用变成一系列微服务,要管理和协调这些服务,系统的运维复杂度会增加不少;
原来调用的本地方法变成了服务间的远程调用,可能会使系统性能有所降低,这意味着要增加硬件投入。
架构的挑战
除了应用中的挑战,微服务架构本身也面临挑战,根据CAP理论,在分布式系统中数据一致性(Consistency)、服务可用性(Availability)、分区容忍性(Partition tolerance)三者不可能同时满足,最多只能实现其中两点,那么如何根据业务特点做出最佳权衡和取舍,就是微服务架构面临的挑战。
孟老夫子说过鱼和熊掌不可兼得,则舍鱼而取熊掌者也。在分布式系统中,分区容忍是必须要满足的,所以一般在一致性和可用性之间进行权衡,要么舍弃部分一致性,追求高可用;要么严格强调一致性,损失部分高可用。
到底是高可用重要还是一致性重要,这在服务注册中心也对应着两种流派:一种是Eureka为代表的AP流派,强调高可用,弱化一致性;另一种是CP流派,典型的就是ZooKeeper这类注册中心,更强调一致性,但会牺牲部分高可用。
一种常用的折中方案就是BASE原则,它是指基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventual Consistency),也就是牺牲强一致性,获得较好的可用性,允许暂时的状态或数据不一致,只要最终一致就行了。
实际应用中要根据系统对高可用和一致性等各方面的要求程度,做出适当的权衡和取舍。
是否采用微服务
对一个系统来讲,架构是逐步演进的,是否采用微服务架构要根据具体的团队和业务情况来定,一般来讲,如果团队规模和业务复杂度达到一定程度,单体应用已经力不从心的时候就该上微服务了。