目录
Netflix Ribbon\Feign : 客户端负载均衡
一.应用架构的演变
随着互联的发展,使用互联网的人群越来越多,软件应用的体量越来越庞大和复杂,传统的单体应用可能不足以支撑大数据量以及高并发场景,应用的架构也随之进行演变,从最开始的单体应用架构到分布式(SOA)架构再到今天比较火的微服务架构,以及服务网格架构。
1. 单体应用架构
1.1. 什么是单体架构
简单来说我们以前传统的应用的就是单体架构,即所有的模块,组件等都在一个应用中应用最终打成一个(war,jar)包使用一个容器(Tomcat)进行部署,通常一个应用享用一个数据库。
在单体应用中我们通常把应用分为三个组成部分:持久层,业务层,表现层,这样的应用结构在项目初期业务较少的情况下没有任何问题,但是随着业务需求不断的增加要求单体应用中的业务逻辑,业务组件等日益扩张,应用将会变得越来越臃肿,往后的开发和维护就会变得特别麻烦,再加上越来越大访的问量,并发越来越高,面对海量的用户无论从应用性能还是从数据库方面都有吃不消的时候。所以单体应用在数据量,并发量到一定程度的时候一定会遇到瓶颈。
1.2. 单体架构的优缺点
当然单体应用在项目初期也有很多优势,主要有如下表现
-
易于开发 :架构简单,技术成本低
-
易于测试 :所有功能在一个项目,方便测试
-
易于部署 :一个Tomcat就可以实现部署,简单方便
随着项目规模日益变大,我们可以采用集群的手段来出来解决高并发,但包含了所有组成部分的单体应用终归是有许多不足,主要缺点如下
-
代码臃肿不方便开发维护(代码可读性差)
-
代码编译系统启动变慢
-
系统扩展性能变差(牵一发而动全身)
-
无法针对某一个业务做扩展(集群)
-
对大数据量,高并发量的处理不占优势
-
技术选型单一
-
模块/业务耦合度高
1.3.单体应用与集群
在单体架构中,为了提升应用的并发作业能力和防止应用的单节点故障(一个Tomcat挂了,应用就挂了)我们通常会对应用做集群,这里的集群指的是把应用进行复制多个相同的应用一起工作来提高作业能力,多个应用做的是相同的事情。就如同我们生活中的场景“收银”,一个收银台不足以支撑超市大量客户的结账流程,所以需要多个收银台同时工作,多个收银台都是做的相同的收银工作,这就是集群.
当我们的应用做了集群,那么就会存在多个应用节点,多个应用将会暴露多个访问地址(ip:port),那客户端是不知道该访问哪个应用节点的,这个时候我们就需要有一个请求分发的功能的组件(负载均衡器)将客户端的请求相对平均的分发多个应用节点上,这就是负载均衡,这个做请求分发的组件就是负载均衡器
当我们的单体应用没办法支撑较高的并发请求时,我们可以对应用做集群,同时加入负载均衡器来提升应用的作业能力,甚至我们也可以在数据库层也做集群(如主从复制),这样的架构有一定的并发处理能力,也能满足一定的复杂业务需求,但是就应用本身而言任然是单体结构,仍然有其不足之处,如:
-
项目本身任然是单体,代码依然臃肿
-
面对海量数据数据库会成为性能瓶颈(需要分库分表)
-
持续交互能力差,代码臃肿,业务复杂,开发维护时间长,新人入手成本高。
所以当单体应用不能满足复杂的业务和海量数据的系统时,我们需要考虑其他的架构方式。
2. 分布式与SOA
2.1.分布式架构
我们知道,单体应用包含了整个项目的所有代码和服务逻辑,也就是说一个Tomcat需要把整个系统跑起来,那么Tomcat总有处理不过来的时候,我们是否可以为Tomcat减轻一些压力呢?当然可以。我们拿生活中的案例“厨师炒菜”,来说,当饭店规模小的时候我们一个厨师就可以完成所有厨房的工作如“洗菜”,“切菜”,“炒菜”三件事情,当饭店规模增加,一个厨师就忙不过来,这个时候可能要再招聘两个厨师,然后进行分工,厨师A负责洗菜,厨师B负责切菜,厨师C负责炒菜,这样一来每个厨师的压力减轻,并且每个厨师就只需要专注一件事情即可。
将上面的案例映射到我们的应用程序中也是一样的道理,当一个Tomcat负担不起系统中的所有业务的时候,我们可以按照业务把应用进行拆分成多个小的应用,每个小应用都用一个Tomcat去运行,每个小应用都是单体架构,每个应用只需要关系自己的业务即可,应用之间通过API相互调用,如图:
当然如果某个子系统压力依然很大,可以单独对该子系统再做集群,所以分布式和集群并不冲突。
总结一下什么是分布式 :分布式就是将应用按照业务进行拆分成多个子应用,多个子应用部署在不同的服务器中,多个子应用组成一个完整的系统,所有的子系统一起工作相互通信相互协调才能完成最终的业务流程,缺一不可,简单理解:“多个人在一起做不同的事情,多人和在一起才是一件完整的事情,有点0.5+0.5=1的感觉”。
2.2.面向服务的架构SOA
SOA是面向服务的架构,它的思想是每个子应用可以通过网络通信协议向其他子应用提供服务或者消费服务,SOA也是分布式架构,我们可以简单的理解为SOA把分布式架构划分成表示层和服务层,服务层中包含了业务逻辑和相关流程,只需要对外暴露服务即可,表现层负责处理和页面的交互。这样的划分好处在于系统之间调用的方便性,如用户子系统只需要调用订单子系统的服务层即可完成应用之间的通信。这样的结构划分提高了应用的重用性,业务逻辑也变得可组合。如图:
SOA架构中有重要的两个角色,服务消费者(Consumer)和服务提供者(Provider)即服务调用者和服务被调用者,这样的架构优点有:
-
模块拆分,使用API通信,降低模块之间的耦合度
-
项目拆分多个子应用,每个子应用业务简单,代码简单,方便维护开发。
-
不同技术人员可以负责不同的子应用
-
提高服务之间的重用性,业务逻辑可组合。
其缺点在于:
-
服务之间的API接口开发增加了工作量,
-
SOA服务之间的网络通信调用对性能有一定的影响(尽管很小)
-
相对于单体应用来说,技术,人力成本较高。
-
部署和运维相对麻烦
3. 微服务架构
3.1. 什么是微服务
微服务架构可以认识是在SOA架构上的一种发展,最早由“Martin Fowler”提出:
就目前而言,对于微服务业界并没有一个统一的、标准的定义(While there is no precise definition of this architectural style ) 。但通常而言,
微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分成一组小的服务,每个服务运行独立的自己的进程中,服务之间互相协调、互相配合,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API )
。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务。可以使用不同的语言来编写服务,也可以使用不同的数据存储。
我们从这段描述中可以看出,微服务架构和SOA架构很像,总体来说,微服务就是把单一应用进行细粒度的拆分成多个小(微)的服务相,每个服务独立运行,每个服务只需要专注一个业务即可,并且每个服务都可以有自己的数据库(分库),服务之间互协调配合完成整个系统的业务,我们用一个图来理解微服务架构:
我们总结一下微服务有如下的特点 :
-
由多个服务组成完整的系统
-
每个服务都是独立的,有自己的进程
-
服务之间使用HTTP协议通信
-
不同的服务可以使用不同的编程语言
-
不同的服务的数据库可以多样化选择
-
微服务是一个分布式系统
3.2. 微服务的优缺点
在项目规模较大的时候,相对于单体应用来说,微服务具备很多优势,主要体现在如下方面:
-
单个服务业务简单,代码简单方便开发维护
-
服务之间无耦合,服务之间升级维护互不影响
-
轻量级HTTP通信机制,使得的不同的服务可以采用不同的编程语言
-
微服务有极强的扩展能力,业务量大的服务可以再次拆分服务,也可以进行集群部署,剔除服务也很方便
-
更大的系统负载能力和容错能力(集群)
-
对于开发人员来说,通常只需要关注单一服务,新员工上手也比较快
-
微服务架构对现在流行的敏捷开发支持优化
凡是都有双面性,微服务展示出了他都优势之处,同时也有其不足的地方,主要体现如下方面:
-
分布式事务 :服务通信机制增加了事务的复杂性,架构师要选择合适的分布式方案(CAP理论)
-
部署麻烦 :微服务众多,部署麻烦,需要借助容器技术和自动化部署工具,这又增加了开发人员的学习成本。
-
技术成本高 :微服务架构本身比较复杂,技术成本高,开发人员需要花更多的时间学习相关技术。
-
服务通信对性能的损耗 : 微服务架构一定要考虑服务通信延迟对服务调用性能的损耗问题,开发人员需要选择合适的通信方式解决这一问题。
3.3.如何选型
虽然微服务有诸多好处,但是不是任何系统都适合用微服务架构来开发,在项目规模不大的情况下单体应用性能表现良好,当项目规模较大,用户体量,并发较大的时候,微服务总体性能占优势,所以我们应该根据项目类型以及项目规模来决定应用架构的选型,如大型电商,物流,售票等系统我们可以选择使用微服务架构,对于中小型的企业级应用我们依然可以选择单体架构。
总结:中小型项目,选择单体 , 大型项目选择微服务。
二.SpringCloud介绍
1. 认识SpringCloud
1.1.SpringCloud基本概念
Spring cloud是一个基于Spring Boot实现的服务治理工具包
,用于微服务架构中管理和协调服务的
。Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等
,都可以用Spring Boot的开发风格做到一键启动和部署。通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。有了SpringCloud之后,让微服务架构的落地变得更简单。
1.2. SpringCloud常用组件
当我们的项目采用微服务架构之后就会引发一些列的难题需要去解决,如众多微服务的通信地址应该如何管理,微服务之间应该使用何种方式发起调用,微服务故障该如何处理,众多微服务的配置文件如何集中管理等等,SpringCloud为这一系列的难题提供了相应的组件来解决,下面我们简单来理解一下SpringCloud最核心的几大组件如如下:
Netflix Eureka
当我们的微服务过多的时候,管理服务的通信地址是一个非常麻烦的事情,Eureka就是用来管理微服务的通信地址清单的,有了Eureka之后我们通过服务的名字就能实现服务的调用。
Netflix Ribbon\Feign : 客户端负载均衡
Ribbon和Feign都是客户端负载均衡器,它的作用是在服务发生调用的时候帮我们将请求按照某种规则分发到多个目标服务器上,简单理解就是用来解决微服务之间的通信问题。
Netflix Hystrix :断路器
微服务的调用是非常复杂的,有的时候一个请求需要很多的微服务共同完成,那么一旦某个服务发生故障,导致整个调用链上的微服务全都出现异常,甚至导致整个微服务架构瘫痪。Hystrix就是用来解决微服务故障,保护微服务安全的组件。
Netflix Zuul : 服务网关
zuul作为服务网关,我们可以把它看作是微服务的大门,所有的请求都需要经过zuul之后才能到达目标服务,根据这一特性,我们可以把微服务公共的是事情交给zuul统一处理,如:用户鉴权,请求监控等。
Spring Cloud Config :分布式配置
微服务架构中的服务实例非常的多,服务的配置文件分散在每个服务中,每次修改服务的配置文件和重新服务实例都是一个很麻烦的工作,Spring Cloud Config作为分布式配置管理中心就是用来统一的管理服务的配置文件。
Spring Cloud Bus : 消息总线
消息总线是在微服务中给各个微服务广播消息的一个组件,我们使用消息总线构建一个消息中心,其他微服务来接入到消息中心,当消息总线发起消息,接入的微服务都可以收到消息从而进行消费。
Spring Cloud sleuth :微服务链路追踪
当我们的应用采用微服务架构之后,后台可能有几十个甚至几百个服务在支撑,一个请求请求可能需要多次的服务调用最后才能完成,链路追踪的作用就是来监控维护之间的调用关系,让程序员方便直观的感受到一个请求经历了哪些微服务,以及服务的请求时间,是否有异常等。
1.3.SpringCloud的版本
SpringCloud是基于SpringBoot的,所以两者的jar包都需要导入,需要注意的是SprinbCloud的版本需要和SpringBoot的版本兼容,本文章采用的SpringBoot版本是2.0.5.RELEASE , SpringCloud的版本是Finchley.SR1。下面是版本兼容图:
Release Train | Boot Version |
---|---|
Hoxton | 2.2.x |
Greenwich | 2.1.x |
Finchley | 2.0.x |
Edgware | 1.5.x |
Dalston | 1.5.x |
2.服务通信协议
在微服务中服务间通过网络进行通信,那么服务间的远程调用方式有哪些呢?
2.1.RPC
RPC(Remote Produce Call)远程过程调用,类似的还有RMI。自定义数据格式,基于原生TCP通信,速度快,效率高。早期的webservice,现在热门的dubbo,都是RPC的典型
2.2.Http
Http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议。也可以用来进行远程服务调用。缺点是消息封装臃肿。 现在热门的Rest风格,就可以通过http协议来实现
我们可以认为SpringCloud就是基于Http协议实现服务之间的通信。
2.2.如何选择
其实我们并不需要刻意去选择该使用RPC或者是Http,如果架构师选择Dubbo作为微服务开发框架,通信方式自然就是RPC,当架构师选择了SpringCloud作为微服务开发框架,那么通信方式自然就是基于Http协议,当然&#