SpringCloud 微服务学习

引言

为什么要学习微服务?

在这里插入图片描述


需要学习哪些知识?

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


1、认识微服务

1.1 服务架构演变

单体架构
在这里插入图片描述

分布式架构
在这里插入图片描述

服务治理

在这里插入图片描述

总结

微服务是一种经过良好架构设计的分布式架构方案,微服务架构特征:

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发

  • 面向服务:微服务对外暴露业务接口

  • 自治:团队独立、技术独立、数据独立、部署独立

  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

在这里插入图片描述

单体架构特点?

  • 简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统

分布式架构特点?

  • 松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目,例如:京东、淘宝
  • 微服务:一种良好的分布式架构方案
  • 优点:拆分粒度更小、服务更独立、耦合度更低
  • 缺点:架构非常复杂,运维、监控、部署难度提高

1.2 微服务技术对比

微服务结构

在这里插入图片描述

微服务技术对比

在这里插入图片描述

企业需求

在这里插入图片描述


1.3 SpringCloud

介绍

SpringCloud 是目前国内使用最广泛的微服务框架。
官网地址
SpringCloud 集成了各种微服务功能组件,并基于 SpringBoot 实现了这些组件的自动装配,从而提供了良好的开箱即用体验:

在这里插入图片描述

版本对应关系

在这里插入图片描述



2、服务拆分及远程调用

2.1 服务拆分注意事项

  1. 单一职责:不同微服务,不要重复开发相同业务
  2. 数据独立:不要访问其它微服务的数据库
  3. 面向服务:将自己的业务暴露为接口,供其它微服务调用

在这里插入图片描述

总结

  1. 微服务需要根据业务模块拆分,做到单一职责,不要重复开发相同业务
  2. 微服务可以将业务暴露为接口,供其它微服务使用
  3. 不同微服务都应该有自己独立的数据库

2.2 微服务远程调用

案例
在这里插入图片描述

总结

微服务调用方式

  1. 基于 RestTemplate 发起的 http 请求实现远程调用
  2. http 请求做远程调用是与语言无关的调用,只要知道对方的 ip、端口、接口路径、请求参数即可。

服务者和消费者

  • 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
  • 服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)

在这里插入图片描述

总结

服务调用关系

  • 服务提供者:暴露接口给其它微服务调用
  • 服务消费者:调用其它微服务提供的接口
  • 提供者与消费者角色其实是相对的
  • 一个服务可以同时是服务提供者和服务消费者


3、Eureka 注册中心

3.1 服务调用出现的问题

  • 服务消费者该如何获取服务提供者的地址信息?
  • 如果有多个服务提供者,消费者该如何选择?
  • 消费者如何得知服务提供者的健康状态?

在这里插入图片描述


3.2 Eureka 的作用

  • 消费者该如何获取服务提供者具体信息?
    • 服务提供者启动时向 Eureka 注册自己的信息
    • Eureka 保存这些信息
    • 消费者根据服务名称向 Eureka 拉取提供者信息
  • 如果有多个服务提供者,消费者该如何选择?
    • 服务消费者利用负载均衡算法,从服务列表中挑选一个
  • 消费者如何感知服务提供者健康状态?
    • 服务提供者会每隔 30 秒向 EurekaServer 发送心跳请求,报告健康状态
    • Eureka 会更新记录服务列表信息,心跳不正常会被剔除
    • 消费者就可以拉取到最新的信息

总结

在 Eureka 架构中,微服务角色有两类:

  • EurekaServer:服务端,注册中心

    • 记录服务信息
    • 心跳监控
  • EurekaClient:客户端

    • Provider:服务提供者,例如案例中的 user-service
      • 注册自己的信息到 EurekaServer
      • 每隔 30 秒向 EurekaServer 发送心跳
    • consumer:服务消费者,例如案例中的 order-service
      • 根据服务名称从 EurekaServer 拉取服务列表
      • 基于服务列表做负载均衡,选中一个微服务后发起远程调用

在这里插入图片描述


3.3 搭建注册中心

1、引入依赖

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

2、加注解

给启动类添加 @EnableEurekaServer 注解

3、编写 Spring Boot 配置类

server:
  port: 10086 # 服务端口
spring:
  application:
    name: eurekaserver # eureka的服务名称
eureka:
  client:
    service-url:  # eureka的地址信息
      defaultZone: http://127.0.0.1:10086/eureka

总结

搭建 EurekaServer

  • 引入 eureka-server 依赖
  • 添加 @EnableEurekaServe r注解
  • application.yml 中配置 eureka 地址

3.4 服务注册

1、引入依赖

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

2、编写配置类

eureka:
  client:
    service-url:  # eureka的地址信息
      defaultZone: http://127.0.0.1:10086/eureka

模拟多实例部署

在这里插入图片描述

总结

  1. 服务注册
  • 引入 eureka-client 依赖
  • 在 application.yml 中配置 eureka 地址
  1. 无论是消费者还是提供者,引入 eureka-client 依赖
  • 知道 eureka 地址后,都可以完成服务注册

3.5 服务发现

服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡:

  1. 修改 OrderService 的代码,修改访问的 url 路径,用服务名代替 ip、端口:
String url = "http://userservice/user/" + order.getUserId();
  1. 在 order-service 项目的启动类 OrderApplication 中的 RestTemplate 添加负载均衡注解:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    
    
    return new RestTemplate();
}

3.6 总结

1、搭建 EurekaServer

  • 引入 eureka-server 依赖
  • 添加 @EnableEurekaServer 注解
  • 在 application.yml 中配置 eureka 地址

2、服务注册

  • 引入 eureka-client 依赖
  • 在 application.yml 中配置 eureka 地址

3、服务发现

  • 引入 eureka-client 依赖

  • 在 application.yml 中配置 eureka 地址

  • 给 RestTemplate 添加 @LoadBalanced 注解

  • 用服务提供者的服务名称进行远程调用



4、Ribbon 负载均衡

4.1 负载均衡原理

负载均衡流程

在这里插入图片描述


4.2 负载均衡策略

在这里插入图片描述


在这里插入图片描述

通过定义 IRule 实现可以修改负载均衡规则,有两种方式

1、代码方式:

在 order-service 中的 OrderApplication 类中,定义一个新的 IRule:

@Bean
public IRule randomRule() {
    
    
    return new RandomRule();
}

2、配置文件方式:

在 order-service 的 application.yml 文件中,添加新的配置也可以修改规则

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  # 负载均衡规则

4.3 懒加载

Ribbon 默认是采用懒加载,即第一次访问时才会去创建 LoadBalanceClient,请求时间会很长。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    enabled: true # 开启饥饿加载
    clients: # 指定饥饿加载的服务名称
      - userservice

4.4 总结

1、Ribbon 负载均衡规则

  • 规则接口是 IRule
  • 默认实现是 ZoneAvoidanceRule,根据 zone 选择服务列表,然后轮询

2、负载均衡自定义方式

  • 代码方式:配置灵活,但修改时需要重新打包发布
  • 配置方式:直观,方便,无需重新打包发布,但是无法做全局配置

3、饥饿加载

  • 开启饥饿加载
  • 指定饥饿加载的微服务名称


5、Nacos 注册中心

5.1 认识和安装 Nacos

认识 Nacos

Nacos 是阿里巴巴的产品,现在是 SpringCloud 中的一个组件。相比 Eureka 功能更加丰富,在国内受欢迎程度较高。

官网地址

在这里插入图片描述

安装 Nacos

下载地址

直接下载 zip 压缩包就行,然后解压即可。

双击 bin 目录下的 startup.cmd 文件就可以直接启动了。

5.2 Nacos 快速入门

1、引入依赖

<!-- 统一依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>${spring-cloud-alibaba.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>
<!-- Spring Boot 依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- nacos 依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <!-- 排除内置 Tomcat -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 使用 Jetty 服务器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

2、编写配置文件

spring:
  application:
    name: nacos-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # nacos 服务端地址

3、运行结果

在这里插入图片描述

总结

1、Nacos 服务搭建

(1)下载安装包

(2)解压

(3)在 bin 目录下运行指令:startup.cmd -m standalone

2、Nacos 服务注册或发现

(1)引入 nacos.discovery 依赖

(2)配置 nacos 地址 spring.cloud.nacos.server-addr

5.3 Nacos 服务分级存储模型

在这里插入图片描述

在这里插入图片描述

(1)更改配置文件

spring:
  application:
    name: nacos-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # nacos 服务端地址
        cluster-name: HZ # 配置集群名称,也就是机房位置,例如:HZ,杭州

(2)运行结果

在这里插入图片描述

总结

1、Nacos 服务分级存储模型

(1)一级是服务,例如 userservice

(2)二级是集群,例如杭州或上海

(3)三级是实例,例如杭州机房的某台部署了 userservice 的服务器

2、如何设置实例的集群属性

修改 application.yml 文件,添加 spring.cloud.nacos.discovery.cluster-name 属性即可


在这里插入图片描述

总结

1、NacosRule 负载均衡策略

(1)优先选择同集群服务实例列表

(2)本地集群找不到提供者,才去其它集群寻找,并且会报警告

(3)确定了可用实例列表后,再采用随机负载均衡挑选实例


在这里插入图片描述

在这里插入图片描述

总结

1、实例的权重控制

(1)Nacos 控制台可以设置实例的权重值,0 ~ 1 之间

(2)同集群内的多个实例,权重越高被访问的频率越高

(3)权重设置为 0 则完全不会被访问


5.4 Nacos 环境隔离

在这里插入图片描述

1、创建命名空间

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

总结

1、Nacos 环境隔离

(1)每个 namespace 都有唯一 id

(2)服务设置 namespace 时要写 id 而不是名称

(3)不同 namespace 下的服务互相不可见


5.5 Nacos 注册原理

在这里插入图片描述


5.6 总结

1、Nacos 与 Eureka 的共同点

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

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

2、Nacos 与 Eureka 的区别

(1)Nacos 支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式

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

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

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



6、Nacos 配置管理

6.1 统一配置管理

在这里插入图片描述

1、在 Nacos 中添加配置信息:

在这里插入图片描述

2、在表单中填写相应信息

在这里插入图片描述

3、获取配置的步骤
在这里插入图片描述

(1)引入依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

(2)编写 bootstrap.xml 文件

这个文件是引导文件,优先级高于 application.yml

spring:
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        file-extension: yaml # 文件后缀名

总结

将配置交给 Nacos 管理的步骤:

(1)在 Nacos 中添加配置文件

(2)在微服务中引入 nacos 的 config 依赖

(3)在微服务中添加 bootstrap.yml,配置 nacos 地址、当前环境、服务名称、文件后缀名。这些决定了程序启动时去 nacos 读取哪个文件


6.2 配置热更新

Nacos中 的配置文件变更后,微服务无需重启就可以感知。

两种方式:

(1)@RefreshScope

(2)@ConfigurationProperties

总结

Nacos 配置更改后,微服务可以实现热更新,两种方式:

(1)通过 @Value 注解注入,结合 @RefreshScope 来刷新

(2)通过 @ConfigurationProperties 注入,自动刷新

注意点:

(1)不是所有的配置都适合放到配置中心,维护起来比较麻烦

(2)建议将一些关键参数,需要运行时调整的参数放到 nacos 配置中心,一般都是自定义配置

6.3 配置共享

在这里插入图片描述


在这里插入图片描述

总结

微服务从 nacos 读取的配置文件:

(1)[服务名]-[spring.profile.active].yaml,环境配置

(2)[服务名].yaml,默认配置,多环境共享

优先级:

(1)[服务名]-[环境].yaml >[服务名].yaml > 本地配置

6.4 搭建 Nacos 集群



7、Feign Http 客户端

7.1 Feign 替代 RestTemplate

RestTemplate 方式调用存在的问题

  • 代码可读性差,编程体验不统一
  • 参数复杂 URL 难以维护

Feign 的介绍

Feign是一个声明式的 http 客户端。
官方地址
其作用就是帮助我们优雅的实现 http 请求的发送,解决上面提到的问题。

使用 Feign 的步骤如下

1、引入依赖

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

2、在启动类上添加注解

@EnableFeignClients

3、定义 Feign 接口

@FeignClient("userService")
public interface Client {
    
    

    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

说明:

主要是基于SpringMVC 的注解来声明远程调用的信息,比如:

  • 服务名称:userservice
  • 请求方式:GET
  • 请求路径:/user/{id}
  • 请求参数:Long id
  • 返回值类型:User

4、进行使用

// 自动注入
@Autowired
private Client client;

// 调用相应的方法
client.findById(1L);

总结

Feign 的使用步骤:

(1)引入依赖

(2)添加 @EnableFeignClients 注解

(3)编写 FeignClient 接口

(3)使用 FeignClient 中定义的方法代替 RestTemplate


7.2 自定义配置

在这里插入图片描述

配置 Feign 日志有两种方式

(1)全局生效

(2)局部生效


7.3 Feign 使用优化

Feign 底层的客户端实现:

  • URLConnection:默认实现,不支持连接池
  • Apache HttpClient :支持连接池
  • OKHttp:支持连接池

因此优化 Feign 的性能主要包括:

  • 使用连接池代替默认的 URLConnection
  • 日志级别,最好用 basic 或 none

添加 HttpClient 的支持

(1)引入依赖

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

(2)编写配置

feign:
  httpclient:
    # 连接超时时间
    connection-timeout:
    # 最大的连接数  
    max-connections:
    # 每个路径的最大连接数
    max-connections-per-route:
    # 开启 Feign 对 HttpClient 的支持
    enabled: true

总结

  1. 日志级别尽量用 basic
  2. 使用 HttpClient 或 OKHttp 代替 URLConnection

(1)引入 feign-httpClient 依赖

(2)配置文件开启 HttpClient 功能,设置连接池参数

7.4 最佳实践

方式 1:
在这里插入图片描述

方式 2:

在这里插入图片描述

总结

Feign 的最佳实践:

(1)让 Controller 和 FeignClient 继承同一接口

(2)将 FeignClient、POJO、Feign 的默认配置都定义到一个项目中,供所有消费者使用

注意事项

在这里插入图片描述

不同包的 FeignClient 的导入有两种方式:

(1)在 @EnableFeignClients 注解中添加 basePackages,指定 FeignClient 所在的包

(2)在 @EnableFeignClients 注解中添加 clients,指定具体 FeignClient 的字节码



8、GateWay 网关

8.1 为什么需要网关

在这里插入图片描述

在 SpringCloud 中网关的实现有两种:

  • GateWay(主流,推荐)
  • Zuul

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

总结

网关的作用:

(1)对用户请求做身份认证、权限校验

(2)将用户请求路由到微服务,并实现负载均衡

(3)对用户请求做限流

8.2 GateWay 快速入门

1、引入依赖

注意:网关同样也要注册到 Nacos 中去!

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

2、编写配置

spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: nacos:8848 # nacos地址
    gateway:
      routes:
        - id: user-service # 路由标示,必须唯一
          uri: lb://userservice # 路由的目标地址,lb 表示负载均衡
          predicates: # 路由断言,判断请求是否符合规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
      default-filters:
        - AddRequestHeader=Truth,Itcast is freaking awesome!

在这里插入图片描述

总结

网关搭建步骤:

(1)创建项目,引入 nacos 服务发现和 gateway 依赖

(2)配置 application.yml,包括服务基本信息、nacos 地址、路由

路由配置包括:

(1)路由 id:路由的唯一标示

(2)路由目标(uri):路由的目标地址,http 代表固定地址,lb 代表根据服务名负载均衡

(3)路由断言(predicates):判断路由的规则

(4)路由过滤器(filters):对请求或响应做处理


8.3 断言工厂

网关路由可以配置的内容包括:

  • 路由 id:路由唯一标示
  • uri:路由目的地,支持 lb 和 http 两种
  • predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地
  • filters:路由过滤器,处理请求或响应

路由断言工厂

  • 我们在配置文件中写的断言规则只是字符串,这些字符串会被 Predicate Factory 读取并处理,转变为路由判断的条件
  • 例如 Path=/user/** 是按照路径匹配,这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory 类来处理的
  • 像这样的断言工厂在 SpringCloud Gateway 还有十几个

在这里插入图片描述

总结

1、PredicateFactory 的作用是什么?

读取用户定义的断言条件,对请求做出判断

2、Path=/user/** 是什么含义?

路径是以 /user 开头的就认为是符合的


8.4 过滤器工厂

在这里插入图片描述


在这里插入图片描述

总结

1、过滤器的作用是什么?

  • 对路由的请求或响应做加工处理,比如添加请求头
  • 配置在路由下的过滤器只对当前路由的请求生效

2、defaultFilters 的作用是什么?

  • 对所有路由都生效的过滤器

8.5 全局过滤器

在这里插入图片描述

在这里插入图片描述

自定义全局过滤器

@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        // 1.获取请求参数
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        // 2.获取参数中的 authorization 参数
        String auth = params.getFirst("authorization");
        // 3.判断参数值是否等于 admin
        if ("admin".equals(auth)) {
    
    
            // 4.是,放行
            return chain.filter(exchange);
        }
        // 5.否,拦截
        // 5.1.设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        // 5.2.拦截请求
        return exchange.getResponse().setComplete();
    }

    @Override
    public int getOrder() {
    
    
        return -1;
    }
}

总结

1、全局过滤器的作用是什么?

  • 对所有路由都生效的过滤器,并且可以自定义处理逻辑

2、实现全局过滤器的步骤?

  • 实现 GlobalFilter 接口
  • 添加 @Order 注解或实现 Ordered 接口
  • 编写处理逻辑

过滤器执行顺序

在这里插入图片描述

  • 每一个过滤器都必须指定一个 int 类型的 order 值,order 值越小,优先级越高,执行顺序越靠前。
  • GlobalFilter 通过实现 Ordered 接口,或者添加 @Order 注解来指定 order 值,由我们自己指定
  • 路由过滤器和 defaultFilter 的 order 由 Spring 指定,默认是按照声明顺序从1递增。
  • 当过滤器的 order 值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

可以参考下面几个类的源码来查看:

  • org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters() 方法是先加载 defaultFilters,然后再加载某个route 的 filters,然后合并。
  • org.springframework.cloud.gateway.handler.FilteringWebHandler#handle() 方法会加载全局过滤器,与前面的过滤器合并后根据 order 排序,组织过滤器链

总结

路由过滤器、defaultFilter、全局过滤器的执行顺序?

(1)order 值越小,优先级越高

(2)当 order 值一样时,顺序是 defaultFilter 最先,然后是局部的路由过滤器,最后是全局过滤器


8.6 跨域问题

跨域问题处理

跨域:域名不一致就是跨域,主要包括:

  • 域名不同: www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com
  • 端口不同:localhost:8080和localhost8081
  • 协议不同:例如 http 和 https

解决方案:CORS
在这里插入图片描述


8.7 限流过滤器

限流:对应用服务器的请求做限制,避免因过多请求而导致服务器过载甚至宕机。

限流算法常见的包括两种:

  • 计数器算法,又包括窗口计数器算法、滑动窗口计数器算法
  • 漏桶算法(Leaky Bucket)
  • 令牌桶算法(Token Bucket)

(1)计数器算法

在这里插入图片描述

(2)漏桶算法

在这里插入图片描述

(3)令牌桶算法

在这里插入图片描述

总结

1、限流有什么作用?

  • 限流是保护服务器,避免因过多请求而导致服务器过载甚至宕机

2、限流算法

  • 计数器算法
  • 漏桶算法
  • 令牌桶算法


9、微服务框架小结

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_52462015/article/details/121255035