微服务架构和核心组件

82 阅读6分钟

什么是微服务:是一种经过良好设计的分布式架构。

微服务特征

  • 职责单一:每个服务只做一件事,服务的粒度非常细
  • 服务自治:每个服务可以有独立的团队、独立的技术、独立的数据、独立交付部署
  • 面向服务:所有服务都要遵循相同的协议暴露访问接口。SpringCloud使用的是HTTP协议
  • 服务隔离:服务之间应该做好隔离与保护,防止出现服务雪崩

微服务核心组件

  • 注册中心:解决服务治理问题的组件。Nacos,Eureka
  • 远程调用:解决服务之间互相访问的组件,发起远程调用。HttpClient、RestTemplate、Feign
  • 服务保护:解决服务之间的隔离,防止出现雪崩。Sentinel,Hystrix
  • 配置中心:解决服务的配置文件散乱、不好处理的问题。Nacos,SpringCloudConfig
  • 服务网关:解决 众多微服务对象提供统一的访问入口。SpringCloudGateway, Zuul

微服务架构和核心组件如下图:

image-20240429141100475.png

远程调用:微服务之间需要互相调用,进行数据交互===>Feign

  • 使用入门

    添加依赖:添加OpenFeign的依赖坐标

    创建接口:XxxClient接口

    • 接口上加@FeignClient("目标服务名")

    • 接口里方法上加@GetMapping, @PostMapping,……

    • 接口里方法形参加:

      @RequestParam:要把方法参数 作为表单参数 发出去

      @RequestBody:要把方法参数 作为请求体json发出去

      @PathVariable:要把参数 作为路径变量发出去

    • 方法返回值是:期望得到的结果。Feign会帮我们把响应结果转换成 期望的类型

  • 打印日志

    要修改配置文件,设置全局的日志级别为 debug

    要修改配置文件,设置Feign的日志级别。共有4个:NONE,BASIC,HEADERS,FULL

  • 优化性能:

    问题:Feign本身底层使用URLConnection,没有连接池。每次操作要创建连接,之后要关闭销毁连接对象

    解决:把Feign底层换成httpclient

    1. 添加httpclient的依赖坐标

    2. 修改配置文件,启用httpclient

      feign:
        httpclient:
          enabled: true
          max-connections: 最大连接数
          max-connections-per-route: 每个资源路径的最大连接数
      

负载均衡:远程调用时,如果目标服务是集群,就需要实现负载均衡==>Ribbon

  • 负载均衡的两种方式

    提供者一方的负载均衡:Nginx。适用于整个服务的最前沿,直接面向客户端的请求

    消费者一方的负载均衡:Ribbon。适用于微服务之间互相调用时,实现负载均衡

  • Ribbon的使用:不需要额外添加依赖、不需要做任何配置,默认就有负载均衡效果。

  • Ribbon的负载均衡策略,常见的:RandomRule,RoundRobinRule,NacosRule

  • 修改负载均衡策略:

    方式1,修改消费者一方的配置文件,设置负载均衡策略

    方式2,在消费者一方,使用@Bean把负载均衡策略对象放到IoC容器里

  • 饥饿加载

    如果不开启饥饿加载,当第一次访问时,Ribbon才会从注册中心拉取服务地址列表。第一次访问通常比较慢

    可以开启饥饿加载,作用是微服务一启动,Ribbon就立即从注册中心里拉取服务地址列表。

服务保护:远程调用时,必须要防止目标服务出错导致的级联问题==>Hystrix或Sentinel

注册中心:远程调用时,需要实时获取到目标服务的地址信息==>Nacos

  • 注册中心解决了服务治理的问题

  • 使用入门:

    1. 安装开启Nacos。Nacos的管理界面地址 http://localhost:8848/nacos, 帐号nacos,密码nacos

    2. 微服务整合Nacos

      添加依赖:锁定SpringCloudAlibaba的依赖版本,再添加nacos-discovery坐标

      修改配置:

      • 应用服务名,使用spring.application.name配置
      • 注册中心地址,使用spring.cloud.nacos.discovery.server-addr配置

      修改引导类:添加@EnableDiscoveryClient

  • Nacos分级存储模型:

    • 可以把一个服务下边划分多个集群,每个集群下边有多个服务实例。同一集群的实例,部署到同一机房

      灾备(异地容灾),同集群优先访问

    • 修改配置文件,使用spring.cloud.nacos.discovery.cluster-name设置当前微服务所属集群名。实现了分级

    • 修改配置文件,使用NacosRule负载均衡策略,实现了同集群优先访问

  • Nacos的环境隔离:

    效果:

    • 不同环境的服务实例之间,是绝对隔离的,不可能互相发现、不可能互相访问;
    • 同环境的服务可以互相发现调用

    做法:

    1. 在Nacos里创建新的命名空间。设置id、名称、描述

    2. 修改配置文件,设置微服务所属的namespace。

      使用参数spring.cloud.nacos.discovery.namespace=命名空间的id

服务网关:所有微服务,要有一个统一的访问入口==>SpringCloudGateway

  • 网关的作用:

    路由:把客户端的请求,根据判断条件分发到目标微服务上

    过滤:拦截客户端的请求进行过滤处理,再决定是否放行

  • 使用入门:创建Module,然后

    添加依赖:nacos-discovery,gateway的坐标

    修改配置:nacos注册中心的配置,网关路由的配置,跨域的配置

    修改引导类:@EnableDiscoveryClient启动服务发现

  • 过滤器GatewayFilter:网关Gateway提供了大量的GatewayFilter,我们可以直接配置使用,不需要写Java代码

    spring:
      cloud:
        gateway:
          default-filters:
            - 过滤器名=参数
            - 过滤器名=参数
          routes:
            - id: 路由唯一标识
              uri: 路由的目的地,写法是 lb://目标服务名
              predicates:
                - Path=/xx/**
              filters:
                - 过滤器名=参数
                - 过滤器名=参数
          globalcors: #全局跨域的配置
    
  • 过滤器GlobalFilter:通常用于自定义过滤器

    创建类,实现GlobalFilter、Ordered接口

    • 重写GlobalFilter接口的filter方法,在方法里编写过滤逻辑。方法里有一些常用的API

      exchange.getRequest()

      exchange.getResponse()

      request.getURI().getPath()

      request.getHeaders().getFirst("请求头名称")

      如果要放行:return chain.filter(exchange);

      如果不放行:

      • response.setStatus(HttpStatus.UNAUTHORIZED)
      • return response.setComplete();
    • 重写Ordered接口的getOrder方法,在方法里返回int值。值越小,优先级越高

    在类上添加@Component

配置中心:所有微服务的配置文件太散乱、不能热更新==>Nacos

  • 作用:

    可以统一管理所有微服务的配置文件

    可以实现配置参数的热更新

  • 用法:

    1. 把微服务的配置参数,托管到Nacos里。

      在Nacos里创建配置,DataId是 应用服务名-环境标识.后缀名

      把配置参数添加进去。通常把一些 可能会改变的、修改的参数,放到配置中心

    2. 微服务整合配置中心,从配置中心里拉取配置文件

      添加依赖:nacos-config

      创建配置:不要application.yaml,要创建bootstrap.yaml。把不变的配置放到这个配置文件里

      server:
        port: 8080
      spring:
        application:
          name: 应用服务名
        cloud:
          nacos:
            config:
              server-addr: localhost:8848 #Nacos注册中心的地址
              prefix: 应用服务名 
              file-extension: 后缀名
        profiles:
          active: 环境标识
      
  • 参数热更新:

    • 方式1:使用@Value读取参数值,并在bean对象上加@RefreshScope
    • 方式2:使用@ConfigurationProperties读取参数值,它本身就具备参数热更新的能力