Spring Cloud 组件

1.eureka注册中心原理简述

1.服务注册:

        Eureka Client 会通过发送rest请求的方式向eureka服务端注册自身元数据:ip地址,端口,运行状况等信息,服务端会把注册信息存储在一个双层map中。

  • Eureka 的数据存储分了两层:数据存储层和缓存层。

        Eureka Client 在拉取服务信息时,先从缓存层获取,如果获取不到,先把数据存储层的数据加载到缓存中,再从缓存中获取。值得注意的是,数据存储层的数据结构是服务信息,而缓存中保存的是经过处理加工过的、可以直接传输到 Eureka Client 的数据结构。

2.服务续约:

        eureka客户端每30秒发送一次心跳来续约,告知此客户端正常,如果eureka服务端90秒没收到心跳,则将其从注册表删除。

3.获取注册表信息:

        客户端通过rest请求从服务端获取注册表信息,缓存在本地,服务调用的时候,会从注册表查找其它服务,用于服务发现,从而发起远程调用。每30秒更新一次

4.服务调用

        客户端获取到服务清单后,就可以从中查找其它服务地址进行远程调用,会通过ribbon自动进行负载均衡。

5.eureka高可用:服务同步

        配置eureka集群,服务之间会相互注册,客户端的注册信息和续约信息被复制到集群中的所有节点,只要有一个节点活着都可以发挥注册中心的作用。

6.服务剔除

        eureka Client 启动的时候创建一个定时任务,Eureka Server会每60秒遍历一次注册表中的信息,把超过90秒还没有续约的服务剔除。

7.自我保护机制

        当网络一段时间内发生了异常,所有服务都没能够续约,eureka server会把所有服务剔除,显然不太合理,所以就有了自我保护机制。

        服务端如果15分钟内收到的心跳请求率,如果低于85%,可能网络故障,注册表则不再删除,但是提供正89常的服务注册和查询,当恢复正常时,则取消保护机制

8.eureka客户端注册实例为什么这么慢:

(1)默认设置了延时40秒

(2)eureka服务端维护每30秒更新响应缓存

(3)客户端每30秒更新缓存

(4)ribbon从本地获取服务列表时,本身也维护一个缓存,30秒刷新一次

2.Feign远程调用原理

  1. 首先通过@EnableFeignClients注解开启FeignClient 的功能。只有这个注解存在,才会在程序启动时开启对@FeignClient注解的包扫描。
  2. 根据Feign的规则实现接口,并在接口上面加上@FeignClient注解。
  3. 程序启动后,会进行包扫描,扫描所有的@ FeignClient 的注解的类,并将这些信息注入IoC容器中。
  4. 当接口的方法被调用时,通过JDK的代理来生成具体的RequestTemplate模板对象。
  5. 根据RequestTemplate再生成Http请求的Request对象。
  6. Request 对象交给Client去处理,其中Client的网络请求框架可以是HtpURLConnection、HttpClient和OkHttp。
  7. 最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。

3.Ribbon负载均衡

1.基于Ribbon方式的负载均衡,Netflix默认提供了七种负载均衡策略,

2.@LoadBalanced

1.当使用RestTemplate进行远程服务调用时,假如需要负载均衡,还可以在RestTemplate对象构建时,使用@LoadBalanced对构建RestTemplate的方法进行修饰,例如在ConsumerApplication中构建名字为loadBalancedRestTemplate的RestTemplate对象:

@Bean
@LoadBalanced
public RestTemplate loadBalancedRestTemplate(){
    return new RestTemplate();
}

2.RestTemplate在发送请求的时候会被LoadBalancerInterceptor拦截,它的作用就是用于RestTemplate的负载均衡,LoadBalancerInterceptor将负载均衡的核心逻辑交给了loadBalancer,核心代码如下所示(了解):

public ClientHttpResponse intercept(final HttpRequest request, 
    final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
    final URI originalUri = request.getURI();
    String serviceName = originalUri.getHost();
    return this.loadBalancer.execute(serviceName, 
    requestFactory.createRequest(request, body, execution));
}

总结:@LoadBalanced注解是属于Spring,而不是Ribbon的,Spring在初始化容器的时候,如果检测到Bean被@LoadBalanced注解,Spring会为其设置LoadBalancerInterceptor的拦截器。

4.hystrix容错组件

        hystrix是一个容错组件,实现了超时机制和断路器模式,提供了熔断和降级。

4.1 降级

        降级其实就相当于,当我们向一个服务发起请求,当请求超时了,就会把这次请求记录到服务中,然后就会尝试向其他服务发请求,如果还没成功,就对这次请求进行处理(怎么处理取决于业务需求如)就相当于try catch一样的逻辑,当然hystrix底层使用aop来实现的。

4.2 隔离和限流

        Hystrix采取了bulkhead舱壁隔离技术,将外部依赖进行资源隔离,避免任何外部依赖的故障导致本服务崩溃。

舱壁隔离
是说将船体内部空间区隔划分成若干个隔舱,一旦某几个隔舱发生破损进水,水流不会在其间相互流动,如此一来船舶在受损时,依然能具有足够的浮力和稳定性,进而减低立即沉船的危险。

        每当向服务发起一个请求时,就是会发起一个http请求,每一个http请求就要开启一个线程,然后等待服务返回信息,这容易导致线程的堆积,所以就可以用http的URI作为一个标识,然后相同的URI可以开启一个线程池,然后线程池中限定线程数,这样就可以设置拒绝策略,当线程池满了,就可以快速的抛出异常或者拒绝请求,用线程池做到线程隔离来达到限流。

4.3 熔断

        熔断就是有一个阈值,向服务发起请求后,如果不成功,就会记录次数,然后当连续失败次数达到阈值时,下次请求的时候就会直接把这个服务停止。请求有三种状态,可以请求(开),不可请求(关),还有一个中间状态,相当于半开状态,半开状态是什么意思呢,就是可以尝试着去请求,就可以在关闭状态后一段时间,发一个请求尝试一下是否可以请求成功,如果是吧,继续保持关闭状态,如果请求成功,则变成开放状态。

        首先Hystrix发生在请求这一端,所以我们先在consumer端引入Hystrix的依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  <version>2.1.1.RELEASE</version>
</dependency>

然后我们来整合一下Hystrix和feign

        首先呢,feign有两种方式来指定熔断策略,第一种是直接指定一个类,第二种是用fallbackFactory。区别是一种是可以直接熔断,一种是可以根据不同的类型,进行不同的处理。

        首先我们看看第一种,我们可以在@FeignClient注解中加上参数fallback=XXX.class,如下,我们这里的是面向接口编程,可以看我上一篇博客是讲如何用feign的。fallback里面的类也要新建一下。

    //这里name是eureka里的服务名
    @FeignClient(name = "user-provider",fallback = UserProviderBack.class)
    public interface UserAPI extends ProviderApi {
     
    }

        新建UserProviderBack类然后实现我们的UserAPI,把所有的方法都实现一遍,这种熔断策略是针对于每个请求资源的接口。每个接口都是同的。注意这个类要加上@Component注解,就是把这个类给到spring容器去管理。

@Component
public class UserProviderBack implements UserAPI {
    @Override
    public String alive() {
        return "降级了!!!!!!!!!!!!!";
    }
 
    @Override
    public HashMap getMapById(Integer id) {
        return null;
    }
}

        最后一步就是要配置properties文件,因为默认Feign在请求发生错误时,是不会用Hystrix做服务降级处理。

feign.hystrix.enabled=true

        还可以用不用fallback,改用fallbackFactory

@FeignClient(name = "user-provider",fallbackFactory = UserProviderBackFactory.class)
public interface UserAPI extends ProviderApi { 
}

        然后新建UserProviderBackFactory这个类,去实现FallbackFactory接口,这个接口我们可以把我们的接口类型传进去,然后重写create方法,如图,这里的throwable就是具体的异常信息,就可以根据不同的错误类型,进行catch,然后处理。

@Component
public class UserProviderBackFactory implements FallbackFactory<UserAPI> {
    @Override
    public UserAPI create(Throwable throwable) {
        return new UserAPI() {
            @Override
            public String alive() {
               
                return "又又又降级了";
            }
 
            @Override
            public HashMap getMapById(Integer id) {
                return null;
            }
        };
    }
}

5.zuul网关

        该组件是负责网络路由的,假设你后台部署了几百个服务,现在有个前端兄弟,人家请求是直接从浏览器那儿发过来的。打个比方:人家要请求一下库存服务,你难道还让人家记着这服务的名字叫做inventory-service,并且部署在5台机器上,就算人家肯记住这一个,那你后台可有几百个服务的名称和地址呢?难不成人家请求一个,就得记住一个?哈哈哈

        上面这种情况,压根儿是不现实的。所以一般微服务架构中都必然会设计一个网关在里面,像android、ios、pc前端、微信小程序、H5等等,不用去关心后端有几百个服务,就知道有一个网关,所有请求都往网关走,网关会根据请求中的一些特征,将请求转发给后端的各个服务。

5.1 Zuul 网关主要由以下几个组件构成:

  • Filter:过滤器,可以在请求被路由前或者之后添加一些处理逻辑。
  • Route:路由,将请求路由到不同的后端服务上。
  • Ribbon:负载均衡器,Zuul 默认使用 Ribbon 进行负载均衡。
  • Hystrix:容错处理器,可以实现限流和熔断机制。

Zuul 的过滤器链是整个网关的核心部分,它由多个过滤器构成,每个过滤器都负责不同的处理逻辑,比如请求的鉴权、转发等操作。过滤器链在处理请求的过程中,会依次执行这些过滤器,从而实现对请求的全生命周期管理,具体流程如下图所示。

5.2 Zuul 网关可以应用于各种场景中,主要包括以下几个方面:

  • 负载均衡:Zuul 可以将请求分发到不同的后端服务上,实现负载均衡的功能。
  • 路由转发:Zuul 可以根据请求的 URL,将请求转发到不同的后端服务上,实现路由转发的功能。
  • 鉴权和安全:Zuul 可以对请求进行鉴权和认证,保障系统的安全性。
  • 限流和熔断:Zuul 可以在高并发的情况下,通过限流和熔断机制,保障后端服务的可用性。

6.Apollo配置中心

服务通过app-id与Apollo获取配置,获取到配置后会被缓存到本地。
Apollo可以实现WEB页面对配置进行CRUD操作(SpringCloud Config不具备)。
Apollo的配置存储在MySQL中(SpringCloud Config存储于git)
Apollo轻量级,SpringCloud Config则需要依赖于MQ、BUS消息总线

Apollo分为三个服务:portal、admin、config
portal:UI页面
admin:用户、角色管理,CRUD操作
config:用户和服务进行连接,为服务pull和push配置。config服务内置了Eureka

7、流程总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值