首页 > 技术文章 > 从天气项目学习Spring Cloud微服务治理

soldier-cnblogs 2020-03-24 20:32 原文

Spring Cloud简介

 

 

Spring Cloud 与 Spring Boot的关系

  • Spring Boot 是构建Spring Cloud架构的基石
  • Spring Cloud版本命名规则:伦敦地铁站名字

Spring Cloud入门配置

Spring Cloud子项目介绍

  1. Spring Cloud Config*:配置中心,利用git来集中管理程序的配置;
  2. Spring Cloud Netfilx*:集成众多Netfilx的开源软件,包括 Eureka、Hystrix、Zuul、Archaius 等;
  3. Spring Cloud Bus*:消息总线,利用分布式消息将服务与服务实例连接在一起,用于在一个集群中传播状态的变化,比如配置更改的事件。可与 Spring Cloud Config 联合实现热部署。
  4. Spring Cloud for Cloud Foundry:利用 Pivotal CloudFoundry 集成你的应用程序。CloudFoundry 是 VMware 推出的开源 PaaS 云平台。
  5. Spring Cloud Cloud Foundry Service Broker:为建立管理云托管服务的服务代理提供了一个起点。
  6. Spring Cloud Cluster*:基于Zookeeper、Redis、Hazelcast、Consul 实现的领导选举和平民状态模式的抽象和实现。(用于集群中)
  7. Spring Cloud Consul*:基于Hashicorp Consul 实现的服务发现和配置管理。
  8. Spring Cloud Security*:在 Zuul 代理中为 OAuth2 REST客户端和认证头转发提供负载均衡。
  9. Spring Cloud Sleuth*:适用于Spring Cloud 应用程序的分布式追踪,与 Zipkin、HTrace 和基于日志(例如ELK)的追踪相兼容。快要日志的收集。
  10. Spring Cloud Data Flow*:一种针对现代运行时可组合的微服务应用程序的云本地编排服务。易于使用的 DSL、拖放式GUI和REST API一起简化了基于微服务的数据管道的整体编排。
  11. Spring Cloud Stream*:一个轻量级的事件驱动的微服务框架来快速构建可以连接到外部系统的应用程序。使用Apache Kafka或RabbitMQ在Spring Boot应用程序之间发送和接收消息的简单声明模型。
  12. Spring Cloud Stream App Starters:基于Spring Boot为外部系统提供Spring的集成。
  13. Spring Cloud Task App Starters:是 Spring Boot 应用程序,可能是任何进程,包括 Spring Batch 作业,并可以在数据处理有限的时间终止。
  14. Spring Cloud for Amazon Web Services:与 Amazon Web Services 轻松集成。它提供了一个方便的方式与AWS提供的服务进行交互,使用Spring惯用语和API(如消息传递或缓存API)。开发人员可以围绕托管服务构建应用程序,而无需关心基础设施或维护工作。
  15. Spring Cloud Connectors:便于 PasS 应用在各种平台上连接后端镜像数据库和消息服务。
  16. Spring Cloud Starters:基于Spring Boot 的项目,用以简化 Spring Cloud 的依赖管理。该项目已经终止,并且在 Angel.SR2 后的版本和其他项目合并。
  17. Spring Cloud CLI:插件用于在 Groovy 中快速创建 Spring Cloud 组件应用程序。
  18. Spring Cloud Contract:是一个总体项目,其中包含帮助用户成功实施消费者驱动契约(Consumer Driven Contract)的解决方案。

 

常见微服务的消费者

  • httpclient用法介绍--是Apache下的一个开源项目

    第一步:添加依赖

    <!-- httpclient -->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5.3</version>
            </dependency>

    第二步:配置注入RestTemple

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.web.client.RestTemplateBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    @Configuration
    public class RestConfiguration {
    
        @Autowired
        private RestTemplateBuilder builder;
    
        @Bean
        public RestTemplate restTemplate() {
            return builder.build();
        }
    }

     第三步:使用

  • ribbon用法介绍--是SpringCloud的一个组件,是基于客户端的负载均衡工具

    第一步:添加依赖

    <!-- ribbon -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        <version>2.2.2.RELEASE</version>
    </dependency>

    第二步:配置注入RestTemple

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.web.client.RestTemplateBuilder;
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    @Configuration
    @RibbonClient(name = "ribbon-client", configuration = RibbonConfiguration.class)
    public class RestConfiguration {
    
        @Autowired
        private RestTemplateBuilder builder;
    
        @Bean
        public RestTemplate restTemplate() {
            return builder.build();
        }
    }

    第三步:配置Ribbon

    import com.netflix.loadbalancer.IPing;
    import com.netflix.loadbalancer.PingUrl;
    import org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    @Configuration
    public class RibbonConfiguration {
    
        @Bean
        public ZonePreferenceServerListFilter serverListFilter() {
            ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
            filter.setZone("myZone");
            return filter;
        }
    
        @Bean
        public IPing ribbonPing() {
            return new PingUrl();
        }
    }

    第四步:使用

    第五步:配置application.properties

    # 当前客户端的应用名称
    spring.application.name=micro-weather-eureka-client-ribbon
    # 设置注册服务器ip地址,注册当前客户端
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
  • feign用法介绍--在集成eureka客户端的情况下使用

     前提是:服务注册中心已经启动
    第一步:添加依赖

            <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <!-- 必须添加web包,否则启动后会Unregistering -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- feign -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
                <version>2.2.2.RELEASE</version>
            </dependency>

    第二步:配置项目Application启动类

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

    第三步:写一个Feign客户端服务接口

    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    /**
     * @Author soldier
     * @Date 20-3-31 下午4:21
     * @Email:583406411@qq.com
     * @Version 1.0
     * @Description:城市信息客户端
     *      首先通过@FeignClient指定被调用服务的名称
     *      其次通过@GetMapping来调用该服务的接口
     */
    @FeignClient("msa-weather-city-client")
    public interface CityClient {
    
        @GetMapping("/cities")
        String cityList();
    }

    第四步:写一个controller调用该接口

    @RestController
    public class CityController {
    
        @Autowired
        private CityClient cityClient;
    
      @RequestMapping("/cities")
    public String cityList() { // 通过Feign客户端查找 String data = cityClient.cityList(); return data; } }

     第五步:配置application.properties

    # eurekaClient相关配置
        # 当前客户端的应用名称
    spring.application.name=micro-weather-eureka-client-feign
        # 设置注册服务器ip地址,注册当前客户端
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    # feignClient相关配置
        # 设置Feign连接超时时间
    feign.client.config.feignName.connect-timeout=5000
        # 设置Feign读取超时时间
    feign.client.config.feignName.read-timeout=5000

    访问eureka注册服务器--http://localhost:8761/

     访问Feign客户端接口--http://localhost:8080/cities

     

     

 使用API网关的意义

1、集合多个API

2、统一API入口

 

3、避免将内部信息泄露给外部

4、为微服务添加额外的安全层

5、支持混合通信协议

6、降低构建微服务的复杂性

7、微服务模拟与虚拟化

API网关的弊端:

1)在架构上需要额外考虑更多的编排与管理

2)路由逻辑配置要进行统一的管理

3)引发单点故障

常见API网关的实现方式

  • Nginx提供微服务

     

  • Spring Cloud Zuul

    提供了认证、鉴权、限流、动态路由、监控、弹性、安全、负载均衡、协助单点压测、静态响应等边缘服务的架构

  • Kong提供微服务

 

如何集成Zuul网关实现路由配置

也是一个eureka client客户端

简介:

  Zuul的功能包括:认证、压力测试、金丝雀测试、动态路由、负载削减、安全、静态响应处理、主动/主动交换管理

  1. 启动eureka server微服务注册中心
  2. 添加eureka client及SpringCloud netflix zuul依赖
            <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <!-- 必须添加web包,否则启动后会Unregistering -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- zuul -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
                <version>2.2.2.RELEASE</version>
            </dependency>
  3. 配置项目Application启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableZuulProxy
  4. 配置application.properties

    # 当前客户端的应用名称
    spring.application.name=micro-weather-eureka-client-zuul
    
    # 设置注册服务器ip地址,注册当前客户端
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    
    # 当用户发送/hi下的所有请求时,zuul会将hi后的请求转发到micro-weather-eureka-client应用中去
    #    如:当前应用端口是8080,micro-weather-eureka-client应用的端口是8081,当访问localhost:8080/hi/hello,会访问micro-weather-eureka-client应用的/hello请求
    zuul.routes.hi.path=/hi/**
    zuul.routes.hi.service-id=micro-weather-eureka-client

     

使用spring-cloud-config实现server端的微服务配置中心

也是一个eureka Client实例

  1. 添加eureka client及spring cloud config server依赖
        <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <!-- 必须添加web包,否则启动后会Unregistering -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- spring-cloud-config-server -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-server</artifactId>
                <version>2.2.2.RELEASE</version>
            </dependency>
  2. 配置项目Application启动类
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableConfigServer
  3. 配置application.properties
    # 当前应用名称
    spring.application.name=micro-weather-config-server
    server.port=8888
    
    # 设置注册服务器ip地址,注册当前客户端
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    
    # SpringCloud配置
        # 仓库地址
    spring.cloud.config.server.git.uri=https://github.com/soldiergit/spring-cloud-microservices-development.git
        # 配置文件查找目录
    spring.cloud.config.server.git.search-paths=config-repo
  4. 直接启动项目,可以不启动eureka server端

     

使用spring-cloud-config 实现client 端的微服务配置中心

也是一个eureka Client实例

  1. 添加eureka client及spring cloud config client依赖
        <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <!-- 必须添加web包,否则启动后会Unregistering -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- spring-cloud-config-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-client</artifactId>
                <version>2.2.2.RELEASE</version>
            </dependency>
  2. 配置项目Application启动类
    @SpringBootApplication
    @EnableDiscoveryClient
  3. 配置application.properties
    # 当前客户端的应用名称
    spring.application.name=micro-weather-config-client
    
    # 设置注册服务器ip地址,注册当前客户端
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    
    # spring cloud config配置
        # 指定环境
    spring.cloud.config.profile=dev
        # 指定config server端地址
    spring.cloud.config.uri=http://localhost:8888/
  4. 配置中心的文件命名规则

     在spring-cloud-config server端指定的github地址中创建文件

  5. 测试:先启动【micro-weather-eureka-server】,再启动【micro-weather-config-server】,最后在【micro-weather-config-client】的test下测试运行
    @SpringBootTest
    class ApplicationTests {
    
        @Value("${auther}")
        private String auther;
    
        @Test
        void contextLoads() {
            assertEquals("soldier", auther);
        }
    
    }

     

     

服务熔断

什么是服务熔断?什么是服务降级?

熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务降级,进而熔断该节点微服务的调用,快速返回“错误”的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。

在SpringCloud框架里熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内调用20次,如果失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand。

服务降级,一般是从整体负荷考虑。就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。这样做,虽然水平下降,但好歹可用,比直接挂掉强。

服务熔断的原理:

断路器:想当于电路中的保险丝
断路器模式:Microsoft Azure断路器模式Hystrix

如何集成Hystrix

也是一个eureka client、feign服务消费者实例

  1. 添加eureka client、feign及hystrix断路器依赖
        <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <!-- 必须添加web包,否则启动后会Unregistering -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- feign -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
                <version>2.2.2.RELEASE</version>
            </dependency>
    
            <!-- hystrix断路器 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
  2. 配置项目Application启动类
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    @EnableCircuitBreaker
  3. 配置application.properties
    # eurekaClient相关配置
        # 当前客户端的应用名称
    spring.application.name=micro-weather-eureka-client-feign-hystrix
        # 设置注册服务器ip地址,注册当前客户端
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    # feignClient相关配置
        # 设置Feign连接超时时间
    feign.client.config.feignName.connect-timeout=5000
        # 设置Feign读取超时时间
    feign.client.config.feignName.read-timeout=5000
  4. 在【常见的微服务消费者-feign用法介绍】学习笔记的前提下修改CityController
    @RestController
    public class CityController {
    
        @Autowired
        private CityClient cityClient;
    
        @RequestMapping("/cities")
        @HystrixCommand(fallbackMethod = "defaultCities")
        public String cityList() {
            // 通过Feign客户端查找
            String data = cityClient.cityList();
            return data;
        }
    
        /**
         * 当服务宕机时调用
         */
        public String defaultCities() {
            return "city data server is down";
        }
    }
  5. 测试:
    首先---先启动【micro-weather-eureka-server】,再启动【msa-weather-city-client】,最后在【micro-weather-eureka-client-feign-hystrix】调用其接口http://localhost:8080/cities

    是没有问题的

    然后---停掉【msa-weather-city-client】,再次访问http://localhost:8080/cities

源码地址

git:https://github.com/soldiergit/spring-cloud-learn

推荐阅读