杂七杂八

tim-qtp2025年4月2日...大约 27 分钟Java基础集合

云图库项目中,你如何存储图片数据?怎么获取到图片信息?

在云图库项目中,我选择使用对象存储来存储图片文件。一方面,借助云厂商(如腾讯云 COS)提供的对象存储可以快速解决海量图片的存储、传输、扩容和备份问题;另一方面,腾讯云对象存储还提供 “数据万象” 图像处理服务,可以在图片上传时自动解析并返回图片的尺寸、大小、格式等元数据信息。

具体实现流程:

1)项目中整合对象存储:

  • 在后端配置文件中写好存储桶(bucket)名称、访问域名、密钥等信息,编写一个配置类来读取参数并初始化客户端。
  • 初始化客户端后,我编写了一个通用的对象存储调用类(CosManager),通过 cosClient.putObject 方法实现上传文件到存储桶。
  • 基于对象存储调用类进一步封装了适用于本项目的文件上传管理类(FileManager),简化文件上传的调用。

2)自动获取图片信息:

  • 在上传图片时,启用 “数据万象” 功能,对图片进行基础信息解析。
  • 解析结果中包含宽度、高度、格式等字段,我再将这些信息写到数据库表的相应字段,便于后续查询与筛选。

这样一来,图片实际的二进制数据并不放在后端服务器或数据库中,而是托管给对象存储服务进行管理,既省去了服务器磁盘维护的繁琐,又能利用云存储高可用的特性,提升系统的稳定性和可扩展性。

云图库项目中,你如何实现图片审核功能?

为了避免用户上传的图片内容违规或存在版权风险,给图片模块增加了 “审核功能”。

整体策略包括:

  1. 在数据库中为图片表(picture)添加审核状态字段(reviewStatus)和审核信息(reviewMessage、reviewerId、reviewTime)。
  2. 用户上传或编辑图片时,图片默认状态为 “待审核” 或自动过审(如果是管理员上传);管理员审核后可将状态修改为 “通过” 或 “拒绝”。
  3. 对于审核状态为 “通过” 的图片,普通用户在查询时才能看到;未通过或拒绝的图片仅管理员可见。
  4. 管理员可随时修改图片的审核状态,同时记录审核人、审核时间及原因,方便后期追溯。

这样一来,既能保证图片内容的安全与合规,也能将违规图片拒之门外,提高系统整体质量。

此外,其实我还了解更多企业中的审核策略,比如:

  1. 内容安全审核服务:借助专业的第三方平台的内容审核服务来实现自动审核,像腾讯云、阿里云等基本都支持图片、文本、音视频等内容的审核。
  2. AI 审核:可以将文本内容和审核规则输入给 AI,让 AI 返回是否合规。
  3. 分级审核策略:区分普通用户与高信誉用户,高信誉用户可减少或免除审核流程,比如 VIP 用户自动过审,也可以提高部分效率。
  4. 实名信息和内容溯源:通过用户实名或者手机号注册,提高用户行为的责任感,减少垃圾内容的产生。
  5. 举报机制:通过给平台增加举报机制,还可以给举报行为一些奖励,让用户帮忙维护平台。

云图库项目中,你如何实现通过 URL 上传图片功能?

在云图库项目中,我不仅支持用户上传本地图片文件,也支持直接填写网络图片的 URL 链接,后端自动下载并导入到对象存储中。大致流程如下:

  1. 前端将用户输入的图片 URL 发送给后端。
  2. 后端对该链接进行校验:先用 HEAD 请求检查链接是否存在,并获取其文件大小、类型等元信息,而不是下载文件后再校验,可以节约流量。若检测到格式错误(非 JPEG、PNG 等)或文件过大(超过 2MB),则拒绝上传。
  3. 若链接校验通过,后端使用 Hutool 的 HttpUtil.downloadFile 将图片下载到本地临时文件。
  4. 将临时文件上传到对象存储服务,并利用数据万象接口解析图片宽高、大小、格式等元信息。
  5. 将解析到的信息与文件 URL 一起写入数据库,完成导入操作。

其实步骤 4 和 5 都可以复用我已经实现的本地图片上传功能,因此我也将两种文件上传方式使用模板方法设计模式重构,减少了重复代码,并提高了代码的可扩展性和可维护性。

什么是模板方法设计模式?在云图库项目中如何使用模板方法模式?

模板方法设计模式是一种行为型设计模式,它将某一通用流程的各个步骤抽象出来,并定义在父类的 “模板方法” 里,而将具体差异的实现细节留给子类来完成。简单来说,就是 “固定整体流程,允许子类覆盖部分步骤”。

在云图库项目中,我使用了模板方法模式来统一处理图片上传流程:

  1. 把图片上传的通用步骤(校验 -> 生成临时文件 -> 上传到对象存储 -> 解析图片信息 -> 删除临时文件)定义在抽象类 PictureUploadTemplate 中。
  2. 针对 “本地文件上传” 和 “URL 上传” 两种场景,我分别实现了不同的子类 FilePictureUploadUrlPictureUpload,只需要在 “校验图片”、“获取文件名”、“下载/处理文件” 这几个与输入源相关的步骤上实现不同的逻辑即可,其他步骤则在模板父类里复用。

这样,不仅减少了大量重复代码,也让后续扩展新的文件来源时更加容易 —— 只需继承抽象类,覆盖相关方法即可,实现了对扩展开放、对修改封闭的设计思路。

云图库项目中,你怎么实现网络图片的批量抓取和导入功能?

核心思路是:利用 Jsoup 实现 Bing 网页图片抓取,并将图片进行批量上传和入库。

具体步骤:

  1. 指定搜索关键词与抓取数量:管理员在前端界面输入想抓取的关键词(比如 “壁纸”),以及一次要抓取的图片数量。
  2. 爬取图片链接:后端根据关键词拼接目标 URL(Bing 图片搜索的地址),请求返回的 HTML 网页后使用 Jsoup 解析 DOM,获取所有图片的地址。
  3. 逐条下载并上传:对每个图片链接,先做必要的校验(如过滤多余参数),然后将其下载到本地临时文件,最终上传到对象存储服务中。
  4. 插入数据库记录:把每张成功上传的图片信息保存到 picture 表。如果需要分批次命名,可以加个“名称前缀” 参数,让所有图片名称带上统一前缀。
  5. 容错:为防止爬取过快导致被封,通过 Thread.sleep 增加间隔;如果某张图片下载失败或不通过校验,系统会跳过继续下一张图片,最后统计成功条数。

通过这套批量抓取方案,管理员可一键快速引入大批外部图片,大大减少了前期项目冷启动时手动上传图片的工作量。

云图库项目中,你通过哪些策略对图片功能进行优化?比如性能和成本优化

为提升云图库的性能并降低成本,我对图片查询、上传、加载、存储等环节进行了多方位的优化。

1)图片查询优化:

  • 结合 Redis 和 Caffeine,构建了多级缓存体系,先从本地缓存查询,若未命中再查分布式缓存。这样既能充分利用内存的高速访问,又确保了分布式环境下的数据一致性。
  • 将高频访问的热点图片以及复杂查询结果直接缓存,减少对数据库的压力,成倍缩短了首页响应时间。

2)图片上传优化:

  • 在上传时利用数据万象服务自动将图片格式转换为 WebP 进行压缩,有效降低图片文件大小,节省带宽,提升加载速度。
  • 支持分片上传和断点续传,用于大文件场景,减少网络波动对上传体验的影响。我也尝试过实现文件秒传,通过对文件哈希(MD5)进行校验,避免重复上传。

3)图片加载优化:

  • 生成缩略图,在首页或列表页仅加载缩略图,用户查看图片详情时再加载清晰原图,大幅减少流量。
  • 利用 CDN 加速,将图片资源分配到各地 CDN 节点,用户就近访问,从而降低延迟;并开启浏览器缓存头,进一步提升重复访问的加载速度。
  • 懒加载技术,让页面只在图片真正出现在可视区域时再请求资源,降低一次性加载的压力。

4)图片存储优化:

  • 使用对象存储配合数据沉降(生命周期管理)策略,对 30 天未访问的图片自动切换至低频存储,降低存储费用。
  • 定期清理不再使用或重复的图片文件,减少冗余占用空间。

经过上述优化,系统整体的性能显著提升,同时有效地控制了存储与带宽成本。

什么是 Redis 和 Caffeine?你在云图库项目中如何利用它们构建多级缓存?

Redis 是一种高性能的分布式 KV 存储,支持丰富的数据结构和高并发访问。它能把缓存数据存储在内存中,单节点读写 QPS 可达 10 万,常用于做分布式缓存或分布式锁。

Caffeine 是 Java 主流的本地缓存库,运行在 JVM 内部,访问速度比 Redis 更快,但仅能在单个服务实例内使用,无法在多台服务器之间共享数据。

我在云图库项目中将二者结合,形成多级缓存:

  1. 用户请求先查询 Caffeine 本地缓存
  2. 若本地缓存未命中,则查询 Redis 缓存
  3. 若 Redis 也未命中,则回源到数据库,并将查询结果写回 Redis 与 Caffeine

这样既保证了本地缓存的高速访问,又利用 Redis 做到跨节点数据一致和高可用,提升性能的同时减少对数据库的重复查询。

什么是 CDN?云图库项目中如何利用 CDN 提升图片加载性能?

CDN 内容分发网络是通过将文件分发到全球或全国各地的加速节点,让用户就近从最近的节点访问资源,减少跨网络、跨地域带来的延迟,提高加载资源的速度。

在云图库项目里,我将 COS 对象存储作为 “源站”,再给图片地址配置一层 CDN,起到了这些作用:

  1. 请求拦截:用户访问图片时,先由 CDN 节点判断是否有缓存;若已缓存,则直接返回,加快响应;若无缓存,则回源到 COS 存储获取。
  2. 全局分发:CDN 在各地设有大量加速节点,用户与节点间的距离近、线路好,显著缩短 RTT 和传输时延。
  3. 保护源站:高并发时,绝大多数请求被 CDN 节点拦住,源站压力大幅下降。此外我还通过配置防盗链、带宽监控等策略防止资源滥用和 CDN 被刷量。

使用 CDN 后,我也用 F12 网络控制台看了下请求资源的加载时间,确实加载更快了,也更安全稳定。

什么是降频存储?在云图库项目中,它起到了什么作用?

降频存储指的是将长时间不访问或访问极少的文件从 “标准存储” 自动迁移到 “低频存储” 或 “归档存储” 的过程,降低资源占用成本。

COS 对象存储提供了 “生命周期管理” 功能,可以根据设定的规则自动识别并迁移不活跃的数据。

在云图库项目中,图片在上传初期可能访问量较高,但随着时间推移,不少图片会排到后面的分页中,几乎不会有用户访问。对这类 “冷数据” 图片设置降频存储后,日常占用的存储费用会更低,帮助我们显著节省成本。只有当用户重新访问这些冷数据时才会触发取回费用,但这种情况通常很少,所以我还是开启了降频存储策略。

什么是文件秒传?在云图库项目中,你怎么实现文件秒传?

文件秒传主要运用于大文件上传场景,是通过 “文件指纹” 来识别文件是否已上传过的一种技术。若已存在相同文件,就无需再次传输,直接复用之前的文件存储记录,大幅减少上传时间和流量消耗。

我的实现思路:

  1. 指纹计算:用户在上传前计算文件 MD5(或 SHA-256)哈希
  2. 指纹查重:后端检索数据库,看是否已有相同指纹的文件
  3. 复用记录:若找到相同文件,则跳过上传过程,直接返回之前的存储地址;若没找到,则正常上传并存储文件指纹。

在云图库项目中,图片文件不大,因此秒传的收益有限。但如果有用户可能频繁上传同一大文件,通过这种方式可减少重复上传,节省存储与带宽成本。

什么是文件分片上传和断点续传?在云图库项目中,你怎么实现它们?

1)文件分片上传:将一个大文件拆分成多个小块(分片),逐一上传到服务器。这样可以并发上传各分片,提高带宽利用率,同时若部分分片上传失败,仅需重传失败的分片,避免整体重传。

2)断点续传:在网络中断或上传过程中出现异常时,客户端可从已上传成功的分片或位置继续上传,而不必从头再来,实现更加稳定、高效的大文件上传。

在云图库项目中,我基于 COS 对象存储服务的 SDK 来实现分片上传与断点续传。只需在调用接口时指定分片参数,后端会自动管理各分片的合并与校验。若中途中断,下次上传请求带上已上传好的分片信息,继续传剩余分片即可,从而显著提升网络不稳定场景下的用户体验和上传效率。

云图库项目中,你怎么保证用户最多只能创建一个空间?

我在云图库项目采用了 加锁 + 事务 的方式来限制用户仅能创建一个私有空间:

  1. 数据库设计:在 space 表中根据 userId 查询是否已创建空间,若已创建则阻止再次创建。
  2. 本地分段锁:以 userId 作为锁的 key,进入创建空间的代码前,对该 key 进行 synchronized(或在一个 并发 Map 里)加锁,避免并发下同一个用户多次创建。
  3. 编程式事务:在加锁后,用 transactionTemplate 开启数据库事务,先查询 userId 是否已有空间,再写入新空间记录,若过程中出错则回滚。事务执行完成后释放锁。

云图库项目中,你怎么保证用户上传图片不会超过空间额度?

为了防止用户无限制占用存储资源,我在云图库项目里为每个空间都配置了最大图片数量(maxCount)和最大总大小(maxSize)两种限制,并且在图片上传和图片删除环节都做了相应的更新与校验:

  1. 上传前校验:根据 spaceId 查到该空间的当前已用大小 totalSize 和数量 totalCount,分别与 maxSize、maxCount 对比。若空间或用户已超出限额,则拒绝这次上传请求。
  2. 上传成功后更新: 进入数据库事务,先写入图片表,再将 totalSize 累加上这张图片的大小、totalCount +1。 若任意一步失败,就回滚事务,保证数据的一致性。
  3. 删除图片后释放: 删除图片时,也在同一事务内把对应的大小和数量从 space 的 totalSize、totalCount 字段中减去,确保计量准确。

通过 上传前校验 + 事务内原子更新 的方式,即使在并发场景下,也能让空间用量处于可控状态,一旦某个空间达到了最大额度就禁止再传图,大幅降低系统被滥用的风险。

此外,参考大厂云服务的设计,我允许用户小幅超出额度(比如上传最后一张图时,即使会超额也允许上传),一定程度上减少了开发难度,并提升了用户体验。

云图库项目的后端中,你如何实现多维度的图片搜索功能?

在云图库项目里,我通过封装图片查询请求类,并在查询接口增加多种筛选条件,来实现多维度的图片搜索。主要思路:

  1. 定义一个 PictureQueryRequest 对象,除了基本的分页参数,还支持按名称、简介、分类、标签、编辑时间范围、格式、宽高等维度传参。
  2. 在服务层写一个 getQueryWrapper 方法,根据请求参数动态构造数据库查询条件,比如 queryWrapper.like(StrUtil.isNotBlank(name), "name", name) 等。
  3. 在控制层接收搜索请求并调用 service 进行分页查询,结果返回 Page 列表

前端在搜索表单里,可将这些搜索条件分为常用筛选(关键词、标签、分类)和更多筛选(日期、宽高、格式)等,实现灵活的多维度检索。

这样就能满足用户 “按关键字 + 标签 + 日期 + …” 多种组合搜索需求,大幅提升查询效率和使用体验。

云图库项目的后端中,你如何实现以图搜图功能?

我在云图库项目中采用了 实时爬虫 的方式实现以图搜图。流程如下:

  1. 通过 F12 网络控制台分析百度以图搜图的相关接口
  2. 调用百度以图搜图接口,将图片 URL 传给百度,以获得一个 “搜图页面地址”
  3. 利用 Jsoup 解析返回的 HTML,提取到搜索结果列表的接口地址
  4. 通过 Hutool 的 HttpRequest 调用该接口获取到相似图片、来源链接等信息,封装为一个后端接口返回给前端。

在实现层面,我为这些步骤(获取页面地址、解析 HTML、拉取图片列表)各自写了一个独立的 API 类,然后用 门面模式 将它们统一封装在 ImageSearchApiFacade 类中,对外只暴露一个 searchImage 方法,简化了调用流程,用户只要传入图片 URL 就能得到以图搜图的结果。

云图库项目的后端中,你如何实现颜色搜图功能?

整体思路是:先提取和存储每张图片的主色调,再用欧氏距离算法来判断颜色相似度。

详细流程:

  1. 提取主色调:上传图片后,我利用数据万象服务自动分析图片的主色调,然后将提取到的十六进制色值(如 0xAFB123)保存在数据库的 picColor 字段中。
  2. 用户发起颜色检索:输入一个十六进制色值(如 #FF0000),后端用 Color 类将其转换为 RGB。
  3. 计算相似度:从数据库中查询出每张图的主色调,同样转换为 RGB 后计算二者的欧氏距离 distance = sqrt((R1-R2)^2 + (G1-G2)^2 + (B1-B2)^2),距离越小表示越相似。
  4. 对结果进行排序,取相似度最高的前 N 张图并返回给前端

这样,前端用户只要操作一个颜色选择器,就能在空间内找出和指定颜色最接近的图片,大大提高搜图效率。

云图库项目的后端中,你如何实现批量编辑功能?怎么优化批量编辑的性能?

为了提高空间图片的管理效率,我提供了批量编辑功能,包括批量修改图片的分类、标签、名称等,能安全快速地完成大量图片的更新操作。

实现过程主要分两步:

  1. 在 Service 中,先一次性查询出要修改的图片并检查权限,然后按需更新分类、标签、名称等字段。
  2. 使用 MyBatis Plus 的 updateBatchById 批量更新记录,结合事务保证原子性。

通过下面几个方法,可以优化批量编辑的性能:

  • 减少循环 SQL:统一分批、批量更新数据库,而不是给每张图都执行一条 Update。
  • 并发执行:如果数据量特别大,可以用 CompletableFuture + 线程池将不同分段的图片并发处理,并在全部处理完后再统一提交或回滚。

云图库项目的后端中,你如何实现 AI 扩图功能?使用 AI 服务时有哪些注意事项?

我在云图库项目中采用了阿里云百炼的大模型服务来实现 AI 扩图功能,流程如下:

1)选择 AI 大模型:我调研了很多国内外的 AI 绘画大模型,发现阿里云百炼提供图像扩展 API,可以通过 HTTP 接入并且响应较快,还提供了一定免费额度,所以选择它。

2)异步调用:该 AI 接口需要先创建任务,然后轮询查看任务状态,又分为 2 个步骤:

  1. 后端调用 AI 的 “创建扩图任务” API,传入原图 URL 及一些扩展参数(如左右、上下加多少像素),得到一个 taskId 。
  2. 前端轮询后端接口,后端再调用 AI “查询任务” 的 API 来判断任务是否完成;如果成功,则返回生成好的图片链接,如果失败则提示用户。

使用 AI 服务的注意事项:

  1. 成本控制:绘图大模型通常按调用量或 GPU 耗时计费,要在使用前就预估好成本,并且通过记录次数或费用,整体观测成本消耗情况。
  2. 异步调用:大模型绘画任务往往耗时数秒到数十秒,同步等待会堵塞线程、影响并发性能,因此必须采用异步任务 + 前端轮询或后台轮询的方式。
  3. 超时控制:一旦任务执行很久还没完成,需要及时停止轮询,避免资源浪费。
  4. 参数校验:调用 AI 接口前先检查图片大小、格式、空间容量等,减少无意义的请求。
  5. 安全性:AI 接口成本高,必须加限流(如每分钟 N 次)和权限校验,防止恶意刷任务;对异常或失败任务也要做好记录与告警,保证系统稳定。

云图库项目中,你开发了哪些分析能力?后端如何实现空间分析功能?

在云图库项目中,我针对空间和公共图库的图片数据,开发了多种分析能力,包括空间资源使用分析、图片分类与标签分布、图片大小分布统计、用户上传行为分析,以及管理员可用的全局空间排行分析等。

对于分析类需求,开发流程都是类似的:

  1. 数据采集:从数据源(比如 MySQL 数据库或者大数据仓库)获取原始数据。要提前明确涉及的表和字段,必要时采用分页查询处理大数据量。
  2. 数据预处理:对数据进行清洗、加工和格式化,包括过滤无效数据(比如逻辑删除或审核未通过)、解析复杂字段(比如 JSON 格式的 tags),以及通过字段关联补充上下文信息。
  3. 数据计算:根据需求进行分组、聚合、排序等,从而计算关键指标,比如计算空间各分类图片的占用比例、用户上传图片的时间趋势。可以根据场景调整计算方案,比如对于大数据量的计算,可以采用 Spark 之类的大数据计算组件做离线计算;对于数据实时性要求较高的实时分析场景,可以用 Flink 做流式处理。
  4. 数据存储(可选):针对频繁查询的分析结果,可将结果数据存储为单独的表或缓存,减少重复计算,提高查询效率。
  5. 数据接口设计:为前端提供统一接口,从而支持查询和展示。需要考虑到数据量较大导致前端渲染卡顿的情况,可以按需精简返回的字符串、分页查询等。
  6. 数据可视化:通过图表直观展示分析结果,前端可以使用 Apache EChartsopen in new window 等可视化库渲染。当然也可以让后端生成图表图片并返回,但这种实现方法的灵活度有限。

通过这些分析能力,用户可以清晰掌握自己空间的使用状况和图片分布,管理员也能整体观察系统资源利用率,并做好限额管控和数据运营。如果数据量大,还可进一步用 Redis / 定时任务等手段做缓存或离线计算,提升统计性能与响应速度。

云图库项目的后端中,你如何实现图片的协同编辑功能?

我在已有的图片编辑功能上,结合 WebSocket事件驱动 思想,让多位团队成员能够实时查看对同一张图片的编辑变化。关键的实现点是:

  1. WebSocket 通信:前端与后端在建立 WebSocket 连接后,后端保存每个图片对应的会话集合,以及当前正在编辑的用户信息。
  2. 编辑锁机制:只有一个用户可以进入编辑状态,其他用户只能实时 “围观” 该用户操作,这样从源头上解决了并发冲突。
  3. 事件驱动:每当用户执行放大 / 旋转等编辑动作,相当于生产了一个 “事件”,通过 WebSocket 服务器把该事件分发给其他连接用户,实时广播更新。
  4. 断开连接:若正在编辑用户断线或退出,会自动释放编辑锁,其他用户可申请进入编辑状态。

什么是 WebSocket?为什么在云图库项目中选用它而不是 HTTP 实现协同编辑?

WebSocket 是一种 全双工(双向)通信协议。和传统 “请求-响应” 的 HTTP 不同,WebSocket 在初次握手后会保留一个持久连接,客户端和服务器可彼此 随时主动 发送消息,而无需频繁重建连接。

在协同编辑场景中,需要 高频双向 的消息传输 —— 编辑者的操作需要立刻同步给其他用户。如果用 HTTP 就得不断轮询或发起请求,浪费带宽、且延迟高;而使用 WebSocket 保持长连接,可以低延迟地推送彼此的编辑信息,满足实时协同需求。

什么是事件驱动设计?你在云图库项目中是如何运用它实现协同编辑功能的?

事件驱动设计通过将系统内的操作抽象成 “事件”,当事件发生时,把事件交给异步处理器或消息总线,然后通知其他需要接收的组件或用户,从而 解耦 生产者与消费者,并提高并发性能。

在我的协同编辑实现中,每次用户的编辑动作都被视作一个事件:

  1. WebSocket 接收前端事件后,触发相应的处理器
  2. 处理器中将消息再广播给所有正在编辑此图片的客户端
  3. 其他用户收到此事件后即可同步更新编辑状态和操作

云图库项目的后端中,WebSocket 的握手拦截器和编辑锁机制分别起到什么作用?

1)WebSocket 握手拦截器:在真正建立 WebSocket 长连接前,会进行一次 HTTP Upgrade 请求。我在握手拦截器中校验用户是否已登录、有无团队空间的编辑权限,然后把用户、图片 ID 等信息放到 Session 属性里,这样就能在后续通信中直接复用这些会话属性;如果不符合条件则拒绝握手。

2)编辑锁机制:同一时刻只有一个用户能 “进入编辑” 该图片,其余用户只能接收消息并实时浏览效果,但不能操作。这样可以从源头避免并发冲突,不需要维护复杂的实时合并算法。当持锁用户退出或断连时自动释放锁,其他人才能进入编辑状态。

什么是 Disruptor?在云图库项目中为什么要使用它?又是如何使用它的?

Disruptor 是 LMAX 公司开源的一个 高性能无锁环形队列 框架,常用于高并发、低延迟的消息处理场景。它通过环形缓冲区 + 无锁(CAS + 内存屏障)减少线程切换,来显著提升吞吐量。

在协同编辑中,后端 WebSocket 原本同步接收和处理消息,若并发用户多、单条消息处理耗时长,就易造成阻塞,无法处理更多请求。引入 Disruptor 后,将消息生产与消息处理解耦:

  1. 原本的处理消息逻辑修改为 “仅把消息提交到 Disruptor 队列”
  2. 由 Disruptor 的消费者线程异步取出并执行具体业务逻辑

这能保持 WebSocket 主线程轻量快速,不易被阻塞,也能提高实时响应能力。

我在项目中使用 Disruptor 的步骤:

  1. 引入 Disruptor 依赖
  2. 定义事件,承载编辑请求、WebSocket Session、用户信息等
  3. 定义事件处理器,用于消费编辑事件并调用相应的业务逻辑
  4. 在启动时初始化 Disruptor,初始化固定大小的环形队列,并把事件处理器加入消费者池
  5. 在 WebSocket 收到消息后,把它发布到 Disruptor 的环形队列
  6. Disruptor 内部会多线程异步执行这些事件

什么是优雅停机?你在云图库项目中怎么利用 Disruptor 实现优雅停机?

优雅停机指在应用关闭前,不再接收新的请求等待系统中正在进行的任务全部完成后,才真正停止进程。这样可以确保数据或状态不会在停机时刻中断或丢失,避免产生乱序或资源泄露等问题。

Disruptor 本身提供了优雅停机方法。我利用 Bean 的 PreDestroy 注解,在应用关闭前,先调用 disruptor.shutdown(),然后 Disruptor 本身会等待环形队列内的所有事件处理完才返回,同时拒绝新的编辑操作或网络请求。待队列任务都消费完成,再关闭线程池和资源连接,最后退出应用。