1. 微服务基础知识
1.1 系统架构的演变
随着互联网的发展,网站应用的规模不断扩大,常规的应用架构已无法应对,分布式服务架构以及微服务架构势在必行,亟需一个治理系统确保架构有条不紊的演进。
1.1.1 单体应用架构
Web应用程序发展的早期,大部分web工程(包含前端页面,web层代码,service层代码,dao层代码)是将所有的功能模块,打包到一起并放在一个web容器中运行。
比如搭建一个电商系统:客户下订单,商品展示,用户管理。这种将所有功能都部署在一个web容器中运行的系统就叫做单体架构。
优点:开发简单,适用于小型应用
缺点:不易扩展,维护。代码耦合
1.1.2 垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率
优点:
- 解决高并发问题
- 针对不同的模块优化
- 方便水平扩展,容错
缺点:
- 系统间相互独立
- 重复开发工作
1.1.3 分布式SOA架构
1.1.3.1 什么是SOA
SOA 全称为 Service-Oriented Architecture,即面向服务的架构。它可以根据需求通过网络对松散耦合的粗粒度应用组件(服务)进行分布式部署、组合和使用。一个服务通常以独立的形式存在于操作系统进程中。
站在功能的角度,把业务逻辑抽象成可复用、可组装的服务,通过服务的编排实现业务的快速再生,目的:把原先固有的业务功能转变为通用的业务服务,实现业务逻辑的快速复用。
通过上面的描述可以发现 SOA 有如下几个特点:分布式、可重用、扩展灵活、松耦合
1.1.3.2 SOA架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求
优点:
- 抽取公共的功能为服务,提高开发效率
- 对不同的服务进行集群化部署解决系统压力
- 基于ESB/DUBBO减少系统耦合
缺点:
- 抽取服务的粒度较大
- 服务提供方与调用方接口耦合度较高
1.1.4 微服务架构
优点:
- 通过服务的原子化拆分,以及微服务的独立打包、部署和升级,小团队的交付周期将缩短,运维成本也将大幅度下降
- 微服务遵循单一原则。微服务之间采用Restful等轻量协议传输。
缺点:
- 微服务过多,服务治理成本高,不利于系统维护。
- 分布式系统开发的技术成本高(容错、分布式事务等)。
1.1.5 SOA与微服务的关系
SOA( Service Oriented Architecture
)“面向服务的架构”:他是一种设计方法,其中包含多个服务, 服务之间通过相互依赖最终提供一系列的功能。一个服务通常以独立的形式存在与操作系统进程中。各个服务之间通过网络调用。
微服务架构:其实和 SOA 架构类似,微服务是在 SOA 上做的升华,微服务架构强调的一个重点是“业务需
要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。
这些小应用之间通过服务完成交互和集成。
功能 | SOA | 微服务 |
---|---|---|
组件大小 | 大块业务逻辑 | 单独任务或小块业务逻辑 |
耦合 | 通常松耦合 | 总是松耦合 |
公司架构 | 任何类型 | 小型、专注于功能交叉团队 |
管理 | 着重中央管理 | 着重分散管理 |
目标 | 确保应用能够交互操作 | 执行新功能、快速拓展开发团队 |
1.2 分布式核心知识
1.2.1 分布式中的远程调用
在微服务架构中,通常存在多个服务之间的远程调用的需求。远程调用通常包含两个部分:序列化和通信协议。常见的序列化协议包括json、xml、hession、protobuf、thrift、text、bytes等,目前主流的远程调用技术有基于HTTP的RESTful接口以及基于TCP的RPC协议。
1.2.1.1 RESTful接口
REST,即Representational State Transfer的缩写,如果一个架构符合REST原则,就称它为RESTful架构。
资源(Resources)
所谓”资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。REST的名称”表现层状态转化”中,省略了主语。”表现层”其实指的是”资源”(Resources)的”表现层”。
表现层(Representation)
“资源”是一种信息实体,它可以有多种外在表现形式。我们把”资源”具体呈现出来的形式,叫做它的”表现层”(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的”.html”后缀名是不必要的,因为这个后缀名表示格式,属于”表现层”范畴,而URI应该只代表”资源”的位置。
状态转化(State Transfer)
访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生”状态转化”(State Transfer)。客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。
综合上面的解释,我们总结一下什么是RESTful架构:
- 每一个URI代表一种资源;
- 客户端和服务器之间,传递这种资源的某种表现层;
- 客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”。
1.2.1.2 RPC协议
RPC(Remote Procedure Call ) 一种进程间通信方式。允许像调用本地服务一样调用远程服务。RPC框架的主要目标就是让远程服务调用更简单、透明。RPC框架负责屏蔽底层的传输方式(TCP或者UDP)、序列化方式(XML/JSON/二进制)和通信细节。开发人员在使用的时候只需要了解谁在什么位置提供了什么样的远程服务接口即可,并不需要关心底层通信细节和调用过程。
1.2.1.3 区别与联系
比较项 | RESTful | RPC |
---|---|---|
通讯协议 | HTTP | 一般使用TCP |
性能 | 略低 | 较高 |
灵活度 | 高 | 低 |
应用 | 微服务架构 | SOA架构 |
HTTP相对更规范,更标准,更通用,无论哪种语言都支持http协议。如果你是对外开放API,例如开放平台,外部的编程语言多种多样,你无法拒绝对每种语言的支持,现在开源中间件,基本最先支持的几个协议都包含RESTful。
RPC 框架作为架构微服务化的基础组件,它能大大降低架构微服务化的成本,提高调用方与服务提供方的研发效率,屏蔽跨进程调用函数(服务)的各类复杂细节。让调用方感觉就像调用本地函数一样调用远端函数、让服务提供方感觉就像实现一个本地函数一样来实现服务。
1.2.2 分布式中的CAP原理
现如今,对于多数大型互联网应用,分布式系统(distributed system)正变得越来越重要。分布式系统的最大难点,就是各个节点的状态如何同步。CAP 定理是这方面的基本定理,也是理解分布式系统的起点。
CAP理论由 Eric Brewer 在ACM研讨会上提出,而后CAP被奉为分布式领域的重要理论。分布式系统的CAP理论,首先把分布式系统中的三个特性进行了如下归纳:
Consistency(一致性):数据一致更新,所有数据的变化都是同步的
Availability(可用性):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求
Partition tolerance(分区容忍性):某个节点的故障,并不影响整个系统的运行
通过学习CAP理论,我们得知任何分布式系统只可同时满足二点,没法三者兼顾,既然一个分布式系统无法同时满足一致性、可用性、分区容错性三个特点,所以我们就需要抛弃一样:
选择 | 说明 |
---|---|
CA | 放弃分区容错性,加强一致性和可用性,其实就是传统的关系型数据库的选择 |
AP | 放弃一致性(这里说的一致性是强一致性),追求分区容错性和可用性,这是很多分布式系统设计时的选择,例如很多NoSQL系统就是如此 |
CP | 放弃可用性,追求一致性和分区容错性,基本不会选择,网络问题会直接让整个系统不可用 |
需要明确一点的是,在一个分布式系统当中,分区容忍性和可用性是最基本的需求,所以在分布是系统中,我们的系统最当关注的就是A(可用性)P(容忍性),通过补偿的机制寻求数据的一致性
1.3 常见微服务框架
1.3.1 SpringCloud
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
1.3.2 ServiceComb
Apache ServiceComb 是业界第一个Apache微服务顶级项目, 是一个开源微服务解决方案,致力于帮助企业、用户和开发者将企业应用轻松微服务化上云,并实现对微服务应用的高效运维管理。其提供一站式开源微服务解决方案,融合SDK框架级、0侵入ServiceMesh场景并支持多语言。
1.3.3 ZeroC ICE
ZeroC IceGrid 是ZeroC公司的杰作,继承了CORBA的血统,是新一代的面向对象的分布式系统中间件。作为一种微服务架构,它基于RPC框架发展而来,具有良好的性能与分布式能力。
2. SpringCloud概述
2.1 微服务中的相关概念
2.1.1 服务注册与发现
服务注册:服务实例将自身服务信息注册到注册中心。这部分服务信息包括服务所在主机IP和提供服务的Port,以及暴露服务自身状态以及访问协议等信息。
服务发现:服务实例请求注册中心获取所依赖服务信息。服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去请求它们提供的服务。
2.1.2 负载均衡
负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。
2.1.3 熔断
熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。
2.1.4 链路追踪
随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要对一次请求涉及的多个服务链路进行日志记录,性能监控即链路追踪
2.1.5 API网关
随着微服务的不断增多,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信可能出现:
- 客户端需要调用不同的url地址,增加难度
- 再一定的场景下,存在跨域请求的问题
- 每个微服务都需要进行单独的身份认证
针对这些问题,API网关顺势而生。
API网关直面意思是将所有API调用统一接入到API网关层,由网关层统一接入和输出。一个网关的基本功能有:统一接入、安全防护、协议适配、流量管控、长短链接支持、容错能力。有了网关之后,各个API服务提供团队可以专注于自己的的业务逻辑处理,而API网关更专注于安全、流量、路由等问题。
2.2 SpringCloud的介绍
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
2.3 SpringCloud的架构
2.3.1 SpringCloud中的核心组件
Spring Cloud的本质是在 Spring Boot 的基础上,增加了一堆微服务相关的规范,并对应用上下文(Application Context)进行了功能增强。既然 Spring Cloud 是规范,那么就需要去实现,目前Spring Cloud 规范已有 Spring官方,Spring Cloud Netflix,Spring Cloud Alibaba等实现。通过组件化的方式,Spring Cloud将这些实现整合到一起构成全家桶式的微服务技术栈。
2.3.1.1 Spring Cloud Netflix组件
组件名称 | 作用 |
---|---|
Eureka | 服务注册中心 |
Ribbon | 客户端负载均衡 |
Feign | 声明式服务调用 |
Hystrix | 客户端容错保护 |
Zuul | API服务网关 |
2.3.1.2 Spring Cloud Alibaba组件
组件名称 | 作用 |
---|---|
Nacos | 服务注册中心 |
Sentinel | 客户端容错保护 |
2.3.1.3 Spring Cloud原生及其他组件
组件 | 作用 |
---|---|
Consul | 服务注册中心 |
Config | 分布式配置中心 |
Gateway | API服务网关 |
Sleuth/Zipkin | 分布式链路追踪 |
2.3.2 SpringCloud的体系结构
从上图可以看出Spring Cloud各个组件相互配合,合作支持了一套完整的微服务架构。
- 注册中心负责服务的注册与发现,很好将各服务连接起来
- 断路器负责监控服务之间的调用情况,连续多次失败进行熔断保护。
- API网关负责转发所有对外的请求和服务
- 配置中心提供了统一的配置信息管理服务,可以实时的通知各个服务获取最新的配置信息
- 链路追踪技术可以将所有的请求数据记录下来,方便我们进行后续分析
- 各个组件又提供了功能完善的dashboard监控平台,可以方便的监控各组件的运行状况
3. 案例搭建
使用微服务架构的分布式系统,微服务之间通过网络通信。我们通过服务提供者与服务消费者来描述微服务间的调用关系。
服务提供者:服务的被调用方,提供调用接口的一方
服务消费者:服务的调用方,依赖于其他服务的一方
我们以电商系统中常见的用户下单为例,用户向订单微服务发起一个购买的请求。在进行保存订单之前需要调用商品微服务查询当前商品库存,单价等信息。在这种场景下,订单微服务就是一个服务消费者,商品微服务就是一个服务提供者
3.1 数据库表
商品表
1 | CREATE TABLE `tb_product` ( |
3.2 搭建环境
3.2.1 创建父工程shop_parent
在IDEA中创建父工程 shop_parent 并引入坐标
1 | <parent> |
3.2.2 创建微服务工程模块
- 创建订单微服务模块 shop_service_order
- 创建商品微服务模块 shop_service_product
3.3 搭建商品微服务
3.3.1 编写实体类
1 | /** |
这里使用了 lombok简化实体类的开发
Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率
3.3.2 编写dao接口
1 | /** |
3.3.3 编写service层
service接口
1 | /** |
service实现类
1 | /** |
3.3.4 编写web层
1 | /** |
3.3.5 配置启动类
1 | /** |
3.3.6 配置yml文件
1 | server: |
3.4 搭建订单微服务
3.4.1 编写实体类
1 | /** |
3.4.2 编写web层
1 | /** |
3.5 服务调用
前文已经编写了两个基础的微服务,在用户下单时需要调用商品微服务获取商品数据。那应该怎么做呢?总人皆知商品微服务提供了供人调用的HTTP接口。所以可以再下定单的时候使用http请求的相关工具类完成,如常见的HttpClient,OkHttp,当然也可以使用Spring提供的RestTemplate
3.5.1 RestTemplate介绍
Spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。RestTemplate类的设计原则与许多其他Spring 模板类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。
RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。
考虑到RestTemplate类是为调用REST服务而设计的,因此它的主要方法与REST的基础紧密相连就不足为奇了,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()、postForObject()、put()和delete()等方法。
3.5.2 RestTemplate方法介绍
3.5.3 通过RestTemplate调用微服务
1、在 shop_service_order工程中OrderApplication启动类 中配置RestTemplate
1 | /** |
2、编写下订单方法
1 | /** |
3.5.4 硬编码存在的问题
至此已经可以通过RestTemplate调用商品微服务的RESTFul API接口。但是我们把提供者的网络地址(ip,端口)等硬编码到了代码中,这种做法存在许多问题:
- 应用场景有局限
- 无法动态调整
那么应该怎么解决呢,就需要通过注册中心动态的对服务注册和服务发现
4. 服务注册Eureka基础
4.1 微服务的注册中心
注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就这里找到服务的地址,进行调用。
4.1.1 注册中心的主要作用
服务注册中心(下称注册中心)是微服务架构非常重要的一个组件,在微服务架构里主要起到了协调者的一个作用。注册中心一般包含如下几个功能:
服务发现:
- 服务注册/反注册:保存服务提供者和服务调用者的信息
- 服务订阅/取消订阅:服务调用者订阅服务提供者的信息,最好有实时推送的功能
- 服务路由(可选):具有筛选整合服务提供者的能力。
服务配置:
- 配置订阅:服务提供者和服务调用者订阅微服务相关的配置
- 配置下发:主动将配置推送给服务提供者和服务调用者
服务健康检测
- 检测服务提供者的健康情况
4.1.2 常见的注册中心
4.1.2.1 Zookeeper
zookeeper它是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。简单来说zookeeper=文件系统+监听通知机制。
4.1.2.2 Eureka
Eureka是在Java语言上,基于Restful Api开发的服务注册与发现组件,Springcloud Netflix中的重要组件
4.1.2.3 Consul
Consul是由HashiCorp基于Go语言开发的支持多数据中心分布式高可用的服务发布和注册服务软件,采用Raft算法保证服务的一致性,且支持健康检查。
4.1.2.4 Nacos
Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。简单来说 Nacos 就是注册中心 + 配置中心的组合,提供简单易用的特性集,帮助我们解决微服务开发必会涉及到的服务注册与发现,服务配置,服务管理等问题。Nacos 还是 Spring Cloud Alibaba 组件之一,负责服务注册与发现。
最后我们通过一张表格大致了解Eureka、Consul、Zookeeper的异同点。选择什么类型的服务注册与发现组件可以根据自身项目要求决定。
组件名 | 语言 | CAP | 一致性算法 | 服务健康检查 | 对外暴露接口 |
---|---|---|---|---|---|
Eureka | Java | AP | 无 | 可配支持 | HTTP |
Consul | Go | CP | Raft | 支持 | HTTP/DNS |
Zookeeper | Java | CP | Paxos | 支持 | 客户端 |
Nacos | Java | AP | Raft | 支持 | HTTP |
4.2 Eureka的概述
4.2.1 Eureka的基础知识
Eureka是Netflix开发的服务发现框架,SpringCloud将它集成在自己的子项目spring-cloud-netflix中,实现SpringCloud的服务发现功能。
上图简要描述了Eureka的基本架构,由3个角色组成:
- Eureka Server
- 提供服务注册和发现
- Service Provider
- 服务提供方
- 将自身服务注册到Eureka,从而使服务消费方能够找到
- Service Consumer
- 服务消费方
- 从Eureka获取注册服务列表,从而能够消费服务
4.2.2 Eureka的交互流程与原理
图是来自Eureka官方的架构图,大致描述了Eureka集群的工作过程。图中包含的组件非常多,可能比较难以理解,我们用通俗易懂的语言解释一下:
- Application Service 相当于本书中的服务提供者,Application Client相当于服务消费者;
- Make Remote Call,可以简单理解为调用RESTful API;
- us-east-1c、us-east-1d等都是zone,它们都属于us-east-1这个region;
由图可知,Eureka包含两个组件:Eureka Server 和 Eureka Client,它们的作用如下:
- Eureka Client是一个Java客户端,用于简化与Eureka Server的交互;
- Eureka Server提供服务发现的能力,各个微服务启动时,会通过Eureka Client向Eureka Server进行注册自己的信息(例如网络信息),Eureka Server会存储该服务的信息;
- 微服务启动后,会周期性地向Eureka Server发送心跳(默认周期为30秒)以续约自己的信息。如果Eureka Server在一定时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(默认90秒);
- 每个Eureka Server同时也是Eureka Client,多个Eureka Server之间通过复制的方式完成服务注册表的同步;
- Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者。
综上,Eureka通过心跳检测、健康检查和客户端缓存等机制,提高了系统的灵活性、可伸缩性和可用性。
4.3 搭建Eureka注册中心
4.3.1 搭建Eureka服务中心
4.3.1.1 引入maven坐标
1 | <dependency> |
4.3.1.2 配置application.yml
1 | spring: |
4.3.1.3 配置启动类
1 | /** |
4.3.2 服务注册中心管理后台
打开浏览器访问 http://localhost:9000即可进入EurekaServer内置的管理控制台,显示效果如下
4.4 服务注册到Eureka注册中心
4.4.1 商品服务注册
4.4.1.1 引入maven坐标
pom文件中添加eureka client的相关坐标
1 | <dependencies> |
4.4.1.2 配置application.yml文件
添加Eureka Server的主机地址
1 | server: |
4.4.1.3 启动类添加服务注册注解
1 | /** |
从Spring Cloud Edgware版本开始, @EnableDiscoveryClient 或 @EnableEurekaClient 可省略。只需加上相关依赖,并进行相应配置,即可将微服务注册到服务发现组件上。
4.4.2 订单服务注册
4.4.2.1 引入maven坐标
pom文件中添加eureka client的相关坐标
1 | <dependencies> |
4.4.2.2 配置application.yml文件
添加Eureka Server的主机地址
1 | server: |
4.5 Eureka中的自我保护
微服务第一次注册成功之后,每30秒会发送一次心跳将服务的实例信息注册到注册中心。通知 Eureka Server 该实例仍然存在。如果超过90秒没有发送更新,则服务器将从注册信息中将此服务移除。
Eureka Server在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%,如果出现低于的情况(在单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定导致),Eureka Server会将当前的实例注册信息保护起来,同时提示这个警告。保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)
验证完自我保护机制开启后,并不会马上呈现到web上,而是默认需等待 5 分钟(可以通过eureka.server.wait-time-in-ms-when-sync-empty 配置),即 5 分钟后你会看到下面的提示信息:
如果关闭自我保护
通过设置 eureka.enableSelfPreservation=false 来关闭自我保护功能。
1 | #配置eureka server |
4.6 Eureka中的元数据
Eureka的元数据有两种:标准元数据和自定义元数据。
- 标准元数据:主机名、IP地址、端口号、状态页和健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。
- 自定义元数据:可以使用eureka.instance.metadata-map配置,符合KEY/VALUE的存储格式。这些元数据可以在远程客户端中访问。
在程序中可以使用DiscoveryClient 获取指定微服务的所有元数据信息
1 | /** |
5. 服务注册Eureka高级
5.1 Eureka Server 高可用集群
在上一个章节,实现了单节点的Eureka Server的服务注册与服务发现功能。Eureka Client会定时连接Eureka Server,获取注册表中的信息并缓存到本地。微服务在消费远程API时总是使用本地缓存中的数据。因此一般来说,即使Eureka Server发生宕机,也不会影响到服务之间的调用。但如果Eureka Server宕机时,某些微服务也出现了不可用的情况,Eureka Server中的缓存若不被刷新,就可能会影响到微服务的调用,甚至影响到整个应用系统的高可用。因此,在生成环境中,通常会部署一个高可用的Eureka Server集群。
Eureka Server可以通过运行多个实例并相互注册的方式实现高可用部署,Eureka Server实例会彼此增量地同步信息,从而确保所有节点数据一致。事实上,节点之间相互注册是Eureka Server的默认行为。
5.1.1 搭建 Eureka Server高可用集群
5.1.1.1 修改yml配置文件
1 | #指定应用名称 |
在配置文件中通过连字符(—)将文件分为三个部分,第一部分为应用名称,第二部分和第三部分是根据不同的profiles选项动态添加,可以在IDEA启动时进行激活配置
使用IDEA启动历次EurekaServerApplicaion分别激活eureka1和eureka2配置。访问http://localhost:9000和http://localhost:8000/。会发现注册中心 EUREKA-SERVER 已经有两个节点,并且registered-replicas (相邻集群复制节点)中已经包含对方。
5.1.2 服务注册到Eureka Server集群
如果需要将微服务注册到Eureka Server集群只需要修改yml配置文件即可
1 | eureka: |
5.2 Eureka中的常见问题
5.2.1 服务注册慢
默认情况下,服务注册到Eureka Server的过程较慢。SpringCloud官方文档中给出了详细的原因
大致含义:服务的注册涉及到心跳,默认心跳间隔为30s。在实例、服务器、客户端都在本地缓存中具有相同的元数据之前,服务不可用于客户端发现(所以可能需要3次心跳)。可以通过配置eureka.instance.leaseRenewalIntervalInSeconds (心跳频率)加快客户端连接到其他服务的过程。在生产中,最好坚持使用默认值,因为在服务器内部有一些计算,他们对续约做出假设。
1 | #配置Eureka |
5.2.2 服务节点剔除问题
默认情况下,由于Eureka Server剔除失效服务间隔时间为90s且存在自我保护的机制。所以不能有效而迅速的剔除失效节点,这对开发或测试会造成困扰。解决方案如下:
Eureka Server:
配置关闭自我保护,设置剔除无效节点的时间间隔
1 | #配置eureka server |
Eureka Client:
配置开启健康检查,并设置续约时间
1 | #配置Eureka |
5.2.3 监控页面显示ip
在Eureka Server的管控台中,显示的服务实例名称默认情况下是微服务定义的名称和端口。为了更好的对所有服务进行定位,微服务注册到Eureka Server的时候可以手动配置示例ID。配置方式如下
1 | #配置Eureka |
6. Eureka替换方案Consul
6.1 Eureka闭源的影响
6.1.1 Eureka闭源影响
在Euraka的GitHub上,宣布Eureka 2.x闭源。近这意味着如果开发者继续使用作为 2.x 分支上现有工作repo 一部分发布的代码库和工件,则将自负风险。
6.1.2 Eureka的替换方案
6.1.2.1 Zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
6.1.2.2 Consul
consul是近几年比较流行的服务发现工具,工作中用到,简单了解一下。consul的三个主要应用场景:服务发现、服务隔离、服务配置
6.1.2.3 Nacos
Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
6.2 什么是consul
6.2.1 consul 概述
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等)。使用起来也较 为简单。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。
Consul 的优势:
- 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是Paxos, 而 etcd 使用的则是 Raft。
- 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中心功能的支持。
- 支持健康检查。 etcd 不提供此功能。
- 支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。
- 官方提供 web 管理界面, etcd 无此功能。
- 综合比较, Consul 作为服务注册和配置管理的新星, 比较值得关注和研究。
特性:
- 服务发现
- 健康检查
- Key/Value 存储
- 多数据中心
6.2.2 consul与Eureka的区别
6.2.2.1 一致性
Consul强一致性(CP)
- 服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的节点都写入成功才认为注册成功
- Leader挂掉时,重新选举期间整个consul不可用。保证了强一致性但牺牲了可用性。
Eureka保证高可用和最终一致性(AP)
- 服务注册相对要快,因为不需要等注册信息replicate到其他节点,也不保证注册信息是否replicate成功
- 当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性。
6.2.2.2 开发语言和使用
eureka就是个servlet程序,跑在servlet容器中
Consul则是go编写而成,安装启动即可
6.2.3 consul的下载与安装
Consul 不同于 Eureka 需要单独安装,访问 Consul 官网下载 Consul 的最新版本,我这里是consul1.5x。根据不同的系统类型选择不同的安装包,从下图也可以看出 Consul 支持所有主流系统。
在linux虚拟中下载consul服务
1 | ## 从官网下载最新版本的Consul服务 |
启动consul服务
1 | ##已开发者模式快速启动,-client指定客户端可以访问的ip地址 |
启动成功之后访问: http://IP:8500 ,可以看到 Consul 的管理界面
6.3 consul的基本使用
Consul 支持健康检查,并提供了 HTTP 和 DNS 调用的API接口完成服务注册,服务发现,以及K/V存储这些功能。接下来通过发送HTTP请求的形式来了解一下Consul
6.3.1 服务注册与发现
6.3.1.1 注册服务
通过postman发送put请求到 http://192.168.142.128:8500/v1/catalog/register地址可以完成服务注册
1 | { |
6.3.1.2 服务查询
通过postman发送get请求到http://192.168.142.128:8500/v1/catalog/services查看所有的服务列表
通过postman发送get请求到http://192.168.142.128:8500/v1/catalog/service/服务名 查看具体的服务详情
6.3.1.3 服务删除
通过postman发送put请求到http://192.168.142.128:8500/v1/catalog/deregister删除服务
1 | { |
6.3.2 Consul的KV存储
可以参照Consul提供的KV存储的 API完成基于Consul的数据存储
含义 | 请求路径 | 请求方式 |
---|---|---|
查看key | v1/kv/:key | GET |
保存或更新 | v1/kv/:key | put |
删除 | /v1/kv/:key | DELETE |
- key值中可以带/, 可以看做是不同的目录结构。
- value的值经过了base64_encode,获取到数据后base64_decode才能获取到原始值。数据不能大于512Kb
- 不同数据中心的kv存储系统是独立的,使用dc=?参数指定。
6.4 基于consul的服务注册
6.4.1 案例准备
拷贝一份新的工程,起名为 shop_consul_parent ,并导入相关的子模块
6.4.1.1 修改pom文件
修改每个微服务的pom文件,添加SpringCloud提供的基于Consul的依赖
1 | <dependencies> |
6.4.2 配置服务注册
修改每个微服务的application.yml配置文件,添加consul服务发现的相关配置信息
1 | spring: |
6.5 基于consul的服务发现
由于SpringCloud对Consul进行了封装。对于在消费者端获取服务提供者信息和Eureka是一致的。同样使用 DiscoveryClient 完成调用获取微服务实例信息
6.6 consul高可用集群
此图是官网提供的一个事例系统图,图中的Server是consul服务端高可用集群,Client是consul客户端。consul客户端不保存数据,客户端将接收到的请求转发给响应的Server端。Server之间通过局域网或广域网通信实现数据一致性。每个Server或Client都是一个consul agent。Consul集群间使用了GOSSIP协议通信和raft一致性算法。
6.6.1 Consul的核心知识
6.6.1.1 Gossip协议
传统的监控,如ceilometer,由于每个节点都会向server报告状态,随着节点数量的增加server的压力随之增大。在所有的Agent之间(包括服务器模式和普通模式)运行着Gossip协议。服务器节点和普通Agent都会加入这个Gossip集群,收发Gossip消息。每隔一段时间,每个节点都会随机选择几个节点发送Gossip消息,其他节点会再次随机选择其他几个节点接力发送消息。这样一段时间过后,整个集群都能收到这条消息。示意图如下。
6.6.1.2 RAFT一致性算法
6.6.2 Consul 集群搭建
首先需要有一个正常的Consul集群,有Server,有Leader。这里在服务器Server1、Server2、Server3上分别部署了Consul Server。(这些服务器上最好只部署Consul程序,以尽量维护Consul Server的稳定)
服务器Server4和Server5上通过Consul Client分别注册Service A、B、C,这里每个Service分别部署在了两个服务器上,这样可以避免Service的单点问题。(一般微服务和Client绑定)在服务器Server6中Program D需要访问Service B,这时候Program D首先访问本机Consul Client提供的HTTP API,本机Client会将请求转发到Consul Server,Consul Server查询到Service B当前的信息返回
6.6.2.1 准备环境
服务器ip | consul类型 | Node(节点名称) | 序号 |
---|---|---|---|
192.168.74.101 | server | server-1 | s1 |
192.168.74.102 | server | server-2 | s2 |
192.168.74.103 | server | server-3 | s3 |
192.168.71.1 | client | clent-1 | s4 |
- Agent 以 client 模式启动的节点。在该模式下,该节点会采集相关信息,通过 RPC 的方式向 server 发送。Client模式节点有无数个,官方建议搭配微服务配置
- Agent 以 server 模式启动的节点。一个数据中心中至少包含 1 个 server 节点。不过官方建议使用 3 或 5 个 server 节点组建成集群,以保证高可用且不失效率。server 节点参与 Raft、维护会员信息、注册服务、健康检查等功能。
6.6.2.2 安装consul并启动
- 在每个consul节点上安装consul服务,下载安装过程和单节点一致。
1 | ##从官网下载最新版本的Consul服务 |
- 启动每个consul server节点
1 | #登录s1虚拟机,以server形式运行 |
-server: 以server身份启动。
-bootstrap-expect:集群要求的最少server数量,当低于这个数量,集群即失效。
-data-dir:data存放的目录,更多信息请参阅consul数据同步机制
-node:节点id,在同一集群不能重复。
-bind:监听的ip地址。
-client:客户端的ip地址(0.0.0.0表示不限制)
& :在后台运行,此为linux脚本语法
至此三个Consul Server模式服务全部启动成功
1 | ##在本地电脑中使用client形式启动consul |
(3) 每个节点加入集群
在s2,s3,s4 服务其上通过consul join 命令加入 s1中的consul集群中
1 | ##加入consul集群 |
(4) 测试
在任意一台服务器中输入 consul members查看集群中的所有节点信息
1 | ##查看consul集群节点信息 |
6.6.3 Consul 常见问题
6.6.3.1 节点和服务注销
当服务或者节点失效,Consul不会对注册的信息进行剔除处理,仅仅标记已状态进行标记(并且不可使用)。如果担心失效节点和失效服务过多影响监控。可以通过调用HTTP API的形式进行处理节点和服务的注销可以使用HTTP API:
- 注销任意节点和服务:/catalog/deregister
- 注销当前节点的服务:/agent/service/deregister/:service_id
如果某个节点不继续使用了,也可以在本机使用consul leave命令,或者在其它节点使用consul force-leave 节点Id。
6.6.3.2 健康检查与故障转移
在集群环境下,健康检查是由服务注册到的Agent来处理的,那么如果这个Agent挂掉了,那么此节点的健康检查就处于无人管理的状态。
从实际应用看,节点上的服务可能既要被发现,又要发现别的服务,如果节点挂掉了,仅提供被发现的功能实际上服务还是不可用的。当然发现别的服务也可以不使用本机节点,可以通过访问一个Nginx实现的若干Consul节点的负载均衡来实现。
7. 服务调用Ribbon入门
经过以上的学习,已经实现了服务的注册和服务发现。当启动某个服务的时候,可以通过HTTP的形式将信息注册到注册中心,并且可以通过SpringCloud提供的工具获取注册中心的服务列表。但是服务之间的调用还存在很多的问题,如何更加方便的调用微服务,多个微服务的提供者如何选择,如何负载均衡等。
7.1 Ribbon概述
7.1.1 什么是Ribbon
是 Netflixfa 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。在 SpringCloud 中,Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载。
在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取服务提供者的列表信息,并基于内置的负载均衡算法,请求服务
7.1.2 Ribbon的主要作用
7.1.2.1 服务调用
基于Ribbon实现服务调用, 是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助RestTemplate 最终进行调用
7.1.2.2 负载均衡
当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址
7.2 基于Ribbon实现订单调用商品服务
不论是基于Eureka的注册中心还是基于Consul的注册中心,SpringCloud Ribbon统一进行了封装,所以对于服务调用,两者的方式是一样的。
7.2.1 坐标依赖
在springcloud提供的服务发现的jar中已经包含了Ribbon的依赖。所以这里不需要导入任何额外的坐标
7.2.2 工程改造
7.2.2.1 服务提供者
1 | /** |
7.2.2.2 服务消费者
修改服务消费者 shop_service_order模块中的启动类OrderApplication ,在创建RestTemplate方法上添加 @LoadBalanced 注解
1 | /** |
1 | /** |
8. 服务调用Ribbon高级
8.1 负载均衡概述
8.1.1 什么是负载均衡
在搭建网站时,如果单节点的 web服务性能和可靠性都无法达到要求;或者是在使用外网服务时,经常担心被人攻破,一不小心就会有打开外网端口的情况,通常这个时候加入负载均衡就能有效解决服务问题。
负载均衡是一种基础的网络服务,其原理是通过运行在前面的负载均衡服务,按照指定的负载均衡算法,将流量分配到后端服务集群上,从而为系统提供并行扩展的能力。
负载均衡的应用场景包括流量包、转发规则以及后端服务,由于该服务有内外网个例、健康检查等功能,能够有效提供系统的安全性和可用性。
8.1.2 客户端负载均衡与服务端负载均衡
8.1.2.1 服务端负载均衡
先发送请求到负载均衡服务器或者软件,然后通过负载均衡算法,在多个服务器之间选择一个进行访问;即在服务器端再进行负载均衡算法分配
8.1.2.2 客户端负载均衡
客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,这是客户端负载均衡;即在客户端就进行负载均衡算法分配
8.2 基于Ribbon实现负载均衡
8.2.1 搭建多服务实例
修改 shop_service_product 的 application.yml 配置文件,已profiles的形式配置多个实例
1 | spring: |
分别启动两次服务器验证效果,并查看两个控制台发现已轮询的方式调用了商品服务
8.2.2 负载均衡策略
Ribbon内置了多种负载均衡策略,内部负责复杂均衡的顶级接口为com.netflix.loadbalancer.IRule
,实现方式如下
com.netflix.loadbalancer.RoundRobinRule
:以轮询的方式进行负载均衡。com.netflix.loadbalancer.RandomRule
:随机策略com.netflix.loadbalancer.RetryRule
:重试策略。com.netflix.loadbalancer.WeightedResponseTimeRule
:权重策略。会计算每个服务的权重,越高的被调用的可能性越大。com.netflix.loadbalancer.BestAvailableRule
:最佳策略。遍历所有的服务实例,过滤掉故障实例,并返回请求数最小的实例返回。com.netflix.loadbalancer.AvailabilityFilteringRule
:可用过滤策略。过滤掉故障和请求数超过阈值的服务实例,再从剩下的实力中轮询调用。
在服务消费者的application.yml配置文件中修改负载均衡策略
1 | #修改ribbon的负载均衡策略 服务名 - ribbon - NFLoadBalancerRuleClassName : 策略 |
策略选择:
- 如果每个机器配置一样,则建议不修改策略 (推荐)
- 如果部分机器配置强,则可以改为 WeightedResponseTimeRule
-------------本文结束感谢您的阅读-------------
本文标题: SpringCloud(一)
本文链接: https://wgy1993.gitee.io/archives/c069a57d.html
版权声明: 本作品采用 CC BY-NC-SA 4.0 进行许可。转载请注明出处!
