springCloud原理

开头思考

	1.springCloud 管理 微服务应用,解决分布式问题
	2.A服务: A1,A2,A3
	  B服务: B1,B2,B3
	3.现在用 A1,去调用 B服务
		1.B1,B2,B3 调那个? (负载均衡)
		2.有 一个 坏了 怎么办?
		3.服务调用是变了,可能是网络原因   (容错机制)
		4.A1,A2,A3 的配置文件 怎么 统一管理   (配置中心)
		5.服务监控
		6.A1-B2-C3-D4 服务之间的调用关系,以及调用失败的定位  (链路追踪)
		7.日志管理
		8.任务调度
		9.服务注册 管理

注册中心

	1.为什么要用注册中心,传统的rpc调用就可以完成功能
		1.服务注册中心的主要功能是服务的治理
		
		2.注册中心中有一个 服务注册表(key:服务名 value:服务地址)
		
		3.这样注册中心有了服务的信息,当服务调用来了,注册中心可以提供服务的信息
		  调用者拿到信息,底层也是采用rpc去完成调用
		  
		4.说了这多,最后还是 rpc调用,那注册中心保存 服务的 信息有啥用
			1.可以检查服务是否可用(注册者,隔段时间会向 注册中心发一个心跳
			  来确保服务可用,不然注册中心会 把 注册中心表中 此服务信息移除)
			  这样 调用者A,在调用注册中心的 服务的时候,服务已移除,那么调用失败
			  失败后cloud的其他组件,可以处理失败的情况
			  
			2.负载均衡,为负载均衡组件提供服务信息,负载均衡组件完成负载均衡后
			  选出 那个服务,然后注册中心提供给,调用端

			3.准确来说,注册中心最大的好处就是管理服务信息,并且为 cloud的其他组件
			  的功能完成,提供了信息基础,包括负载均衡,服务熔断降级,链路追踪....
			  
	2.注册中心的重要组件(以Eureka为例)
		1.EurekaServer
			1.不是一个单独的服务器,只是提供了依赖,通过@EnableEurekaServer
			  将EurekaServer依赖 注入ioc容器中(可能是 autoconfiguration注册的)
			  
			2.这个我们开启的 有EurekaServer的组件的,服务,才能叫做 注册中心(是一个应用)
			
			3.EurekaServer组件可以,将 注册的服务的信息,填充到 注册中心表
			  并且 可以为 调用者(或cloud的其他组件),提供 服务信息

			4.可以接收,服务注册者的 心跳,也可以移除 服务信息
			  服务端默认 接收心跳的时间为 90s

			5.注册中心,和服务注册者,服务调用者,或者其他组件(想要访问注册中心的
			  注册表的服务信息的组件,之间的交互,都是 http交互的)
			  
		2.EurekaClient
			1.java客户端,也是依赖,用@enble注解,将组件 注册到ioc容器中
			
			2.client组件,可以将 此服务 注册到 注册中心(底层 http交互,向注册中心
			  提供服务的信息,注册中心再将消息,注册到 服务注册表中)

			3.向 注册中心,发送心跳,保证服务可用(也是 http)
			  默认客服端发送心跳的时间是30s

			4.内置一个 基于轮询算法的 负载均衡器

		3.关于 service-url
					defaultZone : 提供一个 server端的 地址 + /eureka
					
			注意:这个只是说当前 服务如果要 注册,那么这个地址就是 想要注册的
			注册中心的地址
			
			而且 服务端,同样可以配置这个地址,注册进其他注册中心,在集群里面常见
			也就是说如果此服务是 服务端,这个地址不一定要和 此服务+/eureka一样
			
			说白了,服务端如果不注册进其他 注册中心,这个配置根本没用
			这个配置就是来将此服务 注册到 这个地址的 注册中心的
			client端 这个地址必须有用,因为就是将client端服务 注册到 这个地址的注册中心的

			但是给 eureka注册中心服务端做集群的时候,这个地址在 就有用了,
			eureka做集群,就是注册中心之间 互相注册,所以都是配置的其他注册中心的地址
			
			但是euraka做集群,注册的话,不需要eurekaClient依赖,而且一个注册中心
			注册到另一个注册中心,也不是用 服务注册表来存储的,是用 
			Ds Replicas来存的,
			
			就是说一个注册中心在接受,一个服务注册过来的信息的时候
			会判断此服务是,注册中心还是,client端,client端的用 服务注册表存
			注册中心用 Ds Replicas存,代表两个注册中心的互相注册关系,是集群关系

	3.eurekaServer做集群
		1.将 2个注册中心之间互相注册,互相注册,互相守望
		2.将 client端 分别注册进 这两个注册中心

	4.client端做集群(没有内置负载均衡)
		1.将 相同业务的 client端 都注册进一个 注册中心
		
		2.ok,eurekaServer已经负载均衡,这样就会选定一个 server,然后一个server里面有
		  相同的 client服务提供者(service-name相同)
		  这时要在 @bean restTemplate上 加一个 @loadBalance做一个负载均衡(默认轮询)
		  这样 restTemplate就有了 负载均衡功能
	(server的集群,client的集群 做负载均衡 可以用ribbon)
			
	5.服务发现(很重要,因为后面,服务调用 ribbon去拿到,服务注册表的信息,就是根据 discoveryClient)
		1.在 client端 加上一个 @EnableDiscoveryClient
		
		2.说白了,就是发现,EurekaServer中 管理的 这些服务的信息,可以通过
		  Discovery这个组件,提供给外界
		  服务的调用,底层也是通过,discovery去查询 这些 服务注册信息的
		  
		3.使用的话,因为@EnableDiscoveryClient就是 注册一个 DiscoveryClient组件
		  你在 client端 想使用服务发现的话,将DiscoveryClient  DI进来即可
		  这样我们用DiscoveryClient的 api可以获得 注册中心的 所有服务的基本信息

		4.这样我们可以了解 ,注册进注册中心的 服务,可以通过服务发现来了解服务的信息


	6.Eureka的自我保护机制
		1.默认 注册中心 默认开启 自我保护机制
		
		2.因为,心跳机制,注册中心在接收不到,客户端发来的心跳一定时间会把服务注册表的中服务信息清除调
		  但是为了,服务的高可用,EurekaServer默认开启了自我保护机制,不清除(因为可能是,你server端的 网络不好),
		  就是宁愿保存 服务错误信息,也不误判

		3.改的话,就关闭自我保护机制即可,同时可以修改 心跳发生时间间隔,与服务端接受的时间间隔

		4.Eureka的设计思想就是 CAP的 ap分支 保存分区容错性性和 高可用性,舍弃了分区一致性

服务注册和服务发现的区别

	1.服务发现:服务注册后,注册中心 提供服务的信息,都要用到 服务发现,包括服务调用一个服务
	  想要从注册中心获得 那个服务的信息,要需要服务发现提供

	2.服务注册,仅仅是 将这个服务的信息,注册到 注册中心的注册表中

zookeeper,consul,Eureka的区别

	1.Eureka满足  ap原则 高可用性 
		即使,服务没有发心跳,也不会消除服务,即使是错的也会回复错的,保证服务的高可用
		但是一致性得不到保证,服务已经宕机了,也不会消除
		
	2.zookeeper,consul 满足 cp原则 高一致性
		没有自我保护机制,服务宕机,收不到心跳,立即消除服务,保证高一致性
		但是,满足不了高可用性

cap原则(mysql,redis)

ribbon和 restTemplate

restTemplate 就是封装了 http ,跟注册中心 cloud没关系

负载均衡,都是在调用端,有一个负载均衡器,无一例外

负载分内部负载 和 外部负载
内部负载 就是通过 api实现负载 例如 ribbon
外部负载 就是通过 服务器nginx作 负载

	1.ribbon是 客户端 负载均衡器
		1.就是api依赖
		2.加载 服务消费者端的
		3.是 进程式的(api)
		4.在本地 做 rest调用,就是说,将注册中心的 服务列表找到,加载到 本地 jvm
		  然后,负载均衡策略选择,指定的地址,然后做 本地 rpc调用
		  
	2.Nginx 是 服务器 负载均衡器
		1.服务器
		2.集成式的(服务器)

	3.ribbon在工作时分两步
		1.先选择 EurekaServer,他优先选择在同一个 区域内负载较少的server
		2.再根据 用户指定的 策略,在从server取到的 服务注册列表 中 选择一个地址。
		其中 ribbon 提供 了多张策略:比如轮询,随机,根据响应时间加权

	4.ribbon的核心组件
		1.IRule接口(实现负载均衡的接口)
			RoundRobinRule 轮询 默认
			RandomRule 随机
			RetryRule........
			
		2.如何替换默认 IRule
			1.首先 configuration不能在 启动类的包及其子包下,所以得新建一个包
			2.包内 新建一个 configuration @bean 一个 新的 MyselfRule组件
			3.主启动类 添加 @ RibbonClient(name = 是指你想这个 负载均衡rule 想用在用在 访问哪个服务时使用这个
			,configuration = 是指 自定义的 IRULE 在哪个 configuration下,即你想用哪个 IRule)

		3.RoundRobinRule轮询 的 底层原理
			1.服务调用 注册中心,首先通过 discovery拿到 注册表中的 List<instance> 服务实例列表
			  List<ServiceInstance> instances = discoveryClient.getInstance("服务名")
			  然后缓存到 本地 jvm
			
			2. 用 接口请求的次数 % instance.size() 得到 下标 index
			
			3. List<index> 就是最后返回的 实例
			
			4. 服务调用者拿到这个实例(实例的 ip地址),httpCilent调用

	5.restTemplate(可以访问注册中心,并拿到 服务列表缓存到 本地jvm,然后 底层用httpClient调用)

服务调用(不管用不用ribbon)都是,先把注册中心的,注册表中的 key value拿到
然后存在本地 jvm中,然后在本地做调用,不是说直接 服务消费者 http 直接调用了
缓存中存的就是 通过 discovery.getInstance(key) 的服务实例

OpenFeign

	1.feign(内置ribbon)  = ribbon + restTemplate
	底层 跟 restTemplate没有关系,feign集成了 ribbon 但是没有 集成 restTemplate 是自己的一套 http实现,
	默认是去 注册中心拿 url 但是 也可以配置 不去 注册中心拿,但这样 ribbon就没有用了
	  真正做到 服务接口 绑定 注册中心 服务接口编程,简化配置
	  
	2.feign是一个 声明式 web服务客户端,让编写 web服务客户端更加容易
	
	3.因为内置ribbon,那么 不用再加 @loadBalance注解,就能将ribbon注册到 ioc容器中
	  同时相当于,内置了restTemplate,也不用注册 restTempalte

	4.openFegin的超时控制
		1.默认 建立连接和 从服务器读取到 可用资源的时间是 1s
		2.更改 配置文件 可以修改 超时控制
			ribbon:
				ReadTimeout:  (成功建立连接后,读取可用资源的时间)
				ConnectTimeout (与服务端 建立连接的 时间)

	5.openFeign日志配置
		1. 注册一个 @Bean logger.level.feignloggerLevel()组件 配置日志级别
		2. 在配置文件中 配置日志
			logger:
				level:
					接口名:打印日志的方式(debug)

	6.feign 调用的时候,会有重试机制(源码)

Hystrix 断路器(服务降级等三大功能的具体实现)

	1.三大功能:
		1.服务降级:(服务降级是调用方的机制,调用方接受不到响应端的响应,而触发fallback函数)
			当访问的服务 出现 “问题”后,Hystix给 开启Hystrix一个 备选的解决方案
			这个备选的返回,就是 服务降级
			服务降级不是 “问题”,而是服务出现问题后的,提供的 一个备选 解决方案

			哪些问题出现会触发 服务降级:
				1.服务超时 
				2.出现运行异常
				3.服务熔断(是一个问题) 触发 服务降级
				4.服务宕机
			
		2.服务熔断
			当 访问 此服务 达到服务能接受的最大限度了,此服务触发服务熔断,并且触发 服务降级
			此时已经服务到最大限度了,又没有限流,还有服务要访问,为了避免服务挂掉,执行服务熔断
			等于此刻服务已不可用,并调用服务降级,返回友好提示
			
			过程:
			先是服务已经“满”,不可用了--》服务熔断--》服务降级,返回友好提示 ---》 等正在访问次服务的 调用者,慢慢调用完毕,
			然后再恢复服务
			
		3.服务限流
			此时服务还没有 达到最大限度,服务还没有熔断,为了避免服务熔断,那么触发服务限流,让还
			继续来的服务,要么等待,要么

1.分布式情况下,访问接口的速度一定不能慢,一个慢会导致整个分布式系统都慢,典型的一个慢,全体慢(要是都慢导致分布式系统慢可以接收,但是一个慢导致全体慢不能接受)

2.提高 大量请求 访问接口速度慢的解决方案

	1. 编写接口时,让其尽可能的快,从而提高某时刻的线程资源数
	
	3. 如果接口速度本身就慢,此时如果请求量少,那么线程资源还是充足的
	   这时会导致整个分布式系统慢,但是因为线程资源充足,也不会导致系统崩溃
	   
	3.如果接口速度慢,请求量大,线程资源变少,那么就必须提高接口的速度,业务上
	  不能提高,那么就采取服务降级,尽快返回,间接提高接口响应速度

	4.一个接口慢,导致整个分布式系统的 接口链慢,导致整个系统的线程资源(长时间无法释放)
	  导致整个系统 某一时刻的线程资源变少
	  从而 影响其他 本身都不慢的 接口链
	  也就是说系统A(1,2接口),系统B(3,4接口),B3慢,A1调B3,A2调B4
	  A1B3这个接口链一定会变慢,从而 AB两个系统的 某一时刻的线程资源数变少
	  从而 A2B4(这两个接口都不慢)也会因线程资源数不够用变慢

	4.直接提高线程资源数,即搭集群

	5.总而言之,只要 某一时刻,线程资源数够,那系统一定不会蹦盘,
	  让接口速度变快的原因,也是因为速度慢,会占用线程资源不放,从而导致
	  某一时刻的线程资源数变少,而且一个分布式系统A下的接口速度慢,会导致
	  调用它的 另一个分布式系统B的 接口速度间接变慢,占用B的线程资源,
	  也就是 “一个慢,导致整体慢,进而拖垮整个系统的 线程资源,导致其他接口链,也会因这个接口链的慢占用线程资源,而变慢”

	6.注意:线程资源被占用,和cpu被这个线程占用是有区别的
			1.线程资源被占用,是指线程中的 这些操作(指令)一直没执行完,那线程就不能
			  去更新执行(即存其他操作的指令),就会导致 其他操作 没有线程存,而不能执行
			  
			2.而 线程资源被占用,不代表cpu一直被这个 线程占用,只有这个线程的 某个操作
			  是原子性的,才会占用 这个cpu
			  
			3. cpu被 这个线程占用,比 线程资源得不到释放 严重的 多,线程资源得不到释放
			   只是 说 用来存其他指令的 线程少,但是不代表 不能存,而cpu被线程占用,那
			   就算你线程量 充足,其他所有 请求指令,都能被 线程存起来,但是没有cpu资源
			   根本得不到执行

服务降级(服务降级是 消费端服务调用者 和 服务端服务提供者 都可以做服务降级,简单来说,服务提供者可以首先将自己 ‘出错’ 了,做一个服务降级处理,返回给 消费端,当然 不管如果服务端不做降级,那 我 消费端就得做降级,来保证返回浏览器,释放线程资源

但是 服务降级fallback ,最常见的还是控制在 消费端

	1.服务降级 可以用在 消费端,也可以用在服务端
	
	2.一般出现 服务超时(自定义超时峰值)(服务端和消费端都可以做服务降级)
			  服务端服务宕机(对于服务消费者这块做 服务降级),服务端宕机无法对服务端做这个 ‘错误’的服务降级
			  程序运行异常导致程序退出(服务端和消费端都可以做服务降级)

	3.'错误':是指,系统本身的异常,宕机,
	         也可以指:我们自定义的,比如程序超时峰值
	
	
	  (Hystrix用法:)
	4.1.在yml中开启 feign:hystrix:enable = true 
	  2.Hystrix 启动类 加 @EnableCircuitBreaker(服务端和消费端都可以)
	  3.在方法(controller/service...) 上加 @HystixCommand 代表对这个方法做 服务降级的控制
	    只要这个方法出了 服务超时(自定义timeout峰值),异常,这个方法调用 其他宕机服务
	    那么就会 停止执行这个方法,去执行 备选方法,达到服务降级的目的

	  @hystrixCommand(fallback = 降级方法 , commandProperties = {多个@HystixProperty})
	  @HystrixProperty的意思 就是 断路器执行过程中的 配置,这些配置 是 name,value显示的
	  name是配置的属性,有超时时间,断路器是否开启,断路器的请求次数,时间窗口期,失败率达多少,熔断器从 CLOSED -> OPEN
	  这些name ,value 你如果指定,都会有默认的配置的,来自与 HystrixCommandProperties这个
	  类里面,都有默认的 name 和 value , 例如 超时,请求次数等

	  当然,在 yml中 可以统一配置 commandProperties,免得 代码雍肿
	  
	  注意,在这些属性中,有个超时控制,是可以作为 fallback条件的,与 系统出错,加起来
	  一起作为 fallback触发的条件
	  
	   Hystrix 对这个方法进行 控制,保证这个方法的 顺利return

	5.@HystrixCommand(fallback方法 , commandProperties = { 多个 @HystrixProperty}) 是对方法做 控制 进而服务降级的
	
	  @DefaultProperties(fallback方法)加在类上 ,然后在方法上加上 @HystrixCommand标识
	  里面可以写 @HystrixProperty ,但是 不加 fallback , 那么就会走 @DefalutProerties的全局 fallback
	  这样做的好处,就是 每个要做 Hystrix监控的方法,都得加 fallbck属性,代码太冗余,
	  如果,有些方法的 fallback方法都相同,那么就把它提取出来,写在全局fallback上,然后
	  这些方法 就不用 在 @HystrixCommand()里面加 fallback属性了,出现错误,就会走全局fallback
	  但是 你细粒度的 在 @HystrixCommand() 里面 加了 fallback,就会走细粒度的
	
	
	
	6.消费端 和 服务端同时 加了 Hystrix控制,首先以 消费端为主,消费端出错,即直接走消费端的
	  fallcack,消费端不出错,但是服务端出错,走服务端的 fallback
	


	7.加了 @HystrixCommand, 线程池就会用 Hystrix提供的线程池
	  这也是 Hystrix可以做服务降级的最重要的因素,自己提供的线程池,可以自己控制线程,方法栈的结束时刻
	  

	8.服务端加Hystrix 等于从 源头抓起,控制服务端的‘错误’备选方案
	  在消费端加Hystrix(其实消费端可以做下一个消费端的服务端),就是对消费端的控制,
	  
	  消费端做服务端好理解
	  消费端只做消费端,那么消费端可能不满足,服务端做的服务降级处理,那么消费端还可以做一个
	  服务降级处理,进而导致整个调用链,都能很好的对 ‘错误’的控制,进而系统流畅,线程资源得到尽快释放
	  
	  实际上 Hystrix不知道什么是消费端什么是服务端,它只是来控制 方法的错误,而提供的备选方案的
	  而错误(可以是自定义的超时峰值,也可以是方法的异常,宕机等)



	9.重点: 彻底理解 消费端 和服务端 做 Hystrix的 异同和原因
		1.服务端做 Hystrix,控制服务错误-> 消费者不会因 服务端的 ‘错误’,而受影响,进而影响线程资源
		
		2.消费端做 Hystrix
			1.消费端本来就可以做服务端 和1原因一样
			2.消费端做消费端
				1.对服务端的 控制服务错误 不满足,在消费端 再做一次 ‘错误’ 控制
				 进而,不管是 消费端 还是 服务端,都做了很好的 ‘错误’控制,整个系统就都好了,因为系统就是由消费端+服务端 组成


	10.ok,现在要解决两个个问题
		1.每个要做 服务降级控制的 方法,都得在@HystrixCommand()添加属性
		  可不可以 只用在 想要做控制的方法上 加一个 @HystrixCommand标识,不要加 fallback属性
		  用一个统一的属性列表来统一控制,这些方法呢
		 (当然,如果方法不想被服务降级控制,直接啥也不加即可)
		 
				解决办法:(没有解决备选方法 和 业务逻辑在一起 冗余的 问题)
					1.在controller类上加一个 DefaultProperties(fallback方法:全局fallback方法)
					
					2.在想要 被 统一控制的 方法上 加上 @HystrixCommand标识即可
					被统一控制的,只能共用一个,备选方法
					======================================================
					
					3.想要 独立做控制的方法上(不想被统一控制)还是加上 @HystrixCommand(属性:指定独立的控制属性)
					
					4.根本不想被 服务降级控制的 直接啥也不加就可
					(@HystrixCommand标识的 会找 @DefaultProperties(属性),去控制)
					(@HystrixCommand(属性),会用自己的属性去 控制方法)
					(啥也不加的,不涉及 服务降级,用的是 tomcat的线程池)

					总结:将大部分业务逻辑,用一个统一的服务降级控制,有一个统一的 备选方案即可
					     要定制的 方法控制的,还是用@HystrixCommand(属性)来做定制控制
					     不想 被服务降级控制的 啥也不加即可

		2.怎么解决,业务逻辑,和 备选fallback方法,在一起的 代码冗余问题
			1. 首先 服务端 是无法解决的,服务端就用 之前的就好,对整个加了@HystrixCommand的方法
			   做控制,因为这样方法,只能用在 feign调用方上
			   
			2.对消费端可以解决
				1.由于消费端的方法控制的时候,都会 feign 调用服务端的接口,这个特性
				那么,我们将 方法控制,精确到 feign调用接口 这一块(对这一块代码块 做 服务降级控制)
				
				2.那么,消费者端的 controller方法就不用加@HystrixCommand方法,而是用@FeignClient做服务降级
				
				3.@FeignClient(name = "",fallback = clientFeign的接口实现类)
					这个接口实现类,实现的方法,就是对 feign调用接口这一句 做 服务降级处理的
					
				4.这样,消费端的 controller方法无法做服务降级了,只有 feign调用的这一句代码 由 FeignClient做服务降级
				
				5.缺点:
					1.无法在对 消费端 整个controller做服务降级

				6.优点:
					1.具备 Hystrix所有的功能,包括服务降级,服务熔断,服务限流,以及CommandProerties属性的设置
					
				7.用 feign调用同样 也可以设置 commandProperties 可能用其他方式,因为毕竟没用
				  @HystrixCommand注解

				8.对 feign进行精细控制 HystrixCommand 和 在方法上 进行粗略HystrixCommand控制,都可以使用
			 	 Hystrix的所有功能

				9.在 feign上 做 Hystrix控制,commandProperties可以配置在 yml配置文件中,如果不好直接写的话

				10.  当然,在 yml中 可以统一配置 commandProperties,免得 代码雍肿

服务熔断(熔断器)(服务熔断,是服务端服务提供者 熔断,不是消费端熔断)

目的就是,一个服务的 fallback率太高了(这个fallback 可以是服务端,也可以是消费端,看以什么角度看待,但是 熔断的 是 执行fallback的那一端的 服务),那么让它熔断,任何请求在过来,Hystrix提供线程池,直接访问fallback返回,不让其访问业务逻辑了,给调用方,和服务端,一个‘思考’的时间,

	1.熔断器和 服务降级的区别
		服务降级是 对 ‘错误’的控制,出现‘错误’,调用fallback方法
		
		服务熔断,是指 在A时间窗口期内,B次请求内,有百分率C的失败率(fallback的百分率)
		那么Hystrix的熔断器,会熔断次服务,即 熔断器从 CLOSED状态,变成OPEN 熔断器打开状态
		即开启了服务熔断

		即服务降级,和服务熔断,是从 不同角度和粒度,对服务出错,进行的备选解决方案
		
		然后在一定时间范围内(默认5s),这时再发请求,因为服务是熔断状态(其实就是判断 容器器的状态)
		熔断器是 OPEN状态,那么Hystrix线程池,会直接调用 fallback备选方法(不管程序是不是‘正确的’
		)

		链路在 恢复5秒后
		5s后,熔断器 = HALF-OPEN 状态,此时可以接收请求过来,调用方法
			1.如果 没有 ‘错误’(没有调用fallback 服务降级)返回正确结果,熔断器 从 HALF-OPEN -> CLOSED
			  又开始新一轮的 监控
			2.如果 有 ‘错误’,调用fallback服务降级,熔断器 从 HALF-OPEN -> OPEN
				然后又开始 5s 的链路恢复期(任何请求都 fallback)
				5s后,熔断器 从 OPEN -> HALF-OPEN
				.......

	2.熔断器的具体配置(和服务降级配置一样)
		1.在 yml中 开启 Hystrix
		2.在主启动类上,@EnableCircuitHystrix 开启服务降级和服务熔断
		3.在,业务逻辑方法上加上 @HystrixCommand(里面配置 服务熔断的条件)例如
		
				@HystrixCommand(fallbackMethod = "",commandProperties = {
					@HystrixProperty(name = "circuitBreaker.enabled",value = "true")  //是否开启断路器,
					@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value ="")  //请求次数
					@HystrixProperty(name = "circuitBreaker.sleepwindowInMilliseconds",value ="")  //时间窗口期
					@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value ="")  //失败率达多少,熔断器从 CLOSED -> OPEN
				})

	3.所以说,服务熔断和服务降级是在一起使用的,但是是两个不同的东西

简单来说,Hystrix组件,解决了 服务出错后的 备选处理,其中 最关键的几个注解就是,@EnableCircuitHystrix(注入,hystrix组件,处理服务降级,服务熔断),@HystrixCommand(对 方法进行控制,继而 Hystrix得以实施),而服务降级,服务熔断都是 从不同角度和粒度,对服务出错的 备选解决方案

但是 Hystrix只是 服务出错的 备选解决方案,而不能修复好 出错的服务

在 yml中 可以统一配置 commandProperties,免得 代码雍肿

springcloud gateway网关

gateway自带负载均衡

网关核心功能是路由转发,因此不要有耗时操作在网关上处理,让请求快速转发到后端服务上

网关还能做统一的熔断、限流、认证、日志监控等
gateway做 动态路由 就是 RoutePredicateHandlerMapping 来做的,你可以在配置文件中写死 路由地址,同样 你也可以在 配置类中 添加与 RoutePredicateHandlerMapping相关的路由,通常我们都是从数据库中查询路由,然后再由 RoutePredicateHandlerMapping做路由的

客户端请求,首先会被Gateway Handler Mapping处理,用以在 路由表 中查找一个与请求匹配的 路由 ,然后将请求交由 Web Handler 处理,Web Handler 维护了一个过滤器链,链式执行这些过滤器,这些过滤器在逻辑上存在两个执行阶段 pre 与 post 。

网关可以控制,所有请求,只能先走网关,然后到服务,如果这样设置,那么你的feign调用,也是得先走网关的

	1.他是一个 异步非阻塞网关(底层用 netty)
		tomcat是阻塞的,就是一个请求,分配一个线程
		非阻塞,就是多个请求,分配少量请求

	2.gateway 网关的主要作用
		1.routes  想去哪
			(自带路由的 负载均衡)
			由uri,id,一系列断言,一系列过滤器组成
			uri:请求过来,找到uri,然后去匹配,断言,匹配成功,去这个uri
			
			因为自带负载均衡器,那么uri可以写成 访问服务名(不是具体服务器)
			uri:lb/service-name 如果用这种动态路由,不用具体 http:..../port具体的地址
			那么 要开启 spring:cloud:gateway:discovery:locator:enabled:true 开启动态路由
			
		2.断言 能不能去
			Predicates断言式一些列 RoutePredicateFactory去拦截请求,对请求做断言
			都匹配后,才会去访问uri
			
		3.Filters
			过滤器链,在断言匹配后,去执行 目标资源,前,有一系列filte过滤

		4.注意 一个 route下面包含了,id,uri,predicates,filters
		  多个 route 组成的 routes 形成了 springgateway的 路由功能

		5.简单来说,routes功能是想去哪,里面包含了想去哪, 断言匹配 和 过滤器

	3.gateway工作流程
		1.客户端 访问 gateway网关
		2.gatewayMapping Handler 找到 匹配请求的路由
			用 Predicates ,断言工程链,去断言匹配
		3.将 请求 发送到 gateWay Web Handler
		4.handler 在 将请求 发给 过滤器链,进行过滤
		5.执行目标资源
		6.过滤器链 回过头来执行

	4.Predicates
		1.Route predicate factories 是 java8的 接口
		2.gateway 有10多个 RoutePredicateFactory 实现类,去对request做断言匹配
		3.例子:1.AfterRoutePredicate(请求在?时间后匹配) 
					yaml: Predicates:
							after: 时间
							
				2.Before/Between 类似上面
				3.Cookie/Header/Host/Method/Path......

	5.Filter 是 gateway网关的 filter
		1.配置方法和,Predicate一样
		2.它自带了 30多种 filter
		3.如何自定义 gateWay的filter
			1.实现GlobalFilter和Order接口
			2.将其 注入到 ioc容器中(不用 配置是 tomcat的filter)

Config配置中心(数据源一定要配置在 bootstrap.yml里面,不能配置在 配置中心的 yaml文件里面,服务注册信息也得在bootstrap.yml里面,反正关键信息都得在bootstrap.yaml里面,不然将关键信息配置在配置中心,读取不到)

配置中心:可以将 配置文件 加密到 git,然后从git拉取下来的时候,也会对应的解密
从 git上面直接拉配置文件到 configserver ,可以直接通过浏览器访问 git里面的配置文件,但是本地的不能 通过浏览器访问

config配置中心 不能 和 nacos注册中心一起玩,configserver可以注册进去,也能读到 git 但是 configclient 不能注册进 nacos 并读到 nacos中 configserver的 配置文件

在nacos定义 格式的 时候 只能定义 yaml,但是创建文件的 时候可以是yml或者yaml,创建的是啥格式,那springboot配置文件,就要对应的 配置yaml或者 yml

	1.配置中心 Config server(连接 github的配置)
		1.服务端分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器git
		  并为客户端提供获取配置信息,

		2.config-server具体配置
			1.在启动类上加 @EnableConfigserver
			
			2.将配置中心注册到 注册中心
			
			3.yml中配置(不仅可以配置 git,svn,还可以配置本地native)
				cloud:
				####客户端配置
				  config:
				    server:
				      git:
				      #### Github上git仓库的名字(定位到 配置文件)
				        uri:
				      #### 搜索目录  config目录
				        search-paths:
				      ####访问的时候,clone的时候 用的 http,所以要用这个 git网站的 用户名密码作个登入
      				  ####也可以用 ssh,在 你访问 的网站仓库,设置一个 ssh就可以,实际都是一个 clone前的 登入
          	  		  ####判断 你有没有 这个网站的账号,以及记录 是哪个账号 拉取的 仓库代码
				        username: 15623632167
				        password: chen4852010
				  ####读取的默认分支
				    label:(没什么用,就是说如果 你通过rest规则 去访问 配置文件,如果你选择的规则
				    		是不带 分支名的,那默认就是 你配置的 label,不是说 配置了这个label,通过rest
				    		风格访问,就只能访问 master分支下的 config目录了)
				    
			4.配置后,代表 config-server和 git仓库连接了,即配置中心可以读取github上的配置文件了
			  同时 也可以 根据 rest规则 去访问 configserver 从而去 读取到 git
			
			5.从 configserver 间接 访问 git 的 rest规则
				http://config-server的host:port/git分支名/具体的 配置文件名
				具体就是 http//...../{label}/{application}-{profile}.yml 和上面一个意思
			(注意:当在读取规则中 指定了 git分支名,那配置文件的 label配置失效
			  如果没有指定,默认依据配置文件的 label git分支)

			6. 注意:configserver的最重要的 一特点,也是它作为成为 配置中心特点的 一点就是
			   与 git联系后,将 git上的 配置信息,以rest接口的形式,由configserver暴露出来,
			   这样其他服务或请求,可以配置或访问 这个 configserver 的git rest规则,去完成git
			   上配置文件的读取,
			   具体的 rest风格的规则就是 //config-server的host:port/git分支名/具体的 配置文件名
			   也就是  http//...../{label}/{application}-{profile}.yml

			7.总之就2个概念要区分开,configserver 读取git 的配置规则,和请求和其他服务 通过
			  请求 和 配置 rest规则 的 访问地址,间接访问 configserver,去访问到 git 这两个概念要
			  区分开,一个是configserver 读 git的配置规则,一个是其他服务去读configserver间接读
			  git 的 rest形式的访问规则
		
	2.客户端(连接 配置中心的配置,从而间接 连接 github)
		1.客户端 配置 rest形式的读取规则,直接访问 configserver,间接访问 git config 
		
		2.客户端的配置
			1.配置文件用 bootstrap.yml(来读取 配置中心的 公共配置文件)(优先级高,不会被同名覆盖)
			  用Application.yml 来定制 本系统的 配置向

			2.bootstrap.yml中的配置
				cloud:
				#config客户端配置
				  config:
				    label: master   #分支名
				    name: config   #github上配置文件的 前半部分名称
				    profile: dev    #github上配置文件的 后半部分名称后缀
				    uri: http://host/port    #配置中心的 地址
			上述4个配置项就是拼接一个 rest地址 访问 configserver
			例: uri/label/name-profile.yml 这样就通过 配置中心 间接 读取到了 github上的 配置文件的 内容
			      http://configserver-host/port/master/config-dev.yml

			这样本系统就有了 bootstrap.yml +config-dev.yml +application.yml 三个配置文件
			默认bootstrap的优先级  >config-dev的  >applcation.yml的

	3.配置中心的动态刷新问题
		(就是,git上的配置文件修改了,配置中心不用重新启动可以访问到 新修改的 github上的配置文件
		  但是,客户端 访问通过配置中心 间接 访问 github, 还是原来未修改的 配置文件的值,需要重新启动)
		  
		  1.手动动态刷新
		  	1.在pom中 引入 actuator 监控
		  	
		  	2.修改 yml,暴露 监控端点
		  		management:
					  endpoints:
					  	web:
					  	  exposure:
					  	    include: '*'
					  	    
		  	3.在 controller上 添加 @refreshScope
		  	
		  	4.每次 git作修改 ,需要 运维人员 发送 post请求,刷新 客户端
		  	  这样客户端可以监控到 刷新,并refresh,这样就避免了 服务重启

		问题:若微服务很多,每次 git修改配置文件,都得手动 给客户端 发送一个 通知post请求
		能否广播,一次通知,处处生效? 而且 指定通知哪些刷新,哪些不用通知刷新

	4.配置中心 读 git的 机制是什么?
		配置中心 读 git的机制,是时刻 去 给 git发请求 主动拉取,所以可以及时更新
		
	5.服务 读 配置中心 git 的机制是什么?
		只会主动读取一次,后面git更新后 也不会读取,如果想让其读取,需要服务开启监控,
		而且,需要 给服务 发一个通知,正因为 服务开启了监控,通知就能发到 服务那里,
		然后服务 就又去 主动 拉取一次

Bus消息总线

(解决,广播通知config-client 刷新问题,和指定 具体的 config-client刷新)
(我们采用,bus/refresh -> config-server 去通知 所有 config-client去刷新的方案,而不是,bus/refresh -> 一个client 去通知 其他 client去刷新的方式)
本质 就是 服务开启监控,而且 一旦 git修改,mq主动去 通知 指定client去刷新,通知的方式由2种,通知configserver(configserver 去 通知其他 client),或者通知 一个 client(这个client去通知其他client),client收到通知后就会 去configserver 拉取一次 配置文件,要使用消息总线,必须有消息中间件的主机

rabbitmq 在 消息总线中的使用,就是 topic主题模式,生产者发一个消息(就是 http:post.... 通知client更新的请求)给 topic主题,主题去 推送 给 订阅它的 消费者,消费者消费到消息,执行回调函数,去 从 configserver 拉取 git配置

不选用 client去 通知 其他 client的原因

1.client就作client,不要给他 其他的职责,
2.client如果搭集群,一个client作 通知点,和其他同一个集群下的服务,就不对等
3.有一定局限性,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那会增加更多的修改

	1.Springcloud Bus 动态刷新全局刷新
		1.服务端
			1.pom
				1. actuator依赖
				2. cloud-bus-amqp依赖
				
			2.yml
				1.配置 rabbitmq的 配置项
				2.暴露 监控bus刷新 的端点(区别于 客户端的 暴露普通监控的端点)
					management:
					  endpoints:
					  	web:
					  	  exposure:
					  	    include: 'bus-refresh'
		2.客户端
			1.pom
				1. actuator依赖
				2. cloud-bus-amqp依赖
				
			2.yml
				1.配置 rabbitmq的 配置项
				2.暴露 普通监控 端点
					management:
					  endpoints:
					  	web:
					  	  exposure:
					  	    include: '*'
					  	    
		3.最后,git修改了,客户端不用重启就刷新了,运维给 服务端发送一个post请求
		 http://config-server/actuator/bus-refresh
		 这样服务端,就会通知所有 client 去刷新
		
	2.Springcloud Bus 动态刷新定点刷新
		1.服务端和客户端 和 springcloud Bus 动态刷新全局刷新 一样的配置
		  添加依赖,配置rabbitmq,暴露(监控bus刷新)/普通监控 的端点
		  
		2. 运维给 服务端 发送 post请求 时 带上具体 需要通知的 client
		  http://config-server/actuator/bus-refresh/{destination}
		  destination = service-name : port
		  config-server 通过 destination参数,指定需要更新的 配置的 服务或实例

Nacos 注册中心

	1.nacos = Eureka + 配置中心+bus
	
	2.nacos自带负载均衡(nacos依赖带了 ribbon依赖)
	 但是用 restTemplate 还是得在 @bean上加 @loadBalance 注册 ribbon组件
	 用feign调用,就不用加@loadBalance 注册 ribbon组件
	 
	3.ribbon支持 ap加cp模式的切换(用curl 命令做切换)

Nacos配置中心(数据源一定要配置在 bootstrap.yml里面,不能配置在 配置中心的 yaml文件里面,服务注册信息也得在bootstrap.yml里面,反正关键信息都得在bootstrap.yaml里面,不然将关键信息配置在配置中心,读取不到)

	1.nacos不仅可以做 注册中心,而且可以做 配置中心
	
	2.nacos配置中心的配置文件做修改了,再也不用 配置中心去 通知所有的 client去 刷新
	(虽然还是得加 @refreshScope注解)等于 加了 springcloud bus 的功能

	3.nacos配置中心 没有yml格式的配置文件,只有 yaml,虽然这两个一样,但是还是得 配成 yaml,不然nacos无法识别

	4.但是 你 本地的 yml的 配置 指定 nacos的配置文件 是 yml不是 yaml,包括 nacos的 也是yml的
	  只是你 指定的格式 是yaml,不要配置错,配错服务起不来

	4.nacos配置中心的 三级配置,即 namespace,group,dataId
		1.namespace > group > dataId
		
		2.通过三层来确定 唯一的 配置文件,那么给系统的,环境层次 更多的可能,更好的管理 系统的配置文件
		
		3.namespace + group + dataId 来确定 配置中心 具体的配置文件
		
		4.通常 namespace来区别 部署环境
		 	   group来区分 不同微服务(或将几个有关联的微服务为  设置为一组)
		 	   dataId来区分 同一个微服务的 不同实例(或 各个微服务的 不同实例)实例级别的
		 	   
		5.默认情况下 
			group的 默认值是:DEFAULT_GROUP
			namespace的 默认值是:public
	
		6.服务 配置文件 读取 配置中心 配置文件的 读取规则
		
			1.client端 有 2个配置文件 bootstrap.yml , application.yml
			  bootstrap优先加载,读取配置中心配置文件的 公共内容
			  application通常配置本服务 实例的 定制的 配置
			  两者一起组成这个服务的 整体配置

			2.读取规则
			{spring.applicaiton.name}-{spring.profile.active}.{spring.cloud.nacos.config.file-extension}
			
			spring.applicaiton.name 服务名
			spring.cloud.nacos.config.file-extension	 配置文件的格式 yml
			这两个一般配置在 bootstrap.yml里面
	
			spring.profile.active 激活环境
			这个一般配置在 Application.yml中

			这个拼接起来 就是 配置中心的 dataId
			
			group默认是 DEFAULT_GROUP 
				配置是 spring.cloud.nacos.config.group: 
				 
			namespace默认值是 public
				配置是 spring.cloud.nacos.config.namespace: 

			  namespace + group + dataId 可以找到 配置中心的 具体配置

nacos内置一个数据库,所有的注册信息和配置信息都在内置数据库里面,但是可以通过更改 配置文件,将数据库改成 自己本地的 mysql的数据库中去

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值