Spring Cloud之五大组件

06-01 1047阅读

Spring Cloud的5大组件

Eureka:注册中心

Ribbon:负载均衡

Feign:远程调用

Hystrix:服务熔断

Zuul/Gateway:网关

  • Spring Cloud之五大组件

    特别地,在Spring Cloud Alibaba中

    Nacos:注册中心/配置中心

    Ribbon:负载均衡

    Feign:服务调用

    Sentinel:服务保护

    Gateway:服务网关

    1、注册中心

    注册中心的核心作用:服务注册和发现

    常见的注册中心有:Eureka、Nocas、Zookeeper

    1.1、Eureka

    Eureka是Netflix开发的一个用于实现服务注册和发现的服务。Eureka主要由两部分组成:Eureka服务器和Eureka客户端。

    (1)服务注册

    服务方需要把自己的信息注册到eureka,由eureka来保持这些信息(如服务名称、IP、端口等)。

    (2)服务发现

    消费者向eureka拉取服务列表信息,如果服务方有集群,则消费方会利用负载均衡算法,选择一个发起调用。

    (3)服务监控

    服务方会每隔30秒向eureka发送心跳,报告健康状态,如果eureka服务90秒没收到心跳,从eureka中剔除。

    Spring Cloud之五大组件

    1.2、Nacos

    Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它支持多种服务治理能力,包括服务注册与发现、动态配置管理、动态DNS服务等。

    (1)注册服务

    Nacos作为注册中心,接收客户端(服务实例)发起的注册请求,并将注册信息存放到注册中心进行管理。注册请求的处理包括客户端组装注册请求、随机选择集群中的一个Nacos节点发起注册、实现负载均衡、路由转发、处理请求、保证数据最终一致性等步骤。

    (2)服务发现

    Nacos通过维护服务实例的列表,使得服务消费者可以通过Nacos查询到可用服务的列表,进而进行服务调用。

    (3)临时实例与永久实例

    Nacos中区分了临时实例和永久实例。

    临时实例在注册到注册中心后仅保存在服务端内部缓存中,不会持久化到磁盘。当服务实例异常或下线时,会从服务注册表中剔除。

    而永久实例不仅存在于服务注册表中,还会被持久化到磁盘文件中。即使服务实例异常或下线,Nacos也不会将其从服务注册表中剔除,而是将其健康状态设置为不健康。

    1.3、nacos和eureka的区别

    在都作为注册中心的前提下

    (1)共同点

    1)都支持服务注册和服务拉取

    2)都支持服务方心跳方式做健康检测

    (2)不同点

    1)nacos支持“服务端”主动检测“服务方”状态:临时实例采用心跳模式,非临时实例采用主动检测模式

    2)临时实例心跳不正常会被剔除,非临时实例则不会被剔除

    3)nacos支持服务列表变更的消息推送模式,服务列表更新更及时

    4)nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;eureka采用AP方式

    AP模式(Availability Priority Mode)高可用性

    CP模式(Consistency Priority Mode)一致性

    特别地,nacos还支持了配置中心,eureka则只有注册中心。

    2、负载均衡

    负载均衡ribbon,发起远程调用feign

    Spring Cloud之五大组件

    2.1、Ribbon负载均衡策略有哪些

    RoundRobinRule:简单轮询服务列表来选择服务器

    WeightedResponseTimeRule:按照权重来选择服务器,响应时间越长,权重越小

    RandomRule:随机选择一个可用的服务器

    BestAvailableRunle:忽略那些短路的服务器,并选择并发数较低的服务器

    RetryRule:重试机制的选择逻辑

    AvailabilityFilteringRule:可用性敏感策略,先过滤非健康的,再选择连接数较小的实例

    ZoneAvoidanceRule:以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后对Zone内的多个服务做轮询。

    2.2、自定义负载均衡策略的实现

    自定义负载均衡策略的实现,有两种方式

    方式一:创建类实现IRule接口,可以指定负载均衡策略(全局)

    Spring Cloud之五大组件

    方式二:在客户端的配置文件中,可以配置某一个服务调用的负载均衡策略(局部)

    Spring Cloud之五大组件

    2.3、示例代码

    自定义负载均衡策略可以通过实现com.netflix.loadbalancer.IRule接口来完成。

    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RoundRobinRule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
     
    @Configuration
    public class CustomLoadBalancerConfiguration {
     
        @Bean
        public IRule randomRule() {
            return new RandomRule(); // 自定义的轮询策略
        }
     
    }
     
    class RandomRule extends RoundRobinRule {
        @Override
        public void initWithNiwsConfig(IClientConfig clientConfig) {
            // 初始化逻辑,如果需要的话
        }
     
        @Override
        public Server choose(ILoadBalancer lb, Object key) {
            if (lb == null) {
                return null;
            }
            Server server = null;
            while (server == null) {
                // 随机从服务器列表中选择一个
                List upList = lb.getReachableServers();
                List allList = lb.getAllServers();
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }
                int index = new Random().nextInt(serverCount);
                server = upList.get(index);
                if (server == null) {
                    Thread.yield();
                }
            }
            return server;
        }
    }
    

    在这个示例中,我们定义了一个RandomRule类,它继承自RoundRobinRule(轮询策略),并覆盖了choose方法,使其实现随机选择服务器的逻辑。这个自定义策略可以替代默认的轮询策略。通过将RandomRule作为一个Bean注册到Spring上下文中,它将会被应用到使用Ribbon进行负载均衡的服务调用中。

    3、远程调用

    3.1、Feign

    Feign是一个声明式的Web服务客户端,用来简化HTTP远程调用。在Spring Cloud中,Feign可以用来封装HTTP调用的接口,使得调用远程服务就像调用本地方法一样简单。通过创建一个接口并注解,Feign可以生成实现该接口的动态代理,从而允许调用其他服务。

    (1)Feign支持HTTP的各种方法

    包括GET、POST、PUT、DELETE和PATCH等。通过使用@RequestMapping注解及其变种(如@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping)来指定HTTP方法。

    (2)如何配置Feign的超时时间

    可以通过在Feign客户端的配置文件中设置超时时间来配置Feign的超时时间。例如,将连接超时时间和读取超时时间都设置为5000毫秒(5秒),可以在application.properties或application.yml文件中进行如下配置:

    feign.client.config.default.connectTimeout=5000
    feign.client.config.default.readTimeout=5000
    

    这将确保如果请求在5秒内没有连接成功或没有返回结果,Feign将会超时。

    (3)Feign如何处理服务降级

    Feign可以通过集成Hystrix来实现服务降级。要启用服务降级,可以执行以下步骤:首先,添加Hystrix依赖到项目中;其次,在Feign客户端的方法上使用@HystrixCommand注解;最后,配置Hystrix的属性以实现降级逻辑,如设置回退方法等。

    (4)Feign与Ribbon的关系

    Feign与Ribbon结合使用可以实现客户端负载均衡。Feign本身不直接支持负载均衡策略,而是通过集成Ribbon来实现。因此,Feign可以使用Ribbon支持的各种负载均衡策略,包括轮询、随机、权重、最佳可用等。要配置Feign使用特定的负载均衡策略,可以在Feign客户端的配置文件中设置Ribbon的负载均衡策略

    3.2、示例代码-Feign

    (1)添加依赖(pom.xml)

        org.springframework.cloud
        spring-cloud-starter-openfeign
    
    

    (2)启用Feign客户端(在启动类上添加@EnableFeignClients注解)

    import org.springframework.boot.SpringApplication;
    import org.springframework.cloud.client.SpringCloudApplication;
    import org.springframework.cloud.openfeign.EnableFeignClients;
     
    @SpringCloudApplication
    @EnableFeignClients
    public class MyApplication {
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    

    (3)创建Feign客户端接口

    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
     
    @FeignClient(name = "remote-service", url = "http://localhost:8080")
    public interface RemoteServiceClient {
        @GetMapping("/data/{id}")
        String getData(@PathVariable("id") Long id);
    }
    

    (4)使用Feign客户端进行调用

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    @RestController
    public class MyController {
     
        @Autowired
        private RemoteServiceClient remoteServiceClient;
     
        @GetMapping("/localData/{id}")
        public String getLocalData(@PathVariable("id") Long id) {
            return remoteServiceClient.getData(id);
        }
    }
    

    RemoteServiceClient是一个Feign客户端接口,用来定义远程服务remote-service的调用方法。在MyController中,我们通过注入RemoteServiceClient来进行远程调用,并将结果返回给客户端。

    注意:上述代码中的url属性是可选的,如果需要调用多个URL,可以使用@FeignClient注解的contextId属性,然后在application.properties或application.yml中配置不同的URL。

    4、服务熔断

    (1)服务雪崩

    一个服务失败,导致整条链路的服务都失败的情形

    (2)服务降级

    服务自我保护的一种方式,或者保护下游服务的一种方式,用于确保服务不会受请求突多影响变得不可用,确保服务不会崩溃,一般在实际开发中与feign接口整合,编写降级逻辑。

    (3)服务熔断

    默认关闭,需要手动打开,如果检测到10秒内接口失败率超过了50%,就触发熔断机制。之后每隔5秒重新尝试请求微服务,如果微服务不能响应,继续走熔断机制。如果微服务可达,则关闭熔断机制,恢复正常请求。

    4.1、sentinel和hystrix区别

    Sentinel和Hystrix都是用于微服务架构中的熔断降级框架,但它们在设计理念、功能实现和应用场景上存在显著差异。具体如下:

    隔离策略和动态调节: Sentinel提供了基于线程池和信号量的隔离方式,并且能够根据系统负载情况动态调整资源的并发度,这使得它更加灵活且适应性强。相比之下,Hystrix主要采用线程池隔离,虽然也支持信号量隔离,但在动态调节方面相对静态,需要通过配置进行调整。

    功能和适用场景: Sentinel不仅提供熔断降级功能,还包括流量控制、实时监控和动态规则配置等,使其适用于需要流量控制和系统负载保护的复杂场景。Hystrix则专注于熔断和降级功能,更适用于需要快速响应和高并发控制的场景。

    实时指标统计: 两者都基于滑动窗口进行实时指标统计,但Sentinel的默认实现是基于LeapArray的高性能滑动窗口,而Hystrix在1.5版本后对实时指标统计的实现进行了重构,采用了基于RxJava的事件驱动模式。

    总结来说,选择Sentinel还是Hystrix应根据项目的具体需求和技术栈来决定,如果项目需要高度的灵活性和动态调节能力,以及流量控制功能,Sentinel可能是更好的选择;如果项目主要关注快速失败和资源隔离,以及对配置的精细控制,Hystrix可能更适合。

    4.2、示例代码-Sentinel

    (1)添加依赖

        com.alibaba.cloud
        spring-cloud-starter-alibaba-sentinel
    
    

    (2)配置Sentinel控制台地址,在application.properties或application.yml中添加:

    spring.cloud.sentinel.transport.dashboard=localhost:8080
    spring.cloud.sentinel.transport.port=8719
    

    (3)启动Sentinel控制台

    (4)在服务中添加服务熔断的逻辑。例如,使用@SentinelResource注解标记需要进行服务熔断的方法:

    import com.alibaba.csp.sentinel.annotation.SentinelResource;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    @RestController
    public class TestController {
     
        @GetMapping("/test")
        @SentinelResource(value = "test", blockHandler = "handleException")
        public String test() {
            return "Test";
        }
     
        public String handleException(BlockException ex) {
            return "Service is blocked, please try again later.";
        }
    }
    

    上述,当服务熔断触发时,Sentinel会调用handleException方法来处理请求,并返回一个错误消息。

    4.3、示例代码-Hystrix

    在Spring Cloud中,Hystrix被整合到了Spring Cloud Netflix中,通过使用@HystrixCommand注解,可以为远程服务调用(如使用Ribbon的服务调用)定义熔断逻辑。

    一个简单的使用Hystrix服务熔断的例子:

    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
     
    @Service
    public class HelloService {
     
        @Autowired
        private RestTemplate restTemplate;
     
        @HystrixCommand(fallbackMethod = "fallbackMethod")
        public String getHelloMessage() {
            return restTemplate.getForObject("http://HELLO-SERVICE/hello", String.class);
        }
     
        public String fallbackMethod() {
            return "Hello Service is not available";
        }
    }
    

    上述,getHelloMessage方法调用了HELLO-SERVICE服务的/hello端点。如果该服务不可用,Hystrix会执行定义的回退方法fallbackMethod,而不是抛出异常或导致线程阻塞。这样可以保证调用服务的客户端即使服务不可用,也会收到一个响应,而不是等待或者产生更多的级联错误。

    5、网关

    Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。

    5.1、示例代码

    Spring Cloud 的网关组件是 Spring Cloud Gateway。以下是一个简单的 Spring Cloud Gateway 示例配置,它使用了 Netty 作为底层通信框架,并且通过路由配置来转发请求。

    (1)在pom.xml中添加依赖

        
            org.springframework.cloud
            spring-cloud-starter-gateway
        
        
        
            org.springframework.cloud
            spring-cloud-starter-consul-discovery
        
    
     
    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                Finchley.SR2
                pom
                import
            
        
    
    

    (2)配置application.yml

    spring:
      cloud:
        gateway:
          routes:
            - id: my_route
              uri: http://localhost:8081
              predicates:
                - Path=/myservice/**
            - id: my_route2
              uri: http://localhost:8082
              predicates:
                - Path=/myservice2/**
    

    在这个配置中,我们定义了两条路由规则:

    • 当请求路径匹配/myservice/**时,转发到http://localhost:8081

    • 当请求路径匹配/myservice2/**时,转发到http://localhost:8082

      (3)启动类

      @SpringBootApplication
      public class GatewayApplication {
          public static void main(String[] args) {
              SpringApplication.run(GatewayApplication.class, args);
          }
      }
      

      这样就配置了一个简单的 Spring Cloud Gateway,它能够根据配置的路由规则转发请求。如果需要更复杂的路由逻辑,可以通过编写 Predicate 和 Filter 来实现。

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码