springCloud-分析+总结
一.Eureka
eureka是一个分布式微服务的架构一个框架,eureka是netflix的一个开源框架,主要用于服务注册与发现.
当项目启动时,生产者服务会将自己的服务信息注册到注册中心,然后消费者又会从注册中心再拉取最新的服务列表,
什么是注册中心?
1.在启动每一个服务的时候,会把自己的信息注册到注册中心中,并且会拉取一份最新的服务列表
2.每隔30秒会给注册中心发送心跳包,确保它还活着,并且会拉取一份最新的服务列表
3.如果连续3次,注册中心都没有接收到心跳包,那么它会把这个节点从注册中心的服务列表中去掉
Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等.
在真实环境当中,基本不会出现大批量的服务器宕机,
比如:网络波动,注册中心连续3次都没有接受到心跳包,如果没哟自我保护机制,那么这些节点就直接被踢出了
但是这些节点仅仅是因为网络波动导致,并不是真的是服务器的问题,所以不应该去除至少在15分钟之内这些节点都是安全的,如果这时有消费者访问这些有问题的节点,可以通过后台设置重试次数或者降级处理,一旦网络恢复了就可以恢复正常运行了
二.Ribbon
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。
自己的理解:
首先ribbon是netflix的一个开源框架,主要是用来做远程调用的,使用的是restTemplate的方式进行远程调用(URLconnection),使用时需要引入依赖,(如果已经引入eureka的依赖,这个则不用引入了,因为eureka的依赖自带ribbon的依赖)
其次,在消费者的服务的启动类中将restTemplate这个对象交给spring管理,同时贴上@loadBalanced这个注解,表示使用ribbon的负载均衡
最后在消费者的controller中使用Resttemplate的方式将生产者的服务名称作为url的一部分传进参数中,ribbon底层会从本地列表服务中找到或者匹配到url中所写生产者的服务名称.然后替换成对应的ip和端口,最后根据拼接好的url地址发送get异步请求,获取数据
三:Feign
由于ribbon使用起来比较麻烦,需要建restTemplate,使用拼接url的方式进行远程调用,不方便,现在出现了feign,feign的出现完美的解决了这个问题,(feign只是对了ribbon进行了封装,然后加入了自己的一些东西,feign的底层还是ribbon)feign采用的方式通过注入一个接口的方式来实现的,具体如下:
1.引入feign的依赖,spring集成好的依赖openFeign这个依赖
2.需要在生产者的api中新建一个接口feign的接口,在这个接口上贴上@FeignClient注解,表示这个一个feign的客户端,写上需要远程调用的服务的名称
3.在这个接口的方法上贴上@RequestMapping("/get")这个注解
4.在方法的参数中贴上@RequestParam("id")这个注解
5.在生成者的服务中新建一个类实现刚才新建的feign的接口,这个类需要贴上@restController这个注解,里面所写的方法和内容和这个服务中的controller类中写的是一样的,因此controller可以不需要写了.
6.在消费者服务中的启动类中需要贴上@EnableFeignClients这个注解,贴上这个注解表示告诉spring框架要扫描所有贴上@FeignClient注解的类或者feign的客户端,注意:扫描的是当前包及其子包下面的类,因此要想@feignClient这个注解被扫描到,需要@FeignClient和@EnableFeignClient这个注解所在的包名是相同的,这样当消费者服务启动时才可以扫描到生产者服务中的feign客户端
7.在消费者服务中的业务层注入feign接口依赖,然后通过feign接口调用方法时,feign底层是通过jdk动态代理的方式(使用反射)创建一个代理对象,这个对象根据反射获取接口上注解以及方法上的注解及方法参数中的注解,根据这些注解就可以获取对应的值,比如:服务名称,路径,参数,然后将获取到这些值拼接成一个路径,然后根据参数名称去本地服务列表中拿到对应的ip和端口,然后替换到url中,然后这个代理对象根据这个url使用HttpUrlConnection发送http请求.
8.请求最终会到生产者服务中实现了feign接口的实现类中(和以前写的controller是一样的,区别就是添加了这个类实现了自定义的feign接口),然后调用业务方法,获取数据,返回给调用者或者消费者
9.消费者服务中的feign接口的代理对象获取生产者服务返回的数据封装到product对象中.
四.Ribbon和Feign的超时时间和超时重试次数的设置
使用ribbon做远程调用时,默认超时时间是60s
源码中默认options中配置的是6000毫秒,但是Feign默认加入了Hystrix,此时默认是1秒超时.
我们可以通过设置修改feign的超时时间:
feign:
client:
config:
default:
connectTimeout: 5000 #等待连接时间设置为5秒 表示连接的时间如果超过了5s则报错或降级
readTimeout: 5000 #相当于通话时间设置为5s,连接上了读的时候超过了5秒则报错或降级
feign的默认重试次数为1次:表示第一次连接不成功的话,会在连接一次
可以进行修改设置:无论是超时时间设置还是超时重试次数设置都是在消费者服务的配置文件中进行设置的
product-server: #表示对哪一个服务进行超时时间重试次数的设置
ribbon: #ribbon的负载均衡策略的设置RandomRule表示随机策略,RoundRobinRule表示轮询策略
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #表示随机
MaxAutoRetries: 0 #表式相同的服务最大超时重试次数,设置为0,表示不重试
MaxAutoRetriesNextServer: 0 #如果生产者服务有多个,表示不同的服务的最大超时重试次数
通过以上也可以看出,feign底层使用的就是ribbon.因此ribbon的相关配置在feign中也是生效的
远程调用时,超时时间重试一定是要保证业务是等幂性操作,:比如如果是添加操作,有可能会造成重复执行
所谓等幂性操作就是无论重试多少次不会造成数据库的改变
五.Hystrix服务熔断和降级
所谓熔断就是当某个服务出现故障时,可能会造成大批量访问,导致资源被耗尽,会造成一些好的服务也无法放访问,为了避免这种情况的出现,要对这个服务进行熔断处理,即熔断表示为了防止整个系统故障,保护自己以及下游的一些服务,而实施一种策略,也就是这个服务出现故障,只熔断这服务,其他正常的服务不受影响,可以正常运行
所谓降级就是抛弃非核心业务,保障核心业务不受影响,例如:双11那一天,订单业务非常多,为了保证核心业务订单能够正常运行,将会停掉一些非核心业务的服务(比如:修改密码,修改收货地址等等),将这些停掉的服务器专门用来执行订单业务,这样就是所谓的降级,整个功能会降一级,但是核心业务不会受影响...
二者区别:触发原因不太一样:服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
二者相同点:
1)目的很一致: 都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;
2)最终表现类似: 对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;
什么是服务雪崩效应
由于某一个服务的不可用,导致资源被耗尽(tomcat的线程被耗尽),而进而导致其他所有服务都不可以调用
如何解决:引入超时机制,引入限流机制,引入熔断机制(当访问服务失败多次以后就可以打开熔断机制.不让在访问的),引入降级机制,(当用户访问错误的时候或者熔断的时候,返回一个页面或者默认数据给用户)
超时机制尽量不超过2秒,否则高并发下会导致资源被耗尽
hystrix的作用
提供了熔断、隔离、Fallback、cache、监控等功能
如何操作
ribbon集成hystrix
1.引入hystrix的依赖,netflix的hystrix的一个框架.
2.在消费者服务的启动类中贴上@EnableHystrix注解或者@EnableCircuitBreaker 注解(这两个注解是一样的,在@EnableHystrix注解上贴有@EnableCircuitBreaker 这个注解),表示项目启动时开启断路器功能或者开启服务熔断和降级功能,
3.在消费者服务中的controller中需要执行熔断降级的方法上面贴上@HystrixCommand注解,并在这个注解中配上属性fallbackMethod="自定义的降级的方法名字",然后自定义的降级方法需要和这个原方法有一样的参数和返回值
上面那样就配置hystrix的熔断降级处理,默认超时时间是1s,只要1s内没有返回数据则执行降级处理,即会执行自定义的降级方法,返回一个自定义的数据,这是最外层的降级处理
feign集成hystrix
1.在生产者api中以前我们自定义了一个feign的接口上面贴了一个注解@feignClient,现在要在使用feign中的hystrix降级功能,需要在这个注解中添加一个属性fallback="我们自定义的一个feignHystrix降级类.Class"
2.既然要使用feign的降级,那就需要自定义一个降级方法,因此在api中自定义个降级类,也就是上面说的feignHystix降级类,这个类实现feign的接口,然后贴上@componet注解交给spring管理
3.在这个类中我们实现接口的这个方法,这个方法就是我们要写的降级的方法,里面可以写当出现降级以后返回的数据
4.要使用feign中的hystix的降级处理,必须要开启hystix,默认是关闭的
#开启feign中的hystrix,默认是关闭的,需要手动打开
#一般feign降级和hystrix降级只需打开一个即可,两个都可以实现降级处理
feign:
hystrix:
enabled: true #开启feign的hystirx熔断降级
client:
config:
default:
connectTimeout: 5000 #等待连接时间设置为5秒 表示连接的时间如果超过了5s则报错或降级
readTimeout: 5000 #相当于通话时间设置为5s,连接上了读的时候超过了5秒则报错或降级
#设置hystrix的超时时间
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
hystix的默认超时时间是1s,可以通过配置进行修改这个时间,feign的降级默认是关闭的,需要手动打开,当feign的超时时间到了之后要执行降级处理
hystrixCommand的超时时间需要比配置feign远程调用的时间要大才有意义
真实开发环境中,超时的时间的不能超过2s.如果需要大于2s需要使用异步或线程处理
六.如何理解feign中hystrix降级和最外层的Hystrix的降级处理
分为以下几种情况:
情况一:假如消费者服务hystix降级开启,默认1s超时,feign没有开启hystix降级,生产者业务执行睡眠3s
则:由于睡眠3s导致hystix降级,执行hystix降级方法,用户接收hystix降级方法的返回数据
情况二:假如消费者服务hystix降级开启,默认1s超时,feign开启hystix降级,.默认超时时间为1s,生产者业务执行睡眠3s
则:由于睡眠3s导致hystix降级,feign也会降级,执行hystix降级方法,feign的降级方法也会执行,但是用户接收hystix降级方法的返回数据
情况三:假如消费者服务hystix降级开启,默认1s超时,feign开启hystix降级,.修改超时时间为2s,生产者业务执行睡眠3s
则:由于睡眠3s导致hystix降级,feign不会降级(因为到1s时没有返回数据就会执行hystix的降级方法),执行hystix降级方法,用户接收hystix降级方法的返回数据
情况四:假如消费者服务hystix降级开启,默认1s超时,feign开启hystix降级,.修改超时时间为4s,生产者业务执行睡眠3s
则:由于睡眠3s导致hystix降级,feign不会降级,执行hystix降级方法,用户接收hystix降级方法的返回数据
情况五:假如消费者服务hystix降级开启,修改超时时间为4s超时,feign开启hystix降级,.修改超时时间为4s,生产者业务执行睡眠3s
则:由于睡眠3s后还未到超时时间,则不会执行feign的降级处理,但是由于feign返回数据到消费者服务接收数据时间如果大于4s则会执行hystix降级方法,返回hysrix数据,如果不大于4s,则都不会进行降级处理,返回feign返回的数据
情况六:假如消费者服务hystix降级开启,修改超时时间为5s超时,feign开启hystix降级,.修改超时时间为4s,生产者业务执行睡眠3s
则:由于睡眠3s后还未到超时时间,则不会执行feign的降级处理,但是由于feign返回数据到消费者服务接收数据时间不足5s,因此不会执行降级方法,正常返回数据
七.zuul微服务网关
引入依赖:Netflix开源的微服务网关,和Eureka,Ribbon,Hystrix等组件配合使用.
在启动类上贴上@EnableZuulProxy注解
配置zuul网关服务信息
server: port: 9000spring: application: name: zuul-servereureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
自定义路由规则
#zuul网关的自定义路由配置zuul: ignoredPatterns: /*-server/** #这个配置表示忽略默认配置 routes: order-server-route: path: /order/** #这个配置表示使用order的路径则会访问order的服务 serviceId: order-server product-server-route: path: /product/** #这个配置表示使用product的路径则会访问product的服务 serviceId: product-server sensitive-headers: #给一个空值表示不会过滤到cookie的信息
cookie请求头问题
sensitiveHeaders: #配置这个表示不让cookie请求头被拦截
八.链路追踪Sleuth和Zipkin
1.在需要进行日志追踪的服务中引入依赖sleuth和zipkin的依赖,不过zipkin已经包含了sleuth依赖,因此只需引入zipkin这一个依赖集合
2.在需要使用链路追踪的服务的配置文件中添加zipkin的地址
spring:
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
probability: 1
九.分布式配置中心
Spring Cloud Config用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,分为服务端和客户端两个部分。其中服务端又称为分布式配置中心,是一个独立的微服务应用,用来连接配置仓库并为客户端提供获取配置信息;而客户端则是微服务架构中的各个微服务应用或基础设施,它们通过指定配置中心来管理应用资源和业务相关的配置内容。服务器存储后端的默认实现使用git,也可以使用SVN仓库或者本地文件系统。
关于git配置信息如下:
spring.cloud.config.server.git.uri: 配置Git仓库位置
spring.cloud.config.server.git.search-paths: 配置仓库路径下的相对搜索位置,默认是只在根目录下寻找,配置相对位置后,除了根目录还回去配置的位置下寻找。
spring.cloud.config.server.git.username: 访问Git仓库的用户名
spring.cloud.config.server.git.password: 访问Git仓库的密码
配置中心的作用和好处
安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏时效性:修改配置,需要重启服务才能生效局限性:无法支持动态调整:例如日志开关、功能开关
如何操作:
1.创建config-server服务,并引入依赖spring-cloud-config-server
2.配置文件
server:
port: 9100
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://gitee.com/d.git
username: 自己的gitte账号
password: 自己gitee密码
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/ #eureka的地址
3.启动类上贴注解@EnableConfigServer
4.创建码云仓库,并把仓库的地址添加到yml文件中,添加Eureka注册中心的配置到application.yml中。注意如果使用的git的仓库地址是http协议的 那么必须在后面继续追加账号和密码,如果使用是ssh的就不用。
5.在其他需要将配置文件上传到码云交给配置中心管理的服务中添加配置中心客户端依赖spring-cloud-config-client
6.将原来的配置文件application.yml改为bootstrap.yml
boostrap.yml如下:
spring:
application:
name: order-server
cloud:
config:
discovery:
service-id: config-server
enabled: true
label: master
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
7.将原来的application.yml的中心移到码云上进行管理
由配置中心进行统一管理,流程如下:
1>项目启动时,商品服务会从注册中心拉取最新的配置中心的config-server的ip地址
2>根据config-server的ip地址发起请求,根据product-server的名字从配置中心获取对应的配置文件
3>项目读取获取到的配置文件product-server.yml.启动服务
bootstrap.yml是先读取,优先级是大于application.yml的,因此先从bootstrap.yml中进行读取
配置中心由于配置了远程仓库的地址,用户名和密码,则会自动从码云上将配置文件缓存到本地服务列表中,项目启动时进行读取