微服务

一、微服务

1.单体架构

(1)单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。

(2)优点:

  • 架构简单
  • 部署成本低

(3)缺点:

  • 耦合度高

2.分布式架构

(1)分布式架构:根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,成为一个服务。

(2)优点:

  • 降低服务耦合
  • 有利于服务升级拓展

3.微服务

(1)微服务:微服务是一种经过良好架构设计的分布式架构方案。

(2)特征:

  • 单一职责:微服务拆分力度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发
  • 面向服务:微服务对外暴露业务接口
  • 自治:团队独立、技术独立、数据独立、部署独立
  • 隔离性强:服务调用做好隔离、容错、降级、避免出现级联问题

4.微服务技术对比

image-20231204192932669

5.SpringCloud

(1)SpringCloud与SpringBoot的版本兼容关系:

image-20231204195337833

二、服务拆分与远程调用

1.服务拆分注意事项

(1)不同微服务,不要重复开发相同业务

(2)微服务数据独立,不要访问其他微服务的数据库

(3)微服务可以将自己的业务暴露为接口,供其他微服务调用

2.提供者与消费者

  • 服务提供者:一次业务中,被其他微服务调用的服务。(提供接口给其他微服务)
  • 服务消费者:一次业务中,调用其他微服务的服务。(调用其他微服务提供的接口)
  • 提供者与消费者角色是相对的
  • 一个服务可以同时是服务提供者和服务消费者

三、Eureka注册中心

1.Eureka的作用

(1)注册服务信息

(2)拉取服务

(3)负载均衡

(4)远程调用

2.Eureka架构中的微服务角色

  • EurekaServer:服务端,注册中心
    • 记录服务信息
    • 心跳监控
  • EurekaClient:客户端
    • Provider:服务提供者
      • 注册自己的信息到EurekaServer
      • 每隔30秒向EurekaServer发送心跳
    • consumer:服务消费者
      • 根据服务名称从EurekaServer拉取服务列表
      • 基于服务列表做负载均衡,选中一个微服务后发起远程调用

四、Ribbon负载均衡

1.负载均衡流程

image-20231205200059961

2.负载均衡策略

(1)Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每一个子接口都是一种规则

image-20231205201249313

image-20231205201429637

(2)默认实现是ZoneAvoidanceRule,根据zone选择服务列表,然后轮询

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

  • 代码方式:在order-service中的OrderApplication类中,定义一个新的IRule

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

3.饥饿加载

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。

而饥饿加载则会在项目启动时创建,降低第一次访问时的耗时,通过下面配置开启饥饿加载:

image-20231205203111069

五、Nacos注册中心

1.nacos服务分级存储模型

image-20231206203254394

2.NacosRule负载均衡策略

  • 优先选择同集群服务实例列表
  • 本地集群找不到提供者,才去其他集群寻找,并且会报警告
  • 确定了可用实例列表后,再采用随机负载均衡挑选实例

3.根据权重负载均衡

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

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

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

4.环境隔离-namespace

(1)namespace用来做环境隔离

(2)每个namespace都有唯一id

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

5.Nacos注册中心细节分析

image-20231206213510681

六、Nacos与Eureka的对比

1.共同点

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

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

2.区别

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

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

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

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

七、Nacos配置管理

1.统一配置管理

  • 配置更改热更新

2.将配置交给Nacos管理的步骤

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

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

(3)在微服务中添加bootstrap.yml,配置nacos地址、当前环境、服务名称、文件后缀名。

3.配置热更新

(1)方式:

  • 方式一:通过@Value注解注入,结合@RefreshScope来刷新
  • 方式二:通过@ConfigurationProperties注入,自动刷新

(2)注意事项:

  • 不是所有的配置都适合放到配置中心,维护起来比较麻烦
  • 建议将一些关键参数,需要运行时调整的参数放到nacos配置中心,一般都是自定义配置

4.多环境配置共享

(1)微服务启动时会从nacos读取多个配置文件:

  • [spring.application.name]-[spring.profiles.cative].yaml
  • [spring.application.name].yaml

(2)无论profile如何变化,[spring.application.name].yaml这个文件一定会加载,因此多环境共享配置可以写入这个文件

(3)多种配置的优先级:

  • 服务名-profile.yaml > 服务名称.yaml > 本地配置

5.Nacos集群搭建步骤

(1)搭建MySQL集群并初始化数据库表

(2)下载解压nacos

(3)修改集群配置(节点信息)、数据库配置

(4)分别启动多个nacos节点

(5)nginx反向代理

八、Feign

1.使用步骤

(1)引入依赖:

image-20231218191535470

(2)在启动类添加注解@EnableFeignClients

(3)编写Feign客户端

image-20231218191704950

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

2.自定义配置

(1)

image-20231218192028710

(2)配置Feign日志两种方式

方式一:

  • 全局生效:

    image-20231218203324415

  • 局部生效:

    image-20231218203340643

方式二:

image-20231218203711057

  • 如果是全局配置,则把它放到@EnableFeignClients这个注解中

    image-20231218203915618

  • 如果是局部配置,则把它放到@FeignClient这个注解中

    image-20231218204009598

3.Feign的性能优化

(1)Feign底层的客户端实现:

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

(2)优化Feign的性能主要包括:

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

(3)连接池配置:

  • 引入依赖

    image-20231218205050527

  • 配置连接池:

    image-20231218205109500

4.Feign的最佳实践

(1)方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准

image-20231218210510364

  • 服务紧耦合
  • 父接口参数列表中的映射不会被继承

(2)方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用

实现步骤:

  • 首先创建一个moudule,命名为feign-api,引入feign的starter依赖
  • 将消费者中的Client、实体类、DefaultFeignConfiguration都复制到feign-api项目中
  • 将消费者引入feign-api的依赖
  • 修改消费者中的所有与上述三个组件有关的import部分,改成导入feign-api中的包
  • 重启测试

(3)当定义的FeignClient不在SPringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:

  • 方式一:指定FeignClient所在包

    image-20231218221520377

  • 方式二:指定FeignClient字节码

    image-20231218221544380

九、Gateway网关

1.网关功能

(1)身份认证和权限校验

(2)服务路由、负载均衡

(3)请求限流

2.网关的技术实现

(1)gateway

(2)zuul

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

3.搭建网关服务步骤

(1)创建新的moudule,引入SpringCloudGateway的依赖和nacos的服务发现依赖

image-20231219192330868

(2)编写路由配置及nacos地址

image-20231219192503080

4.路由断言工厂Route Predicate Factory

Spring提供了11种基本的Predicate工厂:

image-20231219193724931

5.路由过滤器 GatewayFilter

(1)GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:

image-20231219194524309

(2)过滤器工厂GatewayFilterFactory:

Spring提供了31种不同的路由过滤器工厂

image-20231219194715693

(3)过滤器作用:

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

(4)defaultFilters:对所有路由都生效的过滤器

6.全局过滤器GlobalFilter

(1)作用:

全局过滤器的作用是处理一切进入网关的请求和微服务响应。

(2)与GatewayFilter的区别:

区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。

(3)实现步骤:

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

image-20231219200238987

7.过滤器执行顺序

(1)请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器

(2)每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前

(3)GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值。

(4)路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增

(4)当过滤器的order值一样时,会按照defaultFilter>路由过滤器>GlobalFilter的顺序执行

8.跨域问题处理

网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可

image-20231219203358229

十、Docker

1.Docker架构

(1)镜像:Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像

(2)容器:镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器做隔离,对外不可见。

(3)Docker是一个CS架构的程序,由两部分组成:

  • 服务端(server):Docker守护进程,负责处理Docker指令,管理镜像、容器等
  • 客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令。

2.镜像命令

(1)镜像名称一般分两部分组成:[repository]:[tag]

(2)在没有指定tag时,默认是latest,代表最新版本的镜像

(3)镜像操作命令:

image-20240111100507945

3.容器命令

image-20240111122702351

4.数据卷命令

(1)容器与数据耦合的问题:

  • 不便于修改
  • 数据不可复用
  • 升级维护困难

(2)数据卷是一个虚拟目录,指向宿主机文件系统中的某个目录。

(3)数据卷操作基本语法:docker volume [COMMAND]

  • create 创建一个volume
  • inspect 显示一个或多个volume的信息
  • ls 列出所有的volume
  • prune 删除未使用的volume
  • rm 删除一个或多个指定的volume

5.自定义镜像

(1)镜像结构:镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。

  • BashImage层:包含基本的系统函数库、环境变量、文件系统
  • Entrypoint:入口,是镜像中应用启动的命令
  • 其他:再BaseImage基础上添加依赖、安装程序、完成整个应用的安装和配置

(2)Dockerfile:Dockerfile就是一个文本文件,其中包含一个个的指令,用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。

image-20240111180523765

6.DockerCompose

(1)Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器!

(2)Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行

十一、MQ

1.同步调用优缺点

(1)优点:时效性强,可以立即得到结果

(2)问题:

  • 耦合度高
  • 性能下降
  • 资源浪费
  • 级联失败

2.异步通讯优缺点

(1)优势:

  • 服务解耦
  • 性能提升,吞吐量提高
  • 服务没有强依赖,不担心级联失败问题
  • 流量削峰

(2)缺点:

  • 依赖于Broker的可靠性、安全性、吞吐能力
  • 结构复杂,业务没有明显的流程线,不好追踪管理

3.MQ

image-20240112122514141

4.MQ的不同用法

(1)基本消息队列(BasicQueue)

(2)工作消息队列(WorkQueue)

(3)发布订阅(Publish、Subscribe),根据交换机类型分为三种

  • Fanout Exchange:广播
  • Direct Exchange:路由
  • Topic Exchange:主题

5.SpringAMQP

(1)发送消息:

  • 引入amqp的starter依赖
  • 配置RabbitMQ地址
  • 利用RabbitTemplate的convertAndSend方法

(2)接收消息:

  • 引入amqp的starter依赖

  • 配置RabbitMQ地址

  • 定义类,添加@Component注解

  • 类中声明方法,添加@RabbitListener注解,方法参数就是消息

    注意:消息一旦消费就会从队列删除,RabbitMQ没有消息回溯功能

(3)Work模型的使用

  • 多个消费者绑定到一个队列,同一条消息只会被一个消费者处理
  • 通过设置prefetch来控制消费者预取的消息数量

(4)发布订阅模型:发布订阅模式与work的区别就是允许将统一消息发送给多个消费者。实现方式是加入了exchange(交换机)。

注意:exchange负责消息路由,而不是存储,路由失败则消息丢失

(5)Fanout Exchange

Fanout Exchange会将接收到的消息路由到每一个跟其绑定的queue

(6)交换机作用:

  • 接受publisher发送的消息
  • 将消息按照规则路由到与之绑定的队列
  • 不能缓存消息,路由失败,消息丢失
  • FanoutExchange的会将消息路由到每个绑定的队列

(7)DirectExchange

Direct Exchange会将接收到的消息根据规则路由到指定的Queue,因此称为路由模式(routes)。

  • 每一个Queue都与Exchange设置一个BindingKey
  • 发布者发送消息时,指定消息的RoutingKey
  • Exchange将消息路由到BindingKey与消息RoutingKey一致的队列

(8)TopicExchange

  • TopicExchange与DirectExchange类似,区别在于routingKey必须是多个单词的列表,并且以.分割

  • Queue与Exchange指定多个BindingKey时可以使用通配符:

    :代指0个或多个单词

    *:代指一个单词

(9)消息转换器

  • SpringAMQP中消息的序列化和反序列化是利用MessageConverter实现的,默认是JDK的序列化
  • 注意发送方与接收方必须使用相同的MessageConverter
posted @ 2024-03-18 20:48  __YJC  阅读(22)  评论(0编辑  收藏  举报