SpringCloud:
SpringCloud是关注全局的微服务协调整理框架,他将SpringBoot开发的一个个单体服务整合并管理起来,为各个服务之间提供:配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务。SpringCloud离不开SpringBoot,属于依赖关系,SpringBoot专注于快速,方便开发单个个体微服务,SpringCloud关注全局的服务治理框架。
传统的互联网架构:
SpringClould更加完善:
相比较Dubbo而言,SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。降低了自身的服务调用性能,提高了灵活性和兼容性,完美的融合Spring其他的产品:
Springboot配置文件类型:
bootstrap.yml:系统级别的配置
application.yml:用户级别的配置
Eureka配置:
https://www.springcloud.cc/spring-cloud-netflix.html
SpringCloud官方文档中文版:
https://www.springcloud.cc/spring-cloud-dalston.html
SpringCloud中文版:
https://www.springcloud.cn/
SpringCloud版本选择(现在的版本已经到H):
SpringCloud使用:
创建maven工程,导入附录依赖,删除src作为Springcloud的父级应用:然后在父级应用上,右键创建maven工程:
创建一个数据库,在schemas中选中需要创建的数据库:
创建table:
在table中,配置表的字段和信息:
在idea添加信息到数据库:
创建api微服务存放Dept实体类:
创建微服务提供者8081(写太多微服务,命名加上端口号):
application.yml:
Mybatis-config.xml:
DeptMapper.xml:
DeptDao:
DeptServiceImpl:
DeptController:
创建一个消费者类(客户端80):
创建生产RestTemplate的Bean对象
消费者类的控制器:
1.导入依赖 2.编写配置文件
3.开启这个功能 @EnableXXXX 4.配置类
什么是Eureka:
Eureka时候Netflix的一个子模块,也是核心模块之一,是一个基于REST的服务,用于定位服务,有了服务发现与注册,只需要使用服务标识符,就可以访问到服务,而不需要修改服务调用的配置文件了,功能类似于Dubbo的注册中心,比如Zookeeper。
使用Eureka的客户端连接到EurekaServer并维持心跳连接。这样系统的维护人员就可以通过EurekaServer来监控系统中各个微服务是否正常运行,SpringCloud的一些其他模块(比如Zuul)就可以通过EurekaServer来发现系统中的其他微服务,并执行相关的逻辑。
Eureka的两个组件:
Eureka Server提供服务注册服务,各个节点启动后,会在EurekaServer中进行注册,这样Eureka Server中的服务注册表中将会村粗所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个ava客户端,用于简化EurekaServer的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除掉(默认周期为90秒)
三大角色:
Eureka Server:提供服务的注册于发现。Zookeeper
Service Provider:将自身服务注册到Eureka中,从而使消费方能够找到。
Service Consumer:服务消费方从Eureka中获取注册服务列表,从而找到消费服务。
创建Eureka的服务端:
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eureka-serverartifactId>
<version>1.4.6.RELEASEversion>
dependency>dependencies>-->
Application.yml:
server:
port: 7001
#Eureka配置
eureka:
instance:
hostname: localhost #Eureka服务端的实例名称
client: register-with-eureka: false #表示是否向eureka注册中心注册自己
fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
service-url: #监控页面,重写默认网址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
启动项Eureka服务端启动类@EnableEurekaServer:
使用Eureka注册注解(8001服务提供者):
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
<version>1.4.6.RELEASEversion>
dependency>
编写Eureka配置文件:
#Eureka的配置,服务注册到哪里
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
instance:
instance-id: springcloud-provider-dept8001 #修改Eureka上的默认描述信息
开启添加到Eureka注册中心这个功能@EnableEurekaClient:
注册成功图(Application:就是我们配置的Spring的名字,Status就是instanceid名字):
添加监控信息(8001服务提供者):
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>-->
编写监控配置文件:
#info配置info:
app.name: dcits-springboot
company.name: blog.chenglin.com
点击status这个链接,可以访问监控信息
Eureka拥有自我保护机制:
某时某刻一个微服务不可以用了,eureka不会立刻清理,依旧会对该服务的信息进行保存。
·默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka之间无法正常通行,以上行为可能变得非常危险了--因为微服务本身其实是健康的,此时本不应该注销这个服务。Eureka通过自我保护机制来解决这个问题--当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,EurekaServer就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该EurekaServer节点会自动退出自我保护模式。
·在自我保护模式中,EurekaServer会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该EurekaServer节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话:好死不如赖活着
·综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮和稳定
在SpringCloud中,可以使用eureka.server.enable-se1f-preservation = false 禁用自我保护模式
扩展想要了解一个服务信息是干嘛的(在启动类中添加@EnableDiscoveryClient):
然后在配置文件中注册DiscoveryClient:并且获取微服务信息:
可以得到输出:
Eureka的集群:
在原先eureka7001的基础上,创建7002和7003配置不变只改端口号:
集群的作用,就是让三个注册中心,互相相连,一个中心崩了,另外两个会支持注册中心不崩溃。
配置关联的域名映射( C:\Windows\System32\drivers\etc\hosts ):
集群关联,在7001中关联7002和7003,同理7002和7003相互关联另外两个:
server: port: 7001
#Eureka配置
eureka:
instance:
hostname: eureka7001.com #Eureka服务端的实例名称
client:
register-with-eureka: false #表示是否向eureka注册中心注册自己
fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
service-url:
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
在8001中编写配置文件:
#Eureka的配置,服务注册到哪里
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-provider-dept8001
访问其中一个盘配置中心可以看到集群关联的:
在任何一个集群关联的Eureka中都可以挂载注册(关闭其中一个服务不影响集群组):
CAP原则:
C:强一致性
A:可用性
P分区容错性
CAP的三进二:CA、AP、CP
对比ACID:
A:原子性
C:一致性
I:隔离性
D:持久性
CAP理论核心:
·一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,
·根据CAP原理,将NoSQL分成了满足CA原则,满足CP原则和满足AP原则三大类:
·CA:单点集群,满足一致性,可用性的系统,通常可扩展性较差
·CP:满足一致性,分区容错性的系统,通常性能不是特别高
·AP:满足可用性,分区容错性的系统,通常可能对一致性要求低一些
作为服务注册中心,Eureka比zookeeper好在哪里?
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A (可用性)、Р(容错性)。由于分区容错性P在分布式系统中是必须要保证的,因此我们只能在A和C之间进行权衡。
Zookeeper保证的是CP:
可以容忍注册中心返回的是几分钟以前的注册信息。但是不能接受服务器down掉,没有服务的保护机制,一旦down掉服务注册中心就不可用。拥有自己的master节点,当master节点因为网络故障等失去联系,剩余的节点会重新进行选举,但是选举的时间太长。虽然能够恢复,但是漫长的选举时间用户体验不好。
Eureka保证的是AP:
Eureka的诞生尼补了Zookeeper的弊端,在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保住注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的工作,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
1.Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
2.Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点依然可用)
3.当网络稳定时,当前实例新的注册信息会被同步到其他节点中
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪
Ribbon:
什么是Ribbon:
·Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具
·简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将NetFlix的中间层服务连接在一起。Ribbon的客户端组件提供一系列完整的配置项如:连接超时、重试等等。简单的说,就是在配置文件中列出LoadBalancer(简称LB:负载均衡)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法!
Ribbon能干什么?:
·LB,即负载均衡(Load Balance),在微服务或分布式集群中经常用的一种应用。
·负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。
·常见的负载均衡软件有Nginx,Lvs等等
·SpringCloud中均给我们提供了负载均衡,负载均衡算法可以自定义。
负载均衡简单分类:
·集中式LB:
·即在服务的消费方和提供方之间使用独立的LB设施,如Nginx:反向代理服务器!由该设施负责把访问请求通过某种策略转发至服务的提供方!
·进程式LB
·将LB逻辑集成到消费方,消蒉方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器。
·Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址!
Ribbon的使用:
在客户端导入ribbon依赖:ribbon需要从服务中心获取数据判断,所以需要配置Eureka
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-ribbonartifactId>
<version>1.4.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
<version>1.4.6.RELEASEversion>dependency>
填写Ribbon配置:
server:
port: 80
#Eureka配置
eureka:
client:
register-with-eureka: false #不想Eureka中注册自己
service-url: #负债均衡开启后在下面三个网址中通过服务类名称进行访问
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,
http://eureka7003.com:7003/eureka/
配置负债均衡实现在客户端config中RestTemplate(注解@LoadBalanced):
在控制器中,使用Ribbon来动态写入地址,写入的地址是注册中心中的服务类名称:
基于服务名,访问成功:
轮询负载均衡测试(创建复制8001创建8002服务端):
启动Eureka,启动8001,启动8002,在Eureka注册成功图:
启动客户端80.然后通过客户端进行访问,Ribbon会根据自己的算法轮询判断:
启将负载轮询,改为随机,重写myRule,返回一个RandomRule()方法:
Ribbon自定义算法:
在启动类添加(@RibbonClient(name=”spring的名字”),指定自己创建的组件包):
创建一个组件包,将随机的Bean对象移动到这:
进入RandomRule()方法,复制方法为LinRandomRule修改算法:
Feign负载均衡:
feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。SpringCloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。
Feign能干什么?
·Feign在编写javahttp客户端变的更加容易
·在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(类似于以前Dao接口上标准的Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可)
Feign集成了Ribbon
·利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而且简单的实现了服务调用。
Feign的使用(面向接口编程):
导入依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-feignartifactId>
<version>1.4.6.RELEASEversion>
dependency>-->
创建Feign接口(注解@Component可以将对象注入到Spring当中):
使用Feign注解:
Feign启动项:
读取成功:
Hystrix服务熔断:
网站:https://github.com/Netflix/Hystrix/wiki
分布式面临的问题(服务雪崩):
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败!
服务雪崩:
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出"、如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应"。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒中内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
我们需要·弃车保帅·
什么是Hystrix:
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩
Hystrix作用:
·服务降级
·服务熔断
·服务限流
·接近实时的监控等
服务熔断是什么(避免整个微服务出现异常导致整个应用报错):
熔断机制是对应雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息-=-。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
如何使用hystrix服务熔断:
导入hystrix依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-hystrixartifactId>
<version>1.4.7.RELEASEversion>
dependency>
添加Hystrix方法,使用Hystrix注解调用:
Hystrix启动类:
测试(当数据库没有id值,进入Hystrix方法,使服务不down掉):
服务降级:
什么是服务降级:
服务降级是指当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。说白了,就是尽可能的把系统资源让给优先级高的服务。
指定熔断降级降级:
通过工厂调用接口进行服务降级
编写配置信息( #开启降级feign.hystrix):
feign:
hystrix:
enabled: true
运行后关闭服务器(降级成功):
服务熔断:服务端某个服务超时或者异常,引起熔断保险丝
服务降级:客户端从整体网站请求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用~此时在客户端,我们可以准备一个FallbackFactory,返回一个默认的值(缺省值),整体服务的水平下降了,但是好歹能用,比直接挂掉要强~
Hystrix监控面板(dashboard):
首先导入依赖(创建监控客户端,复制80依赖后加入如下两个依赖):
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-hystrixartifactId>
<version>1.4.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-hystrix-dashboardartifactId>
<version>1.4.7.RELEASEversion>
dependency>-->
然后编写端口等配置信息:
server:
port: 9001
hystrix:
dashboard:
proxy-stream-allow-list: localhost
编写监控页面启动类(开启监控注解 @EnableHystrixDashboard):
在服务端,想要监控信息的流,需要添加一个Servlet创建Bean对象,创建Hystrix流监控,并且传递监控Url信息,然后开启对熔断器的支持( @EnableCircuitBreaker):
启动7001,8003,9001,在http://localhost:8003/actuator/hystrix.stream这上面我们可以捕捉到8003服务器上面的get请求信息:
测试启动是否成功,在http://localhost:9001/hystrix上填写需要监控页面的信息:
得到结果:
实心圆的健康程度绿<黄<橙<红 递减 流量越大圆越大,其他参数表示:
Zuul路由网关:
什么是Zuul:
·Zull包含了对请求的路由(用来跳转的)和过滤两个最主要功能:
·其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。
·Zuul服务最终还是会注册进 Eureka
使用Zuul:
创建Zuul工程导入Zuul依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zuulartifactId>
<version>1.4.7.RELEASEversion>
dependency>-->
编写配置信息:
server:
port: 9527
spring:
application:
name: springcloud-zuul#Eureka的配置,服务注册到哪里
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,
http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-zuul-9527
prefer-ip-address: true
#info配置
info:
app.name: dcits-springboot
company.name: blog.chenglin.com
添加启动项:
注册到Eureka:
通过路由网关(微服务名称),访问:
通过Zuul隐藏微服务的名称:
在9527下添加配置信息,通过mydept访问,隐藏微服务的名称:
zuul:
routes:
mydept.serviceId: springcloud-provider-dept
mydept.path: /mydept/**
ignored-services: springcloud-provider-dept #不能够通过这个路径访问,忽略这个名称
通过路由网关(隐藏微服务名称),访问:
发表项目的时候,利用通配符进行隐藏,并且指定访问前缀:
zuul:
routes:
mydept.serviceId: springcloud-provider-dept
mydept.path: /mydept/**
ignored-services: "*" #不能够通过这个路径访问,忽略,隐藏全部
prefix: /lin #统一规定,公共的访问前缀/lin
通过路由网关指定访问前缀,访问:
SpringCloudConfig分布式配置:
什么是springCloudConfig分布式配置中心(在配置中心提供了configServer来解决在大型项目中需要修改无数个配置文件的问题)将配置放github上:
spring cloud config为微服务架构中的微服务提供集中化的外部支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置。
spring cloud config分为服务端和客户端两部分。
服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理。并且可用通过git客户端工具来方便的管理和访问配置内容。
SpringCloud config分布式配置中心能干什么:
·集中式管理配置文件
·不同环境不同配置,动态化的配置更新,分环境部署,比如/dev /test /prod /beta/release
·运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
·当配置发生变动时,服务不需要重启,即可感知到配置的变化,并应用新的配置
·将配置信息以REST接口的形式暴露
Config服务端连接git:
创建config服务端:
导入依赖(除此之外,海域要web和eureka依赖等):
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-serverartifactId>
<version>2.1.1.RELEASEversion>
dependency>
编写配置信息(通过config-server可以连接到git,访问其中的资源以及配置):
server:
port: 3344
spring:
application:
name: springcloud-config-server #连接远程仓库
cloud:
config:
server:
git:
uri: https://github.com/*/springcloud-config.git # https不是git
创建启动类:
HTTP服务通过如下访问git上面的内容:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
访问到git:
创建config客户端:
导入依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
<version>2.1.1.RELEASEversion>
dependency>
编写配置信息(bootstrap.yml系统级别的配置,application.yml用户级别配置):
bootstrap.yml:
#系统级别的配置 bootstrap.yml
spring:
cloud:
config:
name: config-client #需要从git上读取资源的名称,不需要后缀
profile: dev
label: master
uri: http://localhost:3344
application.yml:
#用户级别的配置 application.yml
spring:
application:
name: springcloud-config-client-3355
创建客户端启动类:
编写客户端控制器:
启动客户端和服务端,访问config-clientprofile: dev的配置,得到结果:
重启动客户端,更改系统级别配置文件config-clientprofile: test的配置,得到结果:
得到结果,我们可以把配置,放到远程;