SpringCloud

一、什么是SpringCloud?

Spring Cloud是一个基于Spring Boot实现的,为开发者提供了快速构建分布式系统的工具集。
包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。

二、服务的注册和发现

1、要想SpringCloud中包含Eureka服务器,需要加入Eureka的依赖。
   Spring Cloud Netflix的Eureka ,eureka是一个服务注册和发现模块。

2、eureka是一个高可用的组件,它没有后端缓存,每一个实例注册之后需要向注册中心发送心跳,
   在默认情况下erureka server也是一个eureka client ,如果只作为一个服务注册中心,则必须要在(yml)配置文件
   中指定是一个 server。

   通过eureka.client.registerWithEureka:false和fetchRegistry:false来表明自己是一个eureka server。

3、在SpringBoot的主配置类上添加@EnableEurekaServer注解,启动一个服务注册中心。

   eureka server 是有界面的,端口默认为8761

4、服务提供者 (eureka client):服务的被调用方

   当client向server注册时,它会提供一些元数据,例如主机和端口,URL,主页等。
   Eureka server 从每个client实例接收心跳消息。 如果心跳超时,则通常将该实例从注册server中删除。

5、@EnableDiscoveryClient 与 @EnableEurekaClient 的区别:

    ● spring cloud中discovery service有许多种实现(eureka、consul、zookeeper等等),
      @EnableDiscoveryClient基于spring-cloud-commons, @EnableEurekaClient基于spring-cloud-netflix。

    ● 其实用更简单的话来说,就是如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient,
                         如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。

    ●  @EnableEurekaClient注解只能用在服务采用的是eureka作为注册中心,
       如果服务采用的是其它的注册中心,则不能使用,只能使用@EnableDiscoveryClient 。

三、服务消费者(服务调用方)

在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的。

★ Spring cloud有两种服务调用方式:
                    
           一种是:ribbon + restTemplate;
           另一种是:feign

★ ribbon是一个负载均衡客户端,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon。


1、服务消费者(restTemplate + ribbon)

     ①、在Springboot的主配置类上,添加@EnableDiscoveryClient注解,通过此注解向服务注册中心注册;

     ②、并且在主配置类中通过@Bean注解注入一个RestTemplate bean,返回值是注册的bean, 
        方法名是容器中该bean的id;

     ③、在注入的RestTemplate bean上添加 @LoadBalanced 注解表明这个RestTemplate 开启了负载均衡的功能;

     ④、写一个测试类,使用 @Autowired 注入RestTemplate,然后使用RestTemplate调用服务提供者提供的服务接
        口,可以使用程序名代替具体的Url地址,在Ribben中会根据服务名来选择具体的服务实例,根据服务实例在请求
        的时候会用具体的url替换服务名。


   通过以上步骤编写完之后,多次调用方法,会发现已经实现了负载均衡,默认是使用的轮询机制。
   此外还有随机访问、响应时间加权等机制实现负载均衡。



2、服务消费者(Feign)

    ● Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。Feign 采用的是基于接口的注解;
    ● Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

    ①、导入spring-cloud-starter-feign、spring-cloud-starter-eureka、spring-boot-starter-web依赖;

    ②、在配置文件application.yml文件中,指定程序名,端口号,服务注册地址;

    ③、在SpringBoot的主配置类上添加@EnableFeignClients注解开启Feign的功能;

    ④、定义一个接口,接口上添加@ FeignClient(“服务名”)注解,来指定调用哪个服务;
      在接口中写一个方法,指定调用指定服务的哪个方法;

    ⑤、在web层的controller层,写一个controller,用于外界访问

  
    启动程序,多次访问,发现也实现负载均衡的效果,不同端口轮询显示

四、断路器(Hystrix)

断路器.png
  ●  在微服务架构中,根据业务需求把一个复杂的软件应用拆分成一个个的微小服务,服务与服务之间可以相互调用
    【RPC:远程过程调用(Remote Procedure Call)】,在Spring Cloud 中可以使用RestTemplate + Ribbon 或 
     Feign来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%
     可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源
     会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,
     这就是服务故障的“雪崩”效应。

  ●  解决这个问题的方法:断路器

  ●  Netflix开源了Hystrix组件,实现了断路器模式,SpringCloud对这一组件进行了整合。 
     在微服务架构中,一个请求需要调用多个服务是非常常见的,较底层的服务如果出现故障,会导致连锁故障。
     当对特定的服务的调用,其不可用达到一个阀值(Hystrix 默认是5秒内出现20次), 断路器将会被打开。
     断路打开后,可用避免连锁故障,fallback方法可以直接返回一个固定值。


▲ 在ribbon中使用断路器

    ①、首先在pom.xml 添加 spring-cloud-starter-hystrix 依赖;

    ②、在SpringBoot的主配置类上添加@EnableHystrix注解开启Hystrix;

    ③、在服务消费者调用服务提供者接口的方法上添加@HystrixCommand(fallbackMethod = "方法名")注解,
       该注解对该方法创建了断路器的功能,并指定了fallbackMethod ,fallbackMethod 中的方法返回一个固定值。

          @Service
          public class HelloService {

              @Autowired
              RestTemplate restTemplate;

             @HystrixCommand(fallbackMethod = "hiError")
              public String hiService(String name) {
                  return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
              }

              public String hiError(String name) {
                  return "hi,"+name+",sorry,error!";
              }
          }

  如果出现故障,直接返回指定的值,而不是等待响应超时,很好的控制了容器的线程阻塞。


▲ 在Feign中使用断路器

    ①、在接口上的@FeignClient注解中添加fallback 属性

            @FeignClient(value = "service-hi",fallback = SchedualServiceHiHystric.class)
            public interface SchedualServiceHi {
                @RequestMapping(value = "/hi",method = RequestMethod.GET)
                String sayHiFromClientOne(@RequestParam(value = "name") String name);
            }
  
    ②、fallback 属性指定的类实现接口,并注入到Ioc容器中

            @Component
            public class SchedualServiceHiHystric implements SchedualServiceHi {
                @Override
                public String sayHiFromClientOne(String name) {
                    return "sorry "+name;
                }
            }

   ③、在配置文件中添加:

feign:
  hystrix:
    enabled: true



▲ Hystrix Dashboard (断路器:Hystrix 仪表盘)
 
    ①、需要在pom.xml 中添加spring-cloud-starter-hystrix、spring-cloud-starter-hystrix-dashboard、
       spring-boot-starter-actuator依赖;

    ②、在SpringBoot的主配置类上添加@EnableHystrix 和 @EnableHystrixDashboard 注解,
       @EnableHystrixDashboard注解是开启hystrixDashboard;

    ③、打开浏览器:访问[http://localhost:端口/hystrix,界面如下:

HystrixDashboard.png
  ④、点击monitor stream,进入下一个界面,然后新开窗口访问:http://localhost:8764/hi?name=forezp
     然后返回之前的窗口,此时会出现监控界面:
监控界面.png

五、路由网关(zuul)

  1、在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),
     然后再到具体的服。服务统一注册到高可用的服务注册中心Eureka集群,服务的所有的配置文件由配置服务管理,配置服务的配置文件放在git仓库,
     方便开发人员随时改配置。

  2、Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。
     zuul默认和Ribbon结合实现了负载均衡的功能。

▲ 3、zuul的路由转发功能的实现:
     ①、在pom.xml 中导入spring-cloud-starter-zuul依赖;
    
     ②、在SpringBoot的主配置类上添加@EnableZuulProxy,开启zuul的功能;

     ③、在配置文件application.yml中加上以下的配置代码:

eureka:
  client:
    serviceUrl:
      #指定服务注册中心的地址
      defaultZone: http://localhost:8761/eureka/

server:
#指定服务的端口
  port: 8768

#指定服务名
spring:
  application:
    name: service-zuul

#指定zuul的路由转发功能
zuul:
  routes:
    #以/to-ribbon/ 开头的请求都转发给service-ribbon服务;
    api-a:
      path: /to-ribbon/**
      serviceId: service-ribbon

    #以/to-feign/开头的请求都转发给service-feign服务;
    api-b:
      path: /to-feign/**
      serviceId: service-feign

      ④、依次运行工程;打开浏览器访问:http://localhost:8768/to-ribbon/hi?name=tom;浏览器显示:
              hi tom ,i am from port:8763


▲ 4、zuul的服务过滤功能,可以做一些安全验证,写一个filter  extends ZuulFilter

六、分布式配置中心(Spring cloud Config)

1、在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。
   在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),
   也支持放在远程Git仓库中。

   在spring cloud config 组件中,分两个角色,一是config server,二是config client。


2、配置服务中心可以从远程程序获取配置信息。【config-server 从git仓库读取配置文件信息】

   ①、在pom.xml 中 导入 spring-cloud-config-server依赖;

   ②、在SpringBoot的主配置类上添加@EnableConfigServer注解,开启配置服务器的功能;

   ③、在配置文件application.properties中进行相关配置:

          spring.application.name=服务名
          server.port=端口必须是8888

          spring.cloud.config.server.git.uri=配置git仓库地址
          spring.cloud.config.server.git.searchPaths=配置仓库路径
          spring.cloud.config.label=配置仓库的分支
          spring.cloud.config.server.git.username=用户名 (如果Git仓库为公开仓库,可以不填写用户名和密码,如果是私有仓库需要填写)
          spring.cloud.config.server.git.password=密码
        
   ④、 启动程序访问里面的配置文件,http请求地址和资源文件映射如下:

                /{application}/{profile}[/{label}]
                /{application}-{profile}.yml
                /{label}/{application}-{profile}.yml
                /{application}-{profile}.properties
                /{label}/{application}-{profile}.properties

  【注意:】{application}是git仓库中配置文件的文件名,该文件名与config-client的项目中配置文件中的spring.application.name值相同


4、本地从配置中心读取值

   ①、在pom.xml 中 导入 spring-cloud-starter-config 依赖;

   ②、在配置文件application.properties中进行相关配置:

          spring.application.name=服务名
          server.port=端口任意

          spring.cloud.config.label=指明远程仓库的分支
          spring.cloud.config.profile=激活什么环境
          spring.cloud.config.uri= 指明配置服务中心的网址

   ③、写一个controller,可以获取从配置中心读取的值


5、config-client可以从config-server 中获取属性,而config-server是从git仓库读取的


【注意:】
     ●  config-server 中的配置文件的端口必须是8888

     ●  spring.application.name 设置的值必须和git仓库中要读取的配置文件的名字一样

        否则config-client 从配置中心读取值时就会报错:Could not resolve placeholder '要读取的值' in value "${要读取的值}"

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容