前言
现在研发的项目启动今已近一年之久,期间从项目属性、人员规模、系统定位等方面都发生了很大的变化,而且是越变越好。不过也因为此,项目最初的架构设计已经不能满足现在的需求,并随着时间的推移,诟病越来越多、越来越严重。
为了解决这一问题,开发人员也在努力的尝试各种办法,但总的来说之前的方式更多是在打补丁,暂时或看上去是解决问题了,实质上并没有从本质的变化。基于这一情况,这一次我们下定决心,用一定的人力、物力去重新定义系统的架构——基于Spring Cloud实现微服务的架构。
本文简要介绍微服务及微服务架构的概念,并描述了Spring Cloud的功能,然后基于Spring Cloud的各个组件搭建微服务的整体架构,并对升级后的系统架构进行了设计、约定和说明。
特别说明:鉴于现在的开发模式采用的是前后端分离的模式,系统问题在后端也较为严重,Spring Cloud也只一个后端治理的框架,所以本文主要讲述的是后端微服务的架构设计,前端的架构调整等Spring Cloud雏形完成后进行组合设计。
[TOC]
1. 微服务简述
1.1. 什么是微服务
微服务(MicroService)没有一个官方的标准定义,ThoughtWorks的首席科学家马丁·福勒这样说:“微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。”
http://img.kuqin.com/upimg/allimg/141027/225ZB561-1.png
image_1c3fajgaov1dbt7132p1tu7jkc29.png-99.7kB
1.2. 微服务架构优势
http://www.primeton.com/img/insideout/jiagou.jpg
image_1c3fb07a11f47mnr1rdn13gn16a82m.png-180.7kB
1 复杂度可控
在将应用分解的同时,规避了原本复杂度无止境的积累。每一个微服务专注于单一功能,并通过定义良好的接口清晰表述服务边界。
由于体积小、复杂度低,每个微服务可由一个小规模开发团队完全掌控,易于保持高可维护性和开发效率。
2 独立部署
由于微服务具备独立的运行进程,所以每个微服务也可以独立部署。当某个微服务发生变更时无需编译、部署整个应用。
由微服务组成的应用相当于具备一系列可并行的发布流程,使得发布更加高效,同时降低对生产环境所造成的风险,最终缩短应用交付周期。
3 技术选型灵活
微服务架构下,技术选型是去中心化的。每个团队可以根据自身服务的需求和行业发展的现状,自由选择最适合的技术栈。
由于每个微服务相对简单,所以需要对技术栈进行升级时所面临的风险就较低,甚至完全重构一个微服务也是可行的。
4 容错
当某一组件发生故障时,在单一进程的传统架构下,故障很有可能在进程内扩散,形成应用全局性的不可用。
在微服务架构下,故障会被隔离在单个服务中。若设计良好,其他服务可通过重试、平稳退化等机制实现应用层面的容错。
5 扩展
单块架构应用也可以实现横向扩展,就是将整个应用完整的复制到不同的节点。当应用的不同组件在扩展需求上存在差异时,微服务架构便体现出其灵活性,因为每个服务可以根据实际需求独立进行扩展。
简单来说,微服务是基于单体应用的新型架构模式,可以基于微服务更好的进行自动化测试、运维、监控,从而满足持续交付,最终实现高质量的用户价值。
1.3. 微服务 VS 当前开发
微服务的开发模式和传统开发模式有着很大的不同,大致有以下几点:
分工不同 :现在一个组负责一个系统,一个人负责系统的一部分;微服务后可能是一人负责一个或多个系统。
架构不同:现在更多的从模块上拆分、前后端上拆分开发;微服务后将同时从横向纵向上拆分。
部署方式不同:现在是手工和半自动发布;微服务后得自动化运维。
容灾不同:现在的系统是一个整体,并且是单点运行;微服务后可以多点负载,还可以隔离故障避免系统整体宕机。
团队结构不同 2 pizza(6~10人)的小团队
此处输入图片的描述
分权机制
联邦分权制 -- 对结果负责
职能分权制 -- 对行为负责
2. 技术选型
2.1. Dubbo
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。
Dubbo服务的官方更新非常不确定,2014年10月30日停止更新后,最近几个月低调开始维护,发布了5个优化版本。
2.2. 为什么选择Spring Cloud
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
Spring Cloud的开发团队专注于企业级开源框架的研发,不论是在中国还是在世界上使用都非常广泛,开发出通用、开源、稳健的开源框架是他们的主业。
Spring Cloud是微服务架构的生态环境,考虑到了微服务的各个方面,不像阿里的Dubbo 框架只是专注于服务之间的治理。
Spring Cloud的社区热度非常好,问题修复也非常及时,未来会更加完善和稳定。
Spring Cloud也可以较好的兼容python、php等其他语言开发的微服务。因为采用RESTful。
Spring Cloud与Docker可以完美组合使用。
Spring Cloud 英文官网:http://projects.spring.io/spring-cloud/
Spring Cloud 中文文档:https://springcloud.cc/
2.3. Spring Boot的特性
Spring Boot是一个简化Spring使用的框架,可以使用少量的配置快速创建一个基于Spring的项目。Spring Boot主要有如下核心功能:
独立运行的Spring项目:Spring Boot可以以jar包的形式来运行,运行一个Spring Boot项目我们只需要通过java -jar xx.jar类运行。
内嵌Servlet容器:Spring Boot可以内嵌Tomcat,这样我们无需以war包的形式部署项目。
提供starter简化Maven配置:使用Spring或者SpringMVC我们需要添加大量的依赖,而这些依赖很多都是固定的,这里Spring Boot 通过starter能够帮助我们简化Maven配置。
自动配置Spring
提供生产就绪型功能,如指标,健康检查和外部配置
无代码生成和xml配置
3. 我们微服务架构约定
3.1. 技术栈
编程语言:Kotlin、JAVA、Python、PHP、SQL
构建工具:Gradle、Maven
数据库:MySQL、MongoDB、SQL Server
缓存:Redis
消息队列:RabbitMQ
IDE:IntelliJ IDEA、Eclipse
服务部署:Linux、Docker、Jenkins、Ansible
微服务框架:Spring Cloud
后端开发框架:Spring Boot
前端开发框架:VUE
3.2. Spring Cloud基础服务选型
配置:Spring Cloud Config,统一配置管理
总线:Spring Cloud Bus,可与Spring Cloud Config联合实现热部署
发现:Eureka,微服务的注册与发现
容错:Hystrix,断路器
网关:Zuul,提供动态路由,监控,弹性,安全等边缘服务的框架
负载:Ribbon,有多种负载均衡策略可供选择
调用:Feign,一种声明式、模板化的HTTP客户端
跟踪:Spring Cloud Sleuth, 日志收集工具包
会话:Spring-Session
3.3. 工具版本约定
名称 | 版本 | 备注 |
---|---|---|
Spring Boot | 2.0.0.M6 | - |
Spirng Cloud | Finchley.M4 | - |
Kotlin | 1.2 | 需保持最新 |
JAVA | 1.8.0_151 | — |
Gradle | 4.4.1 | 保持更新 |
Maven | 3.5.2 | - |
MySQL | 5.7.17 | - |
MongoDB | 3.6 | - |
PHP | 7.2.0 | — |
Python | 3.6.4 | — |
Redis | 4.0.1 | - |
Docker | 17.09 | - |
Jenkins | 2.89.2 | - |
CentOS | 7.4 | - |
SQL Server | 2008 | 历史系统 |
Ansible | 2.3.3.0-1 | - |
Tomcat | 8.5.24 | - |
3.4 微服务设计原则
单一职责:
每个服务都很小,且专注于做一件事情,并且把它做好。
至于要多小,有人喜欢100行以内,有人赞成1000行以内,数字并不是最重要的,只要团队觉得合适就好。轻量通讯
服务和服务之间通过轻量级的机制实现彼此间的通信。所谓轻量级通信机制,通常指基于语言无关、平台无关的这类协议,例如XML、JSON,而不是传统我们熟知的Java RMI或者.Net Remoting等。独立部署
每个服务都运行在一个独立的操作系统进程中,这意味着不同的服务能被部署到不同的主机上。康威定律
请读:https://yq.aliyun.com/articles/8611
将1968年由梅尔.康威提出:产品反映了制造该产品的组织结构。
http://img2.tbcdn.cn/L1/461/1/74ab78cb5db601e5db68adf61e6dc58f437df4e0
image_1c3fahngk6qfu5l1adm5undoj1s.png-254.1kB
第一定律:Communication dictates design. 组织沟通方式会通过系统设计表达出来。
第二定律:There is never enough time to do something right, but there is always enough time to do it over.
时间再多一件事情也不可能做的完美,但总有时间做完一件事情。
第三定律:There is a homomorphism from the linear graph of a system to the linear graph of its design organization.
线型系统和线型组织架构间有潜在的异质同态特性。
第四定律:The structures of large systems tend to disintegrate during development, qualitatively more so than with small systems.
大的系统组织总是比小系统更倾向于分解。
3.5 微服务拆分
微服务的拆分是个复杂问题,简单来说需要从横向和纵向多刀去拆。
3.5.1 横向拆分
按照不同的业务域进行拆分,例如订单、营销、风控、积分资源等,形成独立的业务领域微服务集群。
用户:
订单:
评论:
组织:
商品:
交易:
搜索:
营销:
消费者信息:
消费者分布:
消费者画像:
积分:
订货:
账户:
3.5.2 纵向拆分
把一个业务功能里的不同模块或者组件进行拆分。例如把公共组件拆分成独立的原子服务,下沉到底层,形成相对独立的原子服务层。这样一纵一横,就可以实现业务的服务化拆分。
短信:短信发送、记录、均衡、防漏、模板配置
文件:文件上传、缩略、下载、打包、数据库记录
微信:
日志:
支付:
快递:快递查询、状态订阅
地图:地址经纬度互转、距离计算、线路推荐
计划任务:统一的计划任务配置及调度
微信公众号配置:
微信自动回复:
3.6 架构升级步骤
独立构建微服务框架,将现有系统的核心功能分离出来做成基础微服务。如短信模板消息发送、微信模板消息发送、文件上传下载等;
利用这些基础微服务,解耦现有系统,修改其调用关系和依赖方式;
通过不断的微服务化,逐渐将现有系统分解成多个独立的微服务;
废弃现有的系统,使用全新构建的微服务来替代。
3.7. 微服务总体架构图
构件一套完整的微服务架构需要考虑许多问题,包括API Gateway、服务间调用、服务发现、服务容错、服务部署、数据调用等。基于SpringCloud构建微服务架构可以通过自动配置和绑定Spring环境和其他Spring编程模型来实现微服务。采用Spring Boot应用程序提供的集成功能,通过几个简单的注释,开发人员可以快速配置和启用应用程序中的常见功能模块,并使用久经考验的Netflix组件构建大型分布式系统。 提供的微服务功能模块包括服务发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载均衡(Ribbon)等。图2显示了采用Spring Cloud系列平台构建的微服务整体架构。
Spring Cloud架构图.png-141.5kB
基于Spring Cloud系统的微服务架构平台
服务发现是microservice基础架构的关键原则之一。服务注册中心采用Spring CloudNetflix的项目可以自动注册服务,也可以通过HTTP接口手动注册。默认情况下,Eureka使用客户端心跳来确定一个客户端是否活着。也可以另指定DiscoveryClient来传播当前SpringBoot Actuator的应用性能的健康检查状态。
统一的接入服务接口采用Spring Cloud的Zuul组件,实现内外有别的微服务调用。该组件也实现了服务路由功能。采用Spring Cloud Netflix来实现服务的限流和降级。
为实现服务的高可用,保证服务的容错和负载均衡,本平台可采用客户端负载均衡(Ribbon)来实现。
Spring Cloud Netflix的Hystrix熔断器组件,具有容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。为保证核心服务的稳定性,可采用Spring Cloud Netflix的Hystrix组件来实现服务的服务的容错、限流和降级等功能。
微服务的安全控制和权限验证可采用Spring CloudSecurity来实现。对于RESTful,可采用Spring Cloud的Feign 组件,这是一个声明Web服务客户端。这便得编写web服务客户端更容易,使用Feign 创建一个接口并对它进行注解,它具有可插拔的注解支持包括Feign注解与JAX-RS注解,Feign还支持可插拔的编码器与解码器
4. 微服务带来的新问题
一个服务拆成多大才合适?
多个微服务能否共享数据库?
每个微服务都有自己独立的数据库,那么后台管理的联合查询怎么处理?这是大家普遍遇到的一个问题。
有如下三种处理方案:
严格按照微服务的划分来做,微服务相互独立,各微服务数据库也独立,后台需要展示数据时,调用各微服务的接口来获取对应的数据,再进行数据处理后展示出来,这是标准的用法,也是最麻烦的用法。
将业务相关的表放到一个库中,将业务无关的表严格按照微服务模式来拆分,这样既可以使用微服务,也避免了数据库各种切换导致后台统计难以实现,是一个折中的方案。
数据库严格按照微服务的要求来切分,以满足业务高并发,实时或者准实时将各微服务数据库数据同步到 NoSQL 数据库中,在同步的过程中进行数据清洗,用来满足后台业务系统的使用,推荐使用 Mongodb、Hbase 等。
三种方案在不同的公司我都使用过,第一种方案适合业务较为简单的小公司;第二种方案,适合想在原有系统之上,慢慢演化为微服务架构的公司;第三种适合大型高并发的互联网公司。
如何与现有系统结合使用、并行开发、最终替代?
如何避免开发人员瞎子摸象、管中窥豹?
服务调用流,服务编排如何使用?
自动化运维的新挑战?
5. 结束语
微服务架构不是绝对的好,它有一定的使用场景,也有一定的落地难度。结合我们目前的情景和未来的发展来说,微服务架构是适合我们的,并且能够解决很多现有系统的诟病,但是落地的难度也是比较大的,特别是要结合已有的各个系统进行使用。
Spring Cloud作为稳定的微服务的一站式解决方案,能快速高效地搭建微服务架构,并且能够结合多语言开发,这个正是我们所需要的。
从今天开始,微服务的架构升级正式开始,一部分人直接开始参与,一部分人员间接来参与,但最终我们所有人都会在一个统一的架构上进行持续交付,从而更大的实现用户价值。
作者:孙振强
链接:https://www.jianshu.com/p/f564be0cdb54