学习春天の云

①微服务?

灵魂提问:什么是微服务?

微服务是一种架构风格,是一种架构设计方式,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。

威神么(为什么)要微服务,它的好处都有啥?

传统开发模式下,绝大多数的web应用都是单体架构的风格来进行构建,这就使得所有的接口,业务逻辑层,数据持久层全部都被打包在一个web应用中,并且布置在一台服务器上,使得不同的模块之前也高耦合在一起,这种开发模式使得多团队协作开发的开发成本极高。因此不难看出,如果在后期,项目的某个部分需要调整,就会导致“牵一发而动全身”的结果。

它的优点:

1.各个服务的开发、测试、部署都是相互独立的。可以针对某一个特定的服务进行更多的操作,比如负载均衡等。

  1. 当有一个新的需求加入时,传统项目需要结合各方面考虑影响等,微服务就不存在这样的问题,省事省力又省心。

    3.使用微服务将项目拆分后,只需要保证对外接口的正常运行,大大降低了各个模块之间的耦合性,极大的提高开发效率。

缺点:

1.微服务的拆分基于业务,不能随心所欲的拆分,所以如何拆分,对于项目架构来说是非常重要且极具挑战的任务。

2.涉及到服务之间的调用时,常常需要和另外一个服务的提供方进行沟通,若是两个完全不同的公司或者部门,沟通成本比较大;某服务的对外接口要进行修改,也需要与其他服务调用方进行沟通。

3.由于各个服务相互独立,数据也是独立,当多个服务的接口进行操作时,如何保证数据的一致性是一个难点。数据统一性是微服务里面的一个难题。

利用微服务框架实现分布式系统(Spring Cloud)

1.Spring Cloud是完全基于Spring Boot,服务调用是基于REST API ,整合了各种成熟的产品和架构,同时基于Spring Boot也使得整体的开发、配置、部署都非常的方便。

2.Spring系列的产品具备功能齐全、简单好用、性能优美、文档规范等优点。

SC的架构图

SC的核心组件

服务治理Eureka=(Eureka Client)+(Eureka Server)(三大核心、两大步骤)

  • 服务治理的核心由三部分组成:
    • 服务提供者
    • 服务消费者
    • 注册中心
  1. 服务注册:在分布式系统架构中,每个微服务在启动时,会将自己的信息存储在注册中心。
  2. 服务发现:服务消费者从注册中心获取服务提供者的信息,通过这些信息调用服务提供者的服务。

    ②注册中心

如何启动注册中心?

创建一个父工程(配置springBoot)

<parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.0.7.RELEASE</version>
  </parent>

  <dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
  </dependencies>

  <dependencyManagement>
      <dependencies>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>Finchley.SR2</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencies>
  </dependencyManagement>

创建一个子项目,用于配置Eureka

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

在子项目中的yml配置文件中配置Eureka的相关属性

  • server.port:(一般默认8761)
  • eureka.client.register-with-eureka:是否将当前的Eureka Server服务作为客户端进行注册
  • eureka.client.fetch-registry:是否获取其他Eureka Server服务的数据
  • eureka.client.service-url.defaultZone:注册中心的访问地址

最后一步,在子项目中启动springBoot服务

另外,需要注意的是。为了解决jdk9以上没有jaxb API 的问题(不然启动会失败哦),还需要在父项目增加以下依赖

 <!--解决jdk9以上没有jaxb Api的问题 -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>

还有!springBoot和springCloud版本一定要兼容!我就是因为使用了低版本的springCloud(因为视频是19年的,而sprinBoot又是最新的),被折磨了一个上午…

③服务提供者

与上面的类似

创建子项目provider

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>3.0.3</version>
        </dependency>
  1. spring.application.name : 当前服务注册在 Eureka Server 上的名称。
  2. eureka.client.service-url.defaultZone : 注册中⼼的访问地址。
  3. eureka.instance.prefer-ip-address : 是否将当前服务的 IP 注册到 Eureka Server。

④RestTemplate

RestTemplate 是 Spring 框架提供的基于 REST 的服务组件,底层是对 HTTP 请求及响应进⾏了封装, 提供了很多访问 RETS 服务的⽅法,可以简化代码开发。

使用步骤

  1. 创建子项目
  2. 配置application.yml
  3. 创建和服务提供者相同的实体类
  4. 创建controller,调用服务提供者的接口
  5. 创建启动类(@SpringBootApplication),并将RestTemplate的实例(@Bean)进行注入

⑤服务网关

Zuul(祖鲁?)

Zuul 是 Netflix 提供的⼀个开源的 API ⽹关服务器,是客户端和⽹站后端所有请求的中间层,对外开放 ⼀个 API,将所有请求导⼊统⼀的⼊⼝,屏蔽了服务端的具体实现逻辑,Zuul 可以实现反向代理的功 能,在⽹关内部实现动态路由、身份认证、IP 过滤、数据监控等。Zuul也是Spring Cloud集成的组件,通过它来实现服务网关。

Zuulの功能

  1. 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符合的请求。

    1. 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。

    2. 动态路由:动态的将请求路由到不同的后端集群。

    3. 压力测试:逐渐增加指向集群的流量,以了解性能。

  2. 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求。

  3. 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群。

  4. 多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB(Elastic Load Balancing)使用的多样化,以及让系统的便越更贴近系统的使用者。

Zuul的配置文件(模板)

server:
  port: 8030
spring:
  application:
    name: gateway
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
zuul:
  routes:
    provider: /p/**

Zuul的启动类

package com.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy// 包含了 @EnableZuulServer ,设置该类是⽹关的启动类。
@EnableAutoConfiguration
public class GatewayApplication {

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

}

备注:在配置zuul的routes的属性时,可能是因为版本的不兼容会出现ErrorController的异常…(还未解决…)

⑥负载均衡

Ribbon是Sping Cloud的一个组件,Spring Cloud Ribbon是一个负载均衡的解决方案,Ribbon是Netflix发布的负载均衡器,Spring对其进行了集成,Spring Cloud Ribbon是基于Netflix Ribbon实现的,是一个用于对HTTP请求进行控制的负载均衡客户端。Spring Cloud Ribbon也是要结合Eureka Server来使用的,因为也要在注册中心进行注册。在注册中心对Ribbon进行注册之后,Ribbon就可以基于某种负载均衡算法,如轮询、随机、加权轮询、加权随机等自动帮助服务消费者调用接口,开发者也可以根据具体需求自定义Ribbon负载均衡算法。实际开发中,Spring Cloud Eureka来使用,Eureka Server提供所有可以调用的服务提供者列表,Ribbon基于特定的负载均衡算法从这些服务提供者中选择要调用的具体实例。

  1. yml配置文件(略)

  2. 创建启动类

    package com.ribbon;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @SpringBootApplication
    public class RibbonApplication {
        public static void main(String[] args) throws Exception {
            SpringApplication.run(RibbonApplication.class, args);
        }
    
        @Bean
        @LoadBalanced//!!!
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
    }
    

    @LoadBalanced:声明一个基于Ribbon的负载均衡。标注此注解后,RestTemplate就具有了客户端负载均衡的能力。

    1. Controller层代码

      package com.ribbon.controller;
      
      import java.util.Collection;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      import org.springframework.web.client.RestTemplate;
      
      import com.ribbon.bean.user;
      
      @RestController
      @RequestMapping("/ribbon")
      public class RibbonHandler {
      
          @Autowired
          private RestTemplate restTemplate;
      
          @GetMapping("/findAll")
          public Collection<Student> findAll(){
              return restTemplate.getForObject("http://provider/user/findAll", Collection.class);
          }
      
          @GetMapping("/index")
          public String index() {
              return restTemplate.getForObject("http://provider/user/index", String.class);
          }
      
      }
      

⑦Feign声明式接口调用(代替ribbon?)

  • 什么是Feign?

    与Ribbon一样,Feign也是有网飞提供的,Feign是一个声明式、模块化的Web Service的客户端,它简化了开发者编写Web服务客户端的操作,开发者可以通过简单的接口和注解来调用HTTP API,使得开发变得更加简化、快捷。Spring Cloud Feign也是基于Netflix Feign的二次开发,它整合了Ribbon和Hystrix,具有可插拔、基于注解、负载均衡、服务熔断等一系列的便捷功能,也就是说我们在实际开发中可以用Feign来取代Ribbon(好家伙,又“白雪”一节课)

    相比较于Ribbon+RestTemplate的方式,Feign大大简化了代码的开发,Feign支持多种注解,包括Feign注解、JAX-RS注解、Spring MVC注解等,Spring Cloud对Feign进行了优化,整合了Ribbon和Eureka,从而让Feign使用更加方便。

  • 需要的依赖

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

    注意:上面的版本较老

  • 创建启动类

    package com.feign;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    @SpringBootApplication
    @EnableFeignClients//!!!!!!!!!!!!!!!
    public class FeignApplication {
        public static void main(String[] args) throws Exception {
            SpringApplication.run(FeignApplication.class, args);
        }
    
    }
    

    @EnableFeignClients:声明其为Feign客户端


    创建声明式接口

package com.feign;

import java.util.Collection;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

import com.feign.bean.user;

@FeignClient(value = "provider")
public interface IFeignService {

    @GetMapping("/user/findAll")
    public Collection<user> findAll();

    @GetMapping("/user/index")
    public String index();
}

controller代码

package com.feign.controller;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.feign.bean.user;
import com.feign.IFeignService;

@RestController
@RequestMapping("/feign")
public class FeignHandler {

    @Autowired
    private IFeignService feignservice;

    @GetMapping("/findAll")
    public Collection<user> findAll(){
        return feignservice.findAll();
    }

    @GetMapping("/index")
    public String index() {
        return feignservice.index();
    }

}

服务熔断机制

什么是服务熔断?


服务熔断就好比于保险丝的熔断。一般一个功能有多个微服务完成,假设其中一个微服务出现了问题,为了不造成连锁反应,引发更大损失。此时会在出问题的微服务处“切断”服务。就像保险丝熔断一样,防止火灾。feign提供了这一熔断机制,该机制可在配置文件中开启。

feign.hystrix.enable:是否开启熔断机制,默认false

创建IFeignService的实现类FeignServiceImpl,在里面定义容错处理机制,通过@Component注解将FeignServiceImpl实例注入到IOC容器

package com.feign.impl;

import java.util.Collection;

import org.springframework.stereotype.Component;

import com.feign.bean.user;
import com.feign.IFeignService;

@Component
public class FeignServiceImpl implements IFeignService{

    @Override
    public Collection<user> findAll() {
        return null;
    }

    @Override
    public String index() {
        return "服务器维护中。。。";
    }

}

在IFeignService接口定义处定义@FeignClient的fallback属性来做降级处理,设置映射,映射到FeignServiceImpl中去。修改IFeignService后代码如下:

package com.feign;

import java.util.Collection;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

import com.feign.bean.user;
import com.feign.impl.FeignServiceImpl;

@FeignClient(value = "provider",fallback = FeignServiceImpl.class)
public interface IFeignService {

    @GetMapping("/user/findAll")
    public Collection<user> findAll();

    @GetMapping("/user/index")
    public String index();
}

⑧Hystrix容错机制

再不改变各个微服务调用关系的前提下,针对错误情况进行预先处理

  • 设计原则
    1. 服务隔离机制
    2. 服务降级机制
    3. 熔断机制
    4. 提供实时的监控和警报功能
    5. 提供实时的配置修改功能

引入依赖

 <!-- Eureka客户端依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.0.2.RELEASE</version>
    </dependency>
    <!-- 加入feign -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
        <version>2.0.2.RELEASE</version>
    </dependency>
    <!-- 加入actuator健康监控 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
        <version>2.0.7.RELEASE</version>
    </dependency>
    <!-- 添加hysteix熔断器 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.0.2.RELEASE</version>
    </dependency>
    <!-- 添加可视化监控组件 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        <version>2.0.2.RELEASE</version>
    </dependency>

配置文件

server:
  port: 8060
spring:
  application:
    name: hystrix
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
feign:
  hystrix:
    enabled: true
management:
  endpoints:
    web:
      exposure:
        include: 'hystrix.stream'

⑨Spring Cloud 配置中心

Spring Cloud Config可以通过服务端为多个客户端提供配置服务。Spring Cloud Config可以将配置文件存储在本地,也可以将配置文件存储在远程仓库中。可以在不重启微服务的前提下来修改它的配置。具体操作就是创建Config Server,通过它管理所有的配置文件。

  • 依赖引入

  • 配置yml

server:
  port: 8762
spring:
  application:
    name: nativeconfigserver
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations: classpath:/shared
  • 创建启动类

    package com.config;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @SpringBootApplication
    @EnableConfigServer
    public class NativeConfigServerApplication {
        public static void main(String[] args) throws Exception {
            SpringApplication.run(NativeConfigServerApplication.class, args);
        }
    
    }
    

重点:

在创建客户端后,在里面创建一个名为bootstrap.yml的配置文件(名称不能是别的,这是规定),用来读取配置中心的对应配置文件信息

bootstrap的配置信息如下:

spring:
  application:
    name: configclient
  profiles:
    active: dev
  cloud:
    config:
      uri: http://localhost:8762
      fail-fast: true

其中,通过spring.application.name结合spring.profiles.active拼接获得目标配置文件名称configclient-dev.yml,去Config Server中查找该文件。

(拖更…)