springCloud:
1.bootstrap.yml(bootstrap.properties)与application.yml(application.properties)执行顺序
### bootstrap.yml(bootstrap.properties)用来程序引导时执行,应用于更加早期配置信息读取,如可以使用来配置application.yml中使用到参数等
### application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
### bootstrap.yml 先于 application.yml 加载
应用场景 :
1.当使用 Spring Cloud Config Server的时候,你应该在 bootstrap.yml里面指定 spring.application.name和 spring.cloud.config.server.git.uri
2.一些加密/解密的信息
ribbon:
调用链路选择服务器逻辑
LoadBalancerClient(RibbonLoadBalancerClient) -> ILoadBalancer(ZoneAwareLoadBalancer) -> IRule (ZoneAvoidanceRule)
LoadBalancerClient:
转化URI,将含应用名称URI转化成具体主机+端口形式
选择服务实例,通过负载算法,选择指定服务中的一台机器实例
请求执行回调,针对选择后的服务实例,执行具体的请求回调操作
默认实现:RibbonLoadBalancerClient
LoadBalancerContext:
转化URI,将含应用名称URI转化成具体主机+端口形式
组件关联,关联RetryHandler、ILoadBalancer等
记录服务统计信息,记录请求时间、错误数量等
默认实现:RibbonLoadBalancerContext
ILoadBalancer:
增加服务器
获取服务器:通过关联Key获取、获取所有服务列表、获取可用服务器列表
服务器状态:标记服务器宕机
默认实现:ZoneAwareLoadBalancer
IRule
选择服务器,根据负载均衡器以及关联Key获取候选的服务器
默认实现:ZoneAvoidanceRule
IPing:
活动检测,根据指定的服务器,检测其是否活动
默认实现:DummyPing
ServerList:
获取初始化服务器列表
获取更新服务器列表
默认实现:ConfigurationBasedServerList或DiscoveryEnabledNIWSServerList
负载均衡器:
ILoadBalancer
BaseLoadBalancer
DynamicServerListLoadBalancer
ZoneAwareLoadBalancer
NoOpLoadBalancer
负载均衡规则接口
IRule:
随机规则:RandomRule
最可用规则:BestAvailableRule
轮训规则:RoundRobinRule
重试实现:RetryRule
客户端配置:ClientConfigEnabledRoundRobinRule
可用性过滤规则:AvailabilityFilteringRule
RT权重规则:WeightedResponseTimeRule
规避区域规则:ZoneAvoidanceRule
ping策略
IPingStrategy
NoOpPing
DummyPing
PingConstant
PingUrl
NIWSDiscoveryPing
Hystrix:
Hystrix能做什么
通过hystrix可以解决雪崩效应问题,它提供了资源隔离、降级机制、融断、缓存等功能。
资源隔离:包括线程池隔离和信号量隔离,限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用。
降级机制:超时降级、资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据。
融断:当失败率达到阀值自动触发降级(如因网络故障/超时造成的失败率高),熔断器触发的快速失败会进行快速恢复。
缓存:返回结果缓存,后续请求可以直接走缓存。
请求合并:可以实现将一段时间内的请求(一般是对同一个接口的请求)合并,然后只对服务提供者发送一次请求。
初始化顺序: @EnableCiruitBreaker -> EnableCircuitBreakerImportSelector -> HystrixCircuitBreakerConfiguration
HystrixCircuitBreakerConfiguration
自动装配Hystrix组件:
Hystrix命令切面: HystrixCommandAspect
Hystrix Endpoint: HystrixStreamEndpoint
Hystrix指标: HystrixMetricsPollerConfiguration
HystrixCommandAspect
拦截标注@HystrixCommand或@HystrixCollapser的方法(@Aroud)
生成拦截方法原信息(MetaHolderFactory)
生成HystrixInvokable(HystrixCommandFactory)
选择执行模式(Observable或非Observable)
SpringFactoryImportSelector
选择/META-INF/spring.factories中注解类型(泛型),所配置的SpringConfiguration类
EnableCircuitBreakerImportSelector、EnableDiscoveryClientImportSelector
1.使用@EnableHystrix 实现服务提供方短路
@HystrixCommand(
//Command 配置
commandProperties = {
// 设置操作时间为 100 毫秒
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "100")
},fallbackMethod = "fallbackForGetUsers" //设置 fallback 方法
)
@GetMapping("/user/list")
public Collection<User> getUsers() throws InterruptedException {
long executeTime = random.nextInt(200);
// 通过休眠来模拟执行时间
System.out.println("Execute Time : " + executeTime + " ms");
Thread.sleep(executeTime);
return userService.findAll();
}
/**
* {@link #getUsers()} 的 fallback 方法
*/
public Collection<User> fallbackForGetUsers() {
return Collections.emptyList();
}
2.使用@EnableCircuitBreaker 实现服务调用方短路
/**
* 申明 具有负载均衡能力 {@link RestTemplate}
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
3.增加编程方式的短路实现
public class UserRibbonClientHystrixCommand extends HystrixCommand<Collection> {
private final String providerServiceName;
private final RestTemplate restTemplate;
public UserRibbonClientHystrixCommand(String providerServiceName, RestTemplate restTemplate) {
super(HystrixCommandGroupKey.Factory.asKey(
"User-Ribbon-Client"),
100);
this.providerServiceName = providerServiceName;
this.restTemplate = restTemplate;
}
/**
* 主逻辑实现
*
* @return
* @throws Exception
*/
@Override
protected Collection run() throws Exception {
return restTemplate.getForObject("http://" + providerServiceName + "/user/list", Collection.class);
}
/**
* Fallback 实现
*
* @return 空集合
*/
protected Collection getFallback() {
return Collections.emptyList();
}
}
zuull:
两种启动方式:
@EnableZuulServer
DispatcherServlet
ZuulHandlerMapping
ZuulController
ZuulServlet
ZuulFilter
@EnableZuulProxy
DispatcherServlet
ZuulHandlerMapping
ZuulController
ZuulServlet
RibbonRoutingFilter
eureka-server:
1. 错误: Instances currently registered with Eureka
解决问题:
## Spring Cloud Eureka 服务器作为注册中心,通常情况下,不需要再注册到其他注册中心去,同时,它也不需要获取客户端信息
### 取消向注册中心注册
eureka.client.register-with-eureka = false
### 取消向注册中心获取注册信息(服务、实例信息)
eureka.client.fetch-registry = false
## 解决 Peer / 集群 连接问题
eureka.instance.hostname = localhost
eureka.client.serviceUrl.defaultZone = http://${eureka.instance.hostname}:${server.port}/eureka
1. @EnableDiscoveryClient与@EnableEurekaClient区别
注解@EnableEurekaClient上有@EnableDiscoveryClient注解,可以说基本就是@EnableEurekaClient有@EnableDiscoveryClient的功能,其实@EnableEurekaClientz注解就是一种方便使用eureka的注解而已,可以说使用其他的注册中心后,都可以使用@EnableDiscoveryClient注解,但是使用@EnableEurekaClient的情景,就是在服务采用eureka作为注册中心的时候,使用场景较为单一。
服务注册流程:
Eureka Client 的注册是由 Spring Cloud 的 AutoServiceRegistration 自动注册发起, 在设置应用实例 Instance 初始状态为 UP 时, 触发了 InstanceInfoReplicator#onDemandUpdate()按需更新方法, 将实例 Instance 信息通过 DiscoveryClient 注册到 Eureka Server, 期间经过了一些 EurekaHttpClient 的装饰类, 实现了诸如定期重连, 失败重试, 注册重定向, 统计收集 Metrics 信息等功能, 最后由 JerseryClient 发送 POST 请求调用 Eureka Server 的[/eureka/apps / 应用名] 端点, 请求体携带 InstanceInfo实例信息, 完成注册。在服务注册后,Eureka Client会维护一个心跳来持续通知Eureka Server,说明服务一直处于可用状态,防止被剔除。Eureka Client在默认的情况下会每隔30秒(eureka.instance.leaseRenewallIntervalInSeconds)发送一次心跳来进行服务续约。 Eureka Server之间会互相进行注册,构建Eureka Server集群,不同Eureka Server之间会进行服务同步,用来保证服务信息的一致性。
服务调用流程:
Eureka Client在刚启动的时候会从Eureka Server全量获取一次注册信息,同时初始化Eureka Client本地实例信息缓存定时更新任务,默认30s一次 registryFetchIntervalSeconds = 30。同时,为了性能考虑,Eureka Server也会维护一份只读的服务清单缓存,该缓存每隔30秒更新一次。 服务消费者在获取到服务清单后,就可以根据清单中的服务列表信息,查找到其他服务的地址,从而进行远程调用。Eureka有Region和Zone的概念,一个Region可以包含多个Zone,在进行服务调用时,优先访问处于同一个Zone中的服务提供者。
服务下线流程:
当Eureka Client需要关闭或重启时,就不希望在这个时间段内再有请求进来,所以,就需要提前先发送REST请求给Eureka Server,告诉Eureka Server自己要下线了,Eureka Server在收到请求后,就会把该服务状态置为下线(DOWN),并把该下线事件传播出去。
服务剔除:
有时候,服务实例可能会因为网络故障等原因导致不能提供服务,而此时该实例也没有发送请求给Eureka Server来进行服务下线,所以,还需要有服务剔除的机制。Eureka Server在启动的时候会创建一个定时任务,每隔一段时间(默认60秒),从当前服务清单中把超时没有续约(默认90秒,eureka.instance.leaseExpirationDurationInSeconds)的服务剔除。
自我保护:
既然Eureka Server会定时剔除超时没有续约的服务,那就有可能出现一种场景,网络一段时间内发生了异常,所有的服务都没能够进行续约,Eureka Server就把所有的服务都剔除了,这样显然不太合理。所以,就有了自我保护机制,当短时间内,统计续约失败的比例,如果达到一定阈值,则会触发自我保护的机制,在该机制下,Eureka Server不会剔除任何的微服务,等到正常后,再退出自我保护机制。自我保护开关(eureka.server.enable-self-preservation: false)
Eureka与Consul对比:
Consul强一致性(C)带来的是:(CA)
服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的节点都写入成功才认为注册成功
Leader挂掉时,重新选举期间整个consul不可用。保证了强一致性但牺牲了可用性。
Eureka保证高可用(A)和最终一致性:(AP)
服务注册相对要快,因为不需要等注册信息replicate到其他节点,也不保证注册信息是否replicate成功
当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性。
其他方面,eureka就是个servlet程序,跑在servlet容器中; Consul则是go编写而成。
feign(声明式HTTP客户端调用):
Decoder/Encoder: ResponseEntityDecoder/SpringEncoder
Logger: slf4jLogger
Contract: SpringMvcContract
Feign.Builder: HystrixFeign.Builder
client: LoadBalancerFeignClient (Ribbon 激活时)
处理流程:
1.基于面向接口的动态代理方式生成实现类
2.根据接口类的注解声明,解析出底层的methodhandler
3.基于requestbean动态生成request
4.encoder将bean包装成请求
5.拦截器负责对请求和返回进行装饰处理
6.日志记录
7.基于重试器发送http请求,可基于不同的http框架处理