当前位置: 首页 > news >正文

每日学习Java之一万个为什么

文章目录

  • Docker
      • **一、基础命令**
        • **1. 启动/停止Docker服务**
        • **2. 查看Docker信息**
      • **二、镜像操作**
        • **1. 拉取镜像**
        • **2. 列出本地镜像**
        • **3. 删除镜像**
        • **4. 构建镜像**
        • **5. 推送镜像**
      • **三、容器操作**
        • **1. 创建并启动容器**
        • **2. 列出容器**
        • **3. 管理容器生命周期**
        • **4. 进入容器**
        • **5. 查看容器日志**
      • **四、网络操作**
        • **1. 网络管理**
      • **五、卷(Volume)操作**
        • **1. 数据卷管理**
      • **六、系统维护**
        • **1. 清理资源**
        • **2. 查看磁盘占用**
      • **七、其他实用命令**
        • **1. 容器操作**
        • **2. 帮助与文档**
      • **八、进阶命令示例**
        • **1. 端口映射与挂载卷**
        • **2. 资源限制**
      • **九、常见问题命令**
        • **1. 修复Docker进程占用过高**
        • **2. 查找未命名的容器**
      • **附录:快速参考表**
  • Gateway
    • 技术对比
    • 路由转发配置
    • 路由属性 RouterDefinition
    • 网关实现登录校验(JWT)
    • 自定义GatewayFilter
    • 网关处理请求的流程(责任链)
    • 网关过滤器
  • Sentinel
    • 配置信息
      • 1. **熔断降级配置**
        • (1) 基础熔断配置(Java代码)
        • (2) 动态规则配置(Nacos集成)
        • (3) 热点参数限流(秒杀场景)
      • 2. **流控模式与效果**
        • (1) **Warm Up(预热)配置**
        • (2) **排队等待**
    • 微服务集成
      • 1. **Spring Cloud集成步骤**
        • (1) 依赖添加
        • (2) Feign与Sentinel整合
        • (3) 全局异常处理
      • 2. **最佳实践**
  • Seata(分布式事务)
    • XA模式
      • 1. **XA模式原理**
      • 2. **Seata XA模式配置**
    • AT模式
      • 1. **AT模式原理**
      • 2. **Seata AT模式配置**
      • **XA模式 vs AT模式对比**
    • 总结
  • RabbitMQ
    • 同步和异步
    • MQ技术选型
    • 数据隔离
      • 知识总结
      • 注意
      • 使用场景
      • 常见八股文
    • Spring AMQP
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • Work 模式(工作队列)
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • MQ 消息转换器
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • 发布订阅模式(Pub/Sub)
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • 消息堆积问题处理
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • 发送者重连
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • 发送者确认
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • MQ 持久化
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • LazyQueue(惰性队列)
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • 消费者确认
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • 失败重试
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • 业务幂等
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
    • 延迟消息
      • 知识总结
      • 细节
      • 使用场景
      • 常见八股文
  • AOP代理失效的情况
      • **一、内部方法调用(this调用)**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **二、静态方法调用**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **三、final方法或类**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **四、私有方法(private)**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **五、未正确配置AOP**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **六、目标对象未由Spring管理**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **七、异步方法(@Async)**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **八、切点表达式错误**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **九、循环依赖**
        • **现象**
        • **原因**
        • **解决方法**
        • **示例**
      • **十、事务与AOP的冲突**
        • **现象**
        • **原因**
        • **解决方法**
      • **排查步骤总结**

Docker


一、基础命令

1. 启动/停止Docker服务
# 启动Docker服务(Linux)
sudo systemctl start docker# 停止Docker服务
sudo systemctl stop docker# 重启Docker服务
sudo systemctl restart docker# 设置开机自启
sudo systemctl enable docker
2. 查看Docker信息
# 查看Docker版本
docker version# 查看Docker系统详细信息(存储、网络、资源等)
docker info

二、镜像操作

1. 拉取镜像
# 从Docker Hub拉取镜像(默认latest标签)
docker pull 镜像名称[:标签]# 示例:拉取最新版Nginx镜像
docker pull nginx:latest
2. 列出本地镜像
# 查看所有本地镜像
docker images# 仅显示镜像ID(-q)
docker images -q# 查看所有镜像(含历史层)
docker images -a
3. 删除镜像
# 删除指定镜像(需停止所有关联容器)
docker rmi 镜像ID/名称# 强制删除镜像
docker rmi -f 镜像ID/名称# 清理未使用的镜像
docker image prune -a
4. 构建镜像
# 使用Dockerfile构建镜像(当前目录)
docker build -t 镜像名称[:标签] .# 示例:构建名为app:1.0的镜像
docker build -t app:1.0 .
5. 推送镜像
# 登录Docker Hub
docker login# 推送镜像到仓库
docker push 镜像名称[:标签]

三、容器操作

1. 创建并启动容器
# 后台运行容器并映射端口
docker run -d -p 宿主机端口:容器端口 镜像名称[:标签]# 示例:运行Nginx容器并映射8080→80端口
docker run -d -p 8080:80 nginx:latest# 指定名称启动容器
docker run --name 自定义名称 镜像名称
2. 列出容器
# 查看运行中的容器
docker ps# 查看所有容器(含已停止)
docker ps -a# 过滤显示(如仅显示名称)
docker ps --format "table {{.Names}}\t{{.Status}}"
3. 管理容器生命周期
# 停止容器
docker stop 容器ID/名称# 强制停止容器
docker stop -t 0 容器ID/名称# 启动已停止的容器
docker start 容器ID/名称# 删除容器
docker rm 容器ID/名称# 强制删除运行中容器
docker rm -f 容器ID/名称
4. 进入容器
# 交互式进入运行中的容器(新终端)
docker exec -it 容器ID/名称 /bin/bash# 以root权限进入(若容器支持)
docker exec -u root -it 容器ID/名称 /bin/sh
5. 查看容器日志
# 实时查看容器日志
docker logs -f 容器ID/名称# 查看指定行数日志
docker logs --tail 100 容器ID/名称

四、网络操作

1. 网络管理
# 创建自定义网络
docker network create 网络名称# 列出所有网络
docker network ls# 删除网络
docker network rm 网络名称# 将容器连接到网络
docker network connect 网络名称 容器ID/名称# 将容器从网络断开
docker network disconnect 网络名称 容器ID/名称

五、卷(Volume)操作

1. 数据卷管理
# 创建命名卷
docker volume create 卷名称# 列出所有卷
docker volume ls# 删除卷
docker volume rm 卷名称# 清理未使用的卷
docker volume prune

六、系统维护

1. 清理资源
# 清理所有无用资源(停止容器、未使用的镜像、卷、网络)
docker system prune -a# 清理停止的容器
docker container prune# 清理未使用的网络
docker network prune
2. 查看磁盘占用
# 查看Docker资源占用
docker system df

七、其他实用命令

1. 容器操作
# 查看容器实时资源使用(CPU/内存)
docker stats 容器ID/名称# 导出容器为tar文件
docker export 容器ID > 容器备份.tar# 导入tar文件为镜像
docker import 容器备份.tar 新镜像名称
2. 帮助与文档
# 查看Docker命令帮助
docker --help# 查看特定命令帮助(如docker run)
docker run --help

八、进阶命令示例

1. 端口映射与挂载卷
docker run -d \-p 8080:80 \          # 端口映射-v /宿主机路径:/容器路径 \  # 挂载卷--name my_container \  # 自定义名称nginx:latest
2. 资源限制
# 限制容器内存和CPU
docker run -d \--memory="512m" \     # 最大512MB内存--cpus="2" \          # 最多使用2个CPU核心my_app

九、常见问题命令

1. 修复Docker进程占用过高
# 查看占用资源最多的容器
docker stats
2. 查找未命名的容器
docker ps -a | grep "容器ID前缀"

附录:快速参考表

操作类型命令
基础服务systemctl start/stop/restart docker, docker info
镜像操作docker pull, docker images, docker rmi, docker build, docker push
容器操作docker run, docker ps, docker stop/start, docker exec
网络管理docker network create, docker network ls, docker network rm
清理资源docker system prune, docker image prune, docker volume prune

Gateway

技术对比

路由转发配置

路由属性 RouterDefinition

网关实现登录校验(JWT)

问题:怎么实现?

自定义过滤器:编写登录校验的Pre前置处理逻辑。校验时机:网关将请求转发到微服务之前。校验结果后的用户信息放置Http请求头中。

问题:如何自定义过滤器?

实现GlobalFilter接口,重写filter方法,并注册到Spring中。

问题:校验逻辑?

1.获取请求中的请求头中的 登录凭证

2.校验凭证

3.return chain.filter(exchange) 并保证我们的过滤器在NettyRoutingFilter之前执行。

问题:NettyRoutingFilter的实现是什么样的?
实现了globalfilter接口,以及Ordered接口。
Ordered接口需要返回一个优先级,值越低优先级越高,范围是int范围。

问题:微服务之间的用户信息如何存储?

分析:基于OpenFegin发起,可以也可以放在请求头里。

问题:请求头放置什么类型的数据?

自定义GatewayFilter

问题:为什么用GatewayFilter?怎么实现

更灵活。区别于globalfilter,需要实现一个抽象网关过滤器工厂。过滤器工厂可以读取配置并帮助你创建过滤器对象。无参过滤器具体实现是定义匿名内部类的方法。自定义gatewayfilter 方法名必须是
前缀+GatewayFilterFactory,前缀未来就是yml中的 filter: -前缀

网关处理请求的流程(责任链)

1.路由映射器:默认HandlerMapping 路由处理,将匹配的路由存储上下文

2.请求处理器:默认FilteringWebHandler,加载多个过滤器(Pre前置处理),放入集合中形成过滤器链,然后依次执行这些过滤器。

3.路由过滤器:NettyRoutingFilter,将请求转发到微服务(URI属性)并将响应结果存入上下文(Post后置处理)。

网关过滤器

  • GatewayFilter :针对特定路由 / yml中的过滤器属性或者配置到default-filter中,为所有未设置过滤器的路由生效。
  • GlobalFilter:全局过滤器,声明生效。

两种过滤器的接口方法签名完全一致:

Mon<Void> filter(ServerWebExchange exchage,GatewayFilterChain chain);

参数:

  • exchange:网关上下文
  • chain : 可以调用下一个过滤器

返回值:

  • Mono :定义回调函数(异步非阻塞编程)

使用场景:几乎不需要写Post

Sentinel


配置信息

1. 熔断降级配置

(1) 基础熔断配置(Java代码)
// 定义需保护的服务方法,绑定降级逻辑
@SentinelResource(value = "orderService", fallback = "orderFallback", blockHandler = "orderBlockHandler"
)
public OrderDTO getOrder(String orderId) {// 业务逻辑(如调用下游服务)
}// 通用异常降级方法(fallback)
public OrderDTO orderFallback(String orderId, Throwable e) {return new OrderDTO("DEFAULT_ORDER"); // 返回默认值或错误信息
}// 熔断触发时的专用处理(blockHandler)
public OrderDTO orderBlockHandler(String orderId, BlockException ex
) {return new OrderDTO("SERVICE_UNAVAILABLE"); // 服务不可用时的逻辑
}

说明

  • fallback:捕获业务异常(如空指针、数据库异常)。
  • blockHandler:捕获 Sentinel 规则触发的限流/降级(如QPS超过阈值)。
  • 双保险设计:两者结合可覆盖异常和流量控制场景(如知识库[1]中金融平台案例)。
(2) 动态规则配置(Nacos集成)
# application.yml(规则持久化配置)
spring:cloud:sentinel:datasource:ds1:nacos:server-addr: localhost:8848dataId: ${spring.application.name}-sentinel-rulesgroupId: DEFAULT_GROUPrule-type: flow
// Nacos中配置的流控规则示例
[{"resource": "orderService","grade": 1,          // QPS模式"count": 1000,       // 阈值1000 QPS"strategy": 0,       // 直接拒绝"controlBehavior": 0 // 快速失败},{"resource": "paymentService","grade": 2,          // 异常比例模式"count": 0.5,        // 异常率超过50%触发降级"strategy": 0}
]
(3) 热点参数限流(秒杀场景)
// 方法定义(需标注@SentinelResource)
@SentinelResource(value = "hotProduct", blockHandler = "hotProductBlock")
public Product getHotProduct(@RequestParam("productId") String productId) {// 业务逻辑(如查询热门商品)
}// 初始化热点参数规则(白名单配置)
public void initHotRules() {ParamFlowRule rule = new ParamFlowRule("hotProduct").setParamIdx(0)          // 参数索引(从0开始).setCount(100)           // 单参数阈值100 QPS.setGrade(RuleConstant.FLOW_GRADE_QPS).setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);// 添加例外项(如VIP用户不触发限流)rule.getParamFlowItemList().add(new ParamFlowItem().setSpecificItem("VIP_1001") // 指定参数值.setObjectType(ParamFlowItem setObjectTypeAnd));ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
}

2. 流控模式与效果

模式说明效果
直接单纯基于资源名的限流。快速失败、Warm Up(预热)、排队等待(需配置超时时间)。
关联根据关联资源的流量控制非核心操作(如读写分离场景)。例如:当核心写操作流量过高时,自动限流非核心读操作。
链路根据调用链路区分限流对象(如内部调用与外部调用)。例如:外部请求达到阈值时触发限流,内部调用不受影响。
(1) Warm Up(预热)配置
# 配置示例(application.yml)
spring.cloud.sentinel.flow.coldFactor=3  # 冷启动系数,默认3

逻辑

  • 初始QPS = 阈值 / coldFactor(如阈值12 → 起始QPS=4)。
  • 逐步提升至阈值(如4秒内从4 QPS线性增长到12 QPS)。
(2) 排队等待
# 示例配置(需结合规则JSON)
controlBehavior: 2  # 排队等待模式
maxQueueingTimeMs: 2000  # 等待超时时间(毫秒)

效果

  • 达到阈值后,请求进入队列等待,超时未处理则拒绝。

微服务集成

1. Spring Cloud集成步骤

(1) 依赖添加
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
(2) Feign与Sentinel整合
# application.yml启用Feign与Sentinel的集成
feign:sentinel:enabled: true
(3) 全局异常处理
@SentinelResource(fallback = "globalFallback",blockHandler = "globalBlockHandler"
)
@RestControllerAdvice
public class GlobalExceptionHandler {public OrderDTO globalFallback(Throwable e, BlockException ex) {// 全局降级逻辑return new OrderDTO("GLOBAL_ERROR");}
}

2. 最佳实践

  • 服务雪崩防护:对核心服务配置熔断(如知识库[1]中金融平台提升37%成功率)。
  • 监控与告警:通过Sentinel Dashboard实时监控指标(QPS、异常率、熔断状态)。
  • 动态规则管理:结合Nacos或Apollo实现规则热更新,无需重启服务。

Seata(分布式事务)

在这里插入图片描述

在这里插入图片描述

XA模式

1. XA模式原理

  • 角色

    • TM(事务管理器):协调全局事务(如Seata的TC)。
    • RM(资源管理器):管理资源(如数据库)。
    • AP(应用):发起事务请求。
  • 流程

    1. 准备阶段:AP向TM提交事务,TM通知各RM准备(锁资源)。
    2. 提交阶段:TM收集RM状态,若全部成功则提交,否则回滚。
  • 特点

    • 强一致性:依赖数据库对XA协议的支持(如MySQL 8+)。
    • 性能开销大:需两阶段提交,资源锁定时间长。

2. Seata XA模式配置

# seata.config
transaction.service.group.xa.DataSource.XADataSourceType = mysql
transaction.service.group.xa.DataSource.user = root
transaction.service.group.xa.DataSource.password = root
// 业务代码示例(需@GlobalTransactional注解)
@GlobalTransactional
public void saveOrder(OrderSaveParam param) {// 跨服务操作(如扣减库存、生成订单)// 异常时自动回滚
}

AT模式

1. AT模式原理

  • 自动补偿机制:通过异步提交快照对比实现最终一致性。
  • 流程
    1. 预写阶段:记录业务数据的前后快照。
    2. 提交阶段:直接提交业务数据,异步对比快照完成最终提交或回滚。
  • 特点
    • 无侵入性:无需数据库支持XA协议。
    • 性能较高:避免两阶段提交的锁竞争问题。

2. Seata AT模式配置

# seata.config
transaction.service.group.at.DataSource.driverClass = com.mysql.cj.jdbc.Driver
transaction.service.group.at.DataSource.url = jdbc:mysql://localhost:3306/test?useSSL=false
// 业务代码与XA模式相同,只需切换模式
@GlobalTransactional
public void saveOrder(OrderSaveParam param) {// 同样实现跨服务操作
}

XA模式 vs AT模式对比

维度XA模式AT模式
一致性强一致性(两阶段提交)最终一致性(异步补偿)
性能较低(锁资源时间长)较高(无锁设计)
数据库依赖需支持XA协议(如MySQL 8+)无需XA协议,支持主流数据库
适用场景高一致性要求的金融场景高并发、低延迟的电商、互联网场景

总结

  • Sentinel:用于流量控制、熔断降级,保障单服务稳定性。
  • Seata XA/AT模式:解决分布式事务问题,确保跨服务数据一致性。
  • 组合方案:在微服务架构中,Sentinel可与Seata结合,既控制流量又保证事务。

如需进一步优化配置或具体场景实现,可参考知识库中的代码示例和最佳实践!

RabbitMQ

高性能异步通信组件

同步通讯:打视频,打电话(实时阻塞)

异步通讯:WX聊天(非阻塞)
在这里插入图片描述

同步和异步

同步调用:需要等待调用的结果 (大概是核心业务)

异步调用:无需等待调用结果 / 回复 (大概是边缘业务)

问题:异步调用为什么需要消息代理?
消息的接收方可能在忙。需要驿站

MQ技术选型

在这里插入图片描述

数据隔离

知识总结

  • 虚拟主机(Virtual Host):逻辑隔离不同业务的数据,每个虚拟主机独立管理队列、交换机和权限。
  • 用户权限:通过用户与虚拟主机的绑定实现权限隔离,用户只能操作关联虚拟主机内的资源。

注意

  • 默认虚拟主机/ 是默认虚拟主机,需谨慎使用。
  • 权限配置:需显式授予用户对虚拟主机的 configurewriteread 权限。

使用场景

  • 多项目/团队共享同一 RabbitMQ 集群时,避免数据互相干扰。
  • 敏感业务需独立资源管理(如金融、日志系统)。

常见八股文

  • Q:如何实现 RabbitMQ 的数据隔离?
    A:通过创建独立虚拟主机,并为不同用户分配对应虚拟主机的权限。
  • Q:虚拟主机与用户权限的关系?
    A:用户需绑定到虚拟主机,且需显式授予操作权限(如 set_permissions)。

Spring AMQP

知识总结

  • 核心组件RabbitTemplate(发送消息)、@RabbitListener(消费消息)、MessageConverter(消息转换)。
  • 自动声明:通过配置自动创建队列、交换机及绑定关系。

细节

  • 消息序列化:默认使用 JdkSerializationConverter,生产环境推荐 Jackson2JsonMessageConverter,两者不兼容。
  • 事务与确认:需显式配置 publisher-confirmspublisher-returns,并配置相应的回调函数。

使用场景

  • Spring Boot 项目中快速集成 RabbitMQ,实现消息的发送与消费。

常见八股文

  • Q:如何配置 JSON 消息转换器?
    A:通过 @Bean 注册 Jackson2JsonMessageConverter
  • Q:Spring AMQP 如何实现消息确认?
    A:配置 PublisherCallbackChannel 并实现 CorrelationData

Work 模式(工作队列)

知识总结

  • 特性:一个生产者、多个消费者,消息默认按轮询分发,确保消息被消费一次。
  • 负载均衡:消费者按能力拉取消息(基于 prefetch-count 配置)。

细节

  • 公平调度:需设置合理 prefetch-count(默认 256),避免快慢消费者不均。
  • 消息持久化:需同时设置队列持久化(durable)和消息持久化(persistent)。

使用场景

  • 高并发任务处理(如订单创建、日志收集)。

常见八股文

  • Q:Work 模式如何实现公平分发?
    A:通过设置 prefetch-count 为 1,确保消费者处理完当前消息后才拉取新消息。
  • Q:Work 模式与发布订阅的区别?
    A:Work 模式消息被消费一次,发布订阅消息被所有消费者接收(FanOut交换机)。

MQ 消息转换器

知识总结

  • 作用:将 Java 对象与字节流相互转换,支持 JSON、XML、序列化等格式。
  • 核心类MessageConverter(如 Jackson2JsonMessageConverter)。

细节

  • 一致性:生产者与消费者需使用相同的转换器。
  • 自定义转换:可通过继承 AbstractJavaTypeMapper 处理复杂对象映射。
  • Jackson序列化比JDK ObjectOutputStream的转换更小,而且可读性更高。

使用场景

  • 发送复杂对象(如 Java Bean)时避免二进制序列化。

常见八股文

  • Q:如何自定义消息转换器?
    A:实现 MessageConverter 接口,覆盖 toMessagefromMessage 方法。
  • Q:为什么 JSON 转换器比默认序列化更好?
    A:JSON 更易读、体积小,且支持跨语言解析。

发布订阅模式(Pub/Sub)

知识总结

  • 特性:消息被广播到所有绑定的队列,每个消费者独立消费一份副本。
  • 交换机类型fanout(无路由键)、topicdirectheaders

细节

  • 临时队列:消费者可声明 exclusive 队列,断开后自动删除。
  • 路由规则topic 支持通配符(* 匹配一个词,# 匹配多个词)。

使用场景

  • 实时通知(如系统告警、消息广播)。

常见八股文

  • Q:如何实现精准匹配的 Pub/Sub?
    A:使用 direct 交换机,通过路由键精确匹配队列。
  • Q:fanout 与 topic 的区别?
    A:fanout 不区分路由键,消息广播给所有绑定队列;topic 支持通配符路由。

消息堆积问题处理

知识总结

  • 原因:生产速度 > 消费速度,或消费者故障。
  • 解决方案:扩容消费者、优化消费逻辑、调整预取数、使用优先级队列。

细节

  • 预取数(prefetch-count):过高可能导致内存溢出,过低影响吞吐。
  • 死信队列:设置 max-lengthttl,将未及时消费的消息转存。

使用场景

  • 高峰流量(如秒杀、促销活动)时的流量削峰。

常见八股文

  • Q:如何快速缓解消息堆积?
    A:扩容消费者、优化消费逻辑、调整预取数、启用死信队列。
  • Q:消息堆积时如何保证消息不丢失?
    A:确保消息持久化、消费者确认模式为 manual/auto

发送者重连

知识总结

  • 机制:RabbitMQ 客户端通过 Retry 机制自动重连。
  • 配置参数connection-factoryrecovery-intervalautomatic-recovery-enabled

细节

  • 重连间隔:默认 5 秒,需根据业务调整。
  • 未确认消息:重连后需手动重发未确认的消息(如使用 PublisherCallbackChannel)。

使用场景

  • 网络波动或服务重启时保持生产者稳定性。

常见八股文

  • Q:如何配置 RabbitMQ 的重连策略?
    A:通过 CachingConnectionFactory 设置 setRetrysetRecoveryInterval
  • Q:重连时如何避免消息重复?
    A:结合消息 ID 和数据库幂等处理。

发送者确认

知识总结

  • Confirm 确认:确认消息到达交换机。
  • Return 确认:确认消息未被路由到队列(需设置 mandatory)。

细节

  • 异步确认:通过 ConfirmCallback 处理大规模消息。
  • 消息丢失场景:需结合持久化和持久化确认。

使用场景

  • 需要保证消息到达交换机的场景(如订单通知)。

常见八股文

  • Q:Confirm 与 Return 的区别?
    A:Confirm 确认消息到达交换机,Return 确认消息未被路由到队列。
  • Q:如何实现消息的可靠投递?
    A:结合 Confirm、Return 和持久化,配合数据库记录状态。

MQ 持久化

知识总结

  • 队列持久化:设置 durable = true
  • 消息持久化:设置 messageProperties.setDeliveryMode(PERSISTENT)
  • 磁盘写入:需配合 镜像队列集群 避免单点故障。

细节

  • 持久化 ≠ 安全:需结合主从复制或集群保证高可用。
  • 性能影响:持久化会降低吞吐量,需权衡可靠性与性能。

使用场景

  • 重要业务消息(如支付、订单)需持久化。

常见八股文

  • Q:如何实现消息的持久化?
    A:队列设置 durable,消息设置 persistent,并启用磁盘写入。
  • Q:持久化消息丢失的可能原因?
    A:未配置持久化、磁盘故障、未启用主从复制。

LazyQueue(惰性队列)

知识总结

  • 特性:消息先存储在磁盘,延迟加载到内存,适合冷数据存储。
  • 配置:队列参数 x-queue-mode = lazy
  • 版本:3.12 版本后队列默认为惰性队列无法修改

细节

  • 吞吐量下降:磁盘读取速度低于内存,适合低频消费场景。
  • 内存占用:显著降低,适合存储大量不活跃消息。
  • 并发量:能够处理的并发量是上升的。

使用场景

  • 日志归档、历史数据存储。

常见八股文

  • Q:LazyQueue 与普通队列的区别?
    A:LazyQueue 消息存储磁盘,减少内存占用,但吞吐量低。
  • Q:何时使用 LazyQueue?
    A:消息需长期存储且消费频率低时。

消费者确认

知识总结

  • 自动确认autoAck = true,消费立即确认。
  • 手动确认autoAck = false,需显式调用 basicAck

细节

  • 未确认消息:消费者崩溃时消息重新入队(需幂等处理)。
  • 批量确认:通过 basicAckmultiple 参数优化性能。

使用场景

  • 需要确保消息被正确处理后再确认(如事务型操作)。

常见八股文

  • Q:手动确认 vs 自动确认?
    A:手动确认避免消息丢失,但需处理幂等;自动确认简单但可能丢失消息。
  • Q:如何实现批量确认?
    A:设置 multiple = true 并定期调用 basicAck

失败重试

知识总结

  • 死信队列(DLX):将失败消息路由到指定队列,由备用消费者处理。
  • 重试机制:通过 RetryTemplateSpring Retry 实现本地重试。

细节

  • 死信条件:需设置 x-dead-letter-exchangemax-delivery
  • 重试间隔:指数退避避免雪崩,需与业务逻辑匹配。

使用场景

  • 需要重试的失败消息(如网络波动、临时服务不可用)。

常见八股文

  • Q:如何配置死信队列?
    A:设置队列参数 x-dead-letter-exchangex-dead-letter-routing-key
  • Q:本地重试与死信队列的区别?
    A:本地重试在消费者端重试,死信队列将消息转移至其他队列处理。

业务幂等

知识总结

  • 核心思想:同一消息多次处理结果一致。
  • 实现方式:数据库唯一索引、Redis 记录消息 ID、版本号校验。

细节

  • 分布式幂等:需全局唯一 ID(如 UUID)和分布式锁。
  • 幂等与性能:如 Redis 记录需考虑缓存穿透和过期时间。

使用场景

  • 避免重复扣款、重复发券等业务场景。

常见八股文

  • Q:如何实现 RabbitMQ 消息的幂等性?
    A:通过消息 ID 记录(如 Redis)或数据库唯一约束。
  • Q:幂等与事务的区别?
    A:幂等关注结果一致性,事务关注操作的原子性。

延迟消息

知识总结

  • 实现方式
    1. 插件方式rabbitmq_delayed_message_exchange(需配置 x-delay)。
    2. 死信方式:通过 TTL + DLX 实现。
  • 插件配置:声明延迟交换机 x-delayed-message

细节

  • 插件依赖:需安装 rabbitmq_delayed_message_exchange 插件。
  • TTL 方案:需多个队列支持不同延迟时间。

使用场景

  • 定时任务(如优惠券过期通知、订单超时取消)。

常见八股文

  • Q:RabbitMQ 如何实现延迟消息?
    A:使用延迟插件或 TTL + DLX 方案。
  • Q:插件方案与 TTL 方案的优缺点?
    A:插件方案灵活(单消息延迟),TTL 需预设队列但性能更高。

AOP代理失效的情况


一、内部方法调用(this调用)

现象
  • 目标类中一个方法调用本类的另一个方法时,AOP不生效。
原因
  • AOP通过代理对象拦截方法调用,但this引用直接指向原始对象,绕过了代理。
解决方法
  1. 通过代理对象调用:从Spring容器中获取代理对象。
  2. 启用CGLIB代理:配置proxyTargetClass=true
示例
@Service
public class MyService {@Autowiredprivate MyService proxyService; // 通过Spring注入代理对象public void methodA() {methodB(); // 失效(直接调用this的方法)proxyService.methodB(); // 生效(通过代理对象调用)}@Loggable // 自定义切面注解public void methodB() {}
}
// 配置CGLIB代理
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {}

二、静态方法调用

现象
  • 切面无法拦截静态方法。
原因
  • 静态方法属于类而非实例,代理对象无法覆盖静态方法。
解决方法
  • 将静态方法改为实例方法,并确保通过代理对象调用。
示例
public class MyService {public static void staticMethod() { // 无法被AOP拦截// ...}public void instanceMethod() { // 可被拦截// ...}
}

三、final方法或类

现象
  • 标有final的关键字的方法或类无法被AOP拦截。
原因
  • CGLIB无法生成子类覆盖final方法。
解决方法
  • 移除final修饰符。
示例
@Service
public class MyService {@Loggablepublic final void finalMethod() { // 失效(final方法)// ...}
}

四、私有方法(private)

现象
  • 私有方法无法被切面拦截。
原因
  • 代理对象无法访问私有方法。
解决方法
  • 将方法改为publicprotected或包级可见。
示例
@Service
public class MyService {@Loggableprivate void privateMethod() { // 失效(私有方法)// ...}
}

五、未正确配置AOP

现象
  • 切面类未被识别或切点表达式错误。
原因
  • 缺少@Aspect注解或未启用AOP支持。
解决方法
  1. 添加@Aspect到切面类。
  2. 确保主配置类有@EnableAspectJAutoProxy
示例
// ✅ 正确配置
@Aspect
@Component
public class LoggingAspect {@After("execution(* com.example..*(..))")public void log() {System.out.println("Logged!");}
}@Configuration
@EnableAspectJAutoProxy
public class AppConfig {}

六、目标对象未由Spring管理

现象
  • 手动new的对象无法触发AOP。
原因
  • 非Spring管理的对象没有被代理。
解决方法
  • 通过@AutowiredApplicationContext获取Bean。
示例
// ❌ 错误:手动new对象
MyService service = new MyService();
service.method(); // 无AOP// ✅ 正确:通过Spring容器获取
@Autowired
private MyService service;
service.method(); // 有AOP

七、异步方法(@Async)

现象
  • 标有@Async的方法可能无法触发AOP。
原因
  • 异步方法由独立线程执行,代理逻辑可能未正确传递。
解决方法
  • 确保切面支持异步方法,或使用@EnableAsync并配置代理。
示例
@Service
public class MyService {@Async@Loggablepublic void asyncMethod() { // 需要特殊处理// ...}
}

八、切点表达式错误

现象
  • 切点未匹配到目标方法。
原因
  • 表达式语法错误或范围不匹配。
解决方法
  • 检查execution表达式是否正确。
示例
// ❌ 错误表达式:未匹配到包路径
@After("execution(* com.example.service..*(..))")// ✅ 正确表达式:匹配所有service包的方法
@After("execution(* com.example.service.*.*(..))")

九、循环依赖

现象
  • 循环依赖可能导致AOP代理未正确生成。
原因
  • Spring在解决循环依赖时可能返回未增强的早期Bean引用。
解决方法
  • 重构代码消除循环依赖,或使用@Lazy延迟注入。
示例
@Service
public class ServiceA {@Autowiredprivate ServiceB serviceB; // 可能导致循环依赖
}@Service
public class ServiceB {@Autowiredprivate ServiceA serviceA;
}

十、事务与AOP的冲突

现象
  • 事务注解@Transactional与AOP同时失效。
原因
  • 事务本身依赖AOP代理,若AOP失效则事务也失效。
解决方法
  • 确保事务方法在代理对象上调用(如Service层而非内部调用)。

排查步骤总结

  1. 检查配置:确认切面类有@Aspect,主类有@EnableAspectJAutoProxy
  2. 验证Bean管理:确保目标对象是Spring管理的Bean。
  3. 检查方法可见性:非public方法或final方法无法被拦截。
  4. 内部调用问题:通过代理对象调用方法,避免this直接调用。
  5. 切点表达式:确保表达式语法正确且匹配目标方法。
  6. 异步与事务:处理@Async@Transactional的特殊场景。
http://www.xdnf.cn/news/63415.html

相关文章:

  • 用银河麒麟 LiveCD 快速查看原系统 IP 和打印机配置
  • 学习海康VisionMaster之垂线查找
  • 【大数据分析】Apache Doris高性能实时分析数据库:MPP架构下的多场景应用与优势分析以及部署应用
  • Spark-SQL连接Hive全攻略
  • (mamba_ssm)安装踩坑指南
  • JavaScript与TypeScript
  • Buildroot、BusyBox与Yocto:嵌入式系统构建工具对比与实战指南
  • 【C++教程】C++中为什么优先使用 cout/cin流
  • 【自然语言处理与大模型】模型压缩技术之剪枝
  • 可穿戴无线生理信号采集贴片产品市场需求简析
  • 关于ORM
  • numpy、pandas内存优化操作整理
  • 【嵌入式系统设计师(软考中级)】第二章:嵌入式系统硬件基础知识(上)
  • Web 前端打包工具与构建系统的进阶指南
  • Kafka 生产者的幂等性与事务特性详解
  • 归一化对C4.5决策树无效的数学原理与实证分析
  • 配置 VS Code 使用 ESLint 格式化
  • 利用课程编辑器创新教学,提升竞争力​
  • VSCode连接服务器跑深度学习代码相关问题(研0大模型学习第八天)
  • 【软件工程】软件测试基础知识
  • 在springboot3.4.4和jdk17环境下集成使用mapstruct
  • 使用Postman调测“获取IAM用户Token”接口实际操作
  • 性能比拼: Nginx vs Apache
  • nn.LayerNorm():对输入张量的最后一个维度(特征维度)进行归一化
  • 【目标检测】目标检测综述 目标检测技巧
  • 全球首个人形机器人半程马拉松技术分析:翻车名场面背后的突破与挑战
  • DeepSeek赋能Nuclei:打造网络安全检测的“超级助手”
  • 量化研究---小果全球大类低相关性动量趋势增强轮动策略实盘设置
  • ThinkPHP5 的 SQL 注入漏洞
  • 【时时三省】(C语言基础)循环的嵌套和几种循环的比较