spring-Cloud的核心组件原理

Spring Cloud是一个用于构建分布式系统的开发工具包,其中也包括了几个核心组件,如Ereka、Ribbon、Feign、Hystrix、Zuul等;

这里会讲解核心组件的实际应用于原理。

一、spring-cloud核心组件:Eureka

这里介绍一下Eureka的注册原理:

1) 服务提供者将自己的IP和端口注册到注册中心上

2) 服务提供者每隔一段时间向注册中心发送心跳包

3) 服务消费者调用提供者之前,先向注册中心查询提供者的IP和端口

4) 获得服务清单中的IP和端口后,消费者调用提供者

5) 服务提供者的IP和端口改变后,通过心跳机制更新注册中心上的服务清单

假如我们设置三个服务,eureka-service、order-service、proudct-serive,把ereka-service当成是我们的主服务。

 这个时候我们想通过一个主服务去调用其他的服务该怎么办?

Eureka就可以帮我们解决这个问题,Eureka就是微服务架构中的注册中心,专门负责一些服务的注册和发现。

想要用到这个Eureka,我们需要导入相关依赖

首先你得让整个服务有一个主从关系,先往主服务中导入一个依赖如下

<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

从服务导入

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

这两者区别在于,eureka-service是一个注册中心,里面存有一个注册表,专门用来存放所注册的从服务器的ip和端口。从服务可以通过eureka-client来把信息存到rureka中

添加主服务的配置文件,且在主服务的启动类加 @EnableEurekaServer

server.port=8000
# 服务器域名
eureka.instance.hostname=127.0.0.1
# 设置不拉取服务清单
eureka.client.fetch-registry=false
# 设置不注册当前服务
eureka.client.register-with-eureka=false
# 定义注册服务的地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka

添加从服务的配置文件,且从服务的启动类加 @EnableEurekaClient

# 服务名称
spring.application.name=xxxx
# 设置拉取服务清单
eureka.client.fetch-registry=true
# 设置注册当前服务
eureka.client.register-with-eureka=true
# 定义注册服务的地址
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8000/eureka

通过127.0.0.1我们可以看到注册表中我们成功注册的两个从服务

 这个地方我们只需要了解以下:

  • Eureka Client:负责将这个服务的信息注册到Eureka Server中
  • Eureka Server:注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号

二、spring-cloud的核心组件:ribbon

我们发现从服务变多了呢,现在不知道该访问哪个呢?ribbon就可以解决这个问题。它的作用是负载均衡,会帮你在每次请求时选择一台机器,均匀的把请求分发到各个机器上。

SpringBoot2.7.2下使用Ribbon,2.7.2开始使用LoadBalancer

1) 导入依赖,在导入Eureka-client依赖时,自动导入Ribbon依赖

2) 使用 @LoadBalanced 后生效

3) 配置负载均衡策略

负载均衡策略

 在使用前需要添加一个配置类

@Configuration
public class RestTemplateConfig {

    /**
     * 向容器提供HTTP客户端
     * @return
     */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

我选用的是一个随机选择一个可用的服务器

product-server.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

如果没有用这个策略的话,每次访问的都会按照一个顺序,这里用来ribbon之后,每次都会随机选择一个有用的进行访问了。

三、spring-cloud的核心组件:Hystrix

我们在实现一个服务的时候,会有很多线程进行访问,假如有100个线程在运行中,发现有一个服务出现了错误,访问不了,有没有设置跳过,就会卡在这,然后访问其他服务也会失败,导致会出现问题

 如上图,这么多服务互相调用,要是不做任何保护的话,某一个服务挂了,就会引起连锁反应,导致别的服务也挂。比如积分服务挂了,会导致订单服务的线程全部卡在请求积分服务这里,没有一个线程可以工作,瞬间导致订单服务也挂了,别人请求订单服务全部会卡住,无法响应。

出现这个问题,Hystrix就能解决,hystrix是一个可以实现隔离和熔断的框架,会生产众多线程池,就比如eureka-service想要访问order-service做修改,这个访问就是一个线程池,就专门只做访问做修改这一个操作。然后eureka-service想要访问product做添加操作就能正常执行,因为是两个完全不同的操作,所以这里毫无影响。

思考一下,如果我们在执行一系列流程的时候,中间一个流程出现了问题,但是每次都会进行访问,这样是不是会显得很浪费时间,所以比比避免这个问题,我们就把他熔断,就是说,在每次到这的时候返回,跳过,但是这个流程放在这肯定有它的用处,不能都跳过了,我们就加一个降级操作,可以将每次访问想要进行的操作返回到数据库,后面再单独处理。

想用到这个操作也需要

1)添加一个依赖

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

 2)启动类加 @EnableHystrix

3) 在需要熔断的方法上加 @HystrixCommand

4) 设置降级方法,返回兜底数据

@RestController
public class ProductController {

    @Autowired
    private ProductService productService;
    Long start = System.currentTimeMillis();
    @Value("${server.port}")
    private Integer port;
//    @HystrixCommand(fallbackMethod = "getProductByIdFallback")
    @GetMapping("product/{id}")
    public Product getProductById(@PathVariable Long id){
        start = System.currentTimeMillis();
        try {
            Thread.sleep(2000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        Product product = productService.getById(id);
        product.setName(product.getName()+"-from:"+port);
        System.out.println("查询了"+port+"服务器"+product);
        return product;
    }

    public Product getProductByIdFallback(Long id){
        long time = System.currentTimeMillis();
        System.out.println("熔断时间"+(time-start));
        Product product = new Product();
        product.setId(id);
        product.setName("兜底商品数据");
        return product;
    }
}

设置熔断时间

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000

四、spring-cloud的核心组件:feign

问题:每个服务的功能我们都实现了,但是不能光有功能,不去用嘛,所以我们该怎么去调用功能呢,且每个服务之间也要联系哇,我们总是需要一些挥挥手就能干大事的东东,这个时候feign出现了,有了它,问题自然就简单多了。只需要写一个@FeignClient注解,人家Feign Client会在底层根据你的注解,跟你指定的服务建立连接、构造请求、发起靕求、获取响应、解析响应,等等。

光知道好用还不行,还得会用嘞

首先还是老规矩,导依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

然后就是编写客户端接口,

@FeignClient(value = "product-service",fallback = ProductServiceFallback.class)
public interface ProductServiceClient {
    @GetMapping("product/{id}")
    Product getProductById(@PathVariable Long id);
}

接口写好了,现在需要找到它,我们需要扫描,在启动类添加注解进行扫描

@EnableFeignClients(basePackages = "com.blb.common.feign")

在serviceImpl进行调用服务

    @Autowired
    private ProductServiceClient productServiceClient;
    @Override
    public Order getOrderById(Long id){
        Order order = orderMapper.selectById(id);
        Product productById = productServiceClient.getProductById(order.getProductId());
        order.setProduct(productById);
        return order;
    }

feign这么强嘛!它的原理也是一样,

  • 首先,如果你对某个接口定义了@FeignClient注解,Feign就会针对这个接口创建一个动态代理
  • 接着你要是调用那个接口,本质就是会调用 Feign创建的动态代理,这是核心中的核心
  • Feign的动态代理会根据你在接口上的@RequestMapping等注解,来动态构造出你要请求的服务的地址
  • 最后针对这个地址,发起请求、解析响应

五、spring-cloud的核心组件:gateway

最后我们说一下gateway,这个组件是专门负责网络路由的

如果我们有很多服务,这里就当有100个服务吧,100个服务就有100个路由,如果有人想访问,就需要记住这个路由,访问一个记住一个,估计没几个就绷不住了吧。所以嘛,我们不能这么不厚道,我们得用gateway。

我们可以设置一个网关,这样无论有多少服务,我们都得经过网关,网关会通过分析请求的一些数据,发送给后端一些对应的服务,这样就方便了很多,减少了一些不必要的操作。

而且有一个网关之后,还有很多好处,比如可以做统一的降级、限流、认证授权、安全,等等。

gateaway的原理:

1、首先客户端会发送一个请求到gateway中

2、gateway会将请求发送到handlerMapping处理器映射

3、处理器映射会根据请求周到对应的handler执行这个请求

4、请求执行会经过一个过滤器链,过滤器分为两种:pre前置过滤器,主要用于鉴权;post后置过滤器,用于性能监控和日志记录

5、如果请求正常通过,就能访问代理的服务,最后把数据返回给客户端。

总结:这就是spring-cloud的几个核心组件

  • Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里
  • Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台
  • Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
  • Hystrix:发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题
  • Zuul:如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值