项目实践缓存预热方案之CommandLineRunner和ApplicationRunner

本文主要是介绍项目实践缓存预热方案之CommandLineRunner和ApplicationRunner,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

众所周知,在项目的开发中,合理使用缓存是提高服务性能的一大利器,本篇文章就来介绍一下我所在项目中如何使用缓存的一个案例。

背景

我们的项目是由多个微服务所组成,业务是保险,我所负责的模块是出单,在压测的过程中,发现当所有服务启动好之后,第一次出单的时间存在耗时较长的情况,通过sleuth分析了一下各个服务之间的调用链,针对第一单,发现出单接口中存在调用其他接口做查询和逻辑处理,在第一次调用后会将结果缓存,那么以后的调用基本是直接走缓存,不会去和数据库交互,减少了数据库创建和关闭连接之类的耗时。此时,我发现针对首单慢的问题,主要是因为一些接口返回固定的值,第一次没有通过缓存获取而导致的耗时较长的问题。

解决方案

为了解决首单耗时较长的问题,我采用了缓存预热的方案,那就是在服务启动的时候进行缓存预热,这样首单中一些接口的调用也是会通过缓存来取值,肯定是可以减少耗时,提高接口的性能,缩短出单的时间。

缓存预热

  • 不是所有的接口都需要进行缓存预热,应该按照自己的业务所需对缓存预热谨慎使用
  • 对缓存预热应该是同步还是异步进行,这个需要考虑
    • 缓存预热同步,那么服务启动好之后缓存预热也结束了,正常的业务就可以开始进行
    • 缓存预热异步,服务虽然启动好了,但是缓存预热可能还在进行中,是否会影响到自己的业务需要考虑一下
    • 相对比较而言,同步预热会拉长服务的启动时间,异步预热不会拉长服务的启动时间
项目实践

具体的相关代码如下所示:

package com.xxx.xxx.xx.xxx.service.inner.impl;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import java.util.List;import static java.util.stream.Collectors.toList;/*** xxx 服务启动时 加载缓存  缓存项为vvv的内容* @author xxx*/
@Order(4)
@Component
@Slf4j
public class InitMarketCacheService implements CommandLineRunner {@Value("#{'${zz.xx.goodsId}'.split(',')}")private List<String> aaaArray;@Value("#{'${zz.xx.planId}'.split(',')}")private List<String>  bbbArray;@Value("#{'${zz.xx.productId}'.split(',')}")private List<String>  cccArray;@Autowiredprivate AxxService axxShareService;@Autowiredprivate BxxShareService bxxShareService;@Overridepublic void run(String... args) throws Exception {List<Long> goodsIdList = goodsIdArray.stream().map(Long::valueOf).collect(toList());List<Long> goodsPlanIdList = planIdArray.stream().map(Long::valueOf).collect(toList());List<Long> productIdList = productIdArray.stream().map(Long::valueOf).collect(toList());log.warn("begin init xxservice cache");try {for (Long goodsId:goodsIdList){AxxService.queryGoods(goodsId);}for (Long planId:goodsPlanIdList){AxxService.queryPlanAndPackage(planId);}for (Long productId:productIdList){BxxShareService.detail(productId);}}catch (Exception e){log.error("cache warm up failed",e);}finally {log.warn("end init xxx service cache");}}
}
相关知识点说明

CommandLineRunner

源码如下:

package org.springframework.boot;import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;public interface CommandLineRunner {void run(String... args) throws Exception;
}

ApplicationRunner

package org.springframework.boot;import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;public interface ApplicationRunner {void run(ApplicationArguments args) throws Exception;
}

CommandLineRunnerApplicationRunner

  • 区别:
    • CommandLineRunnerrun方法的参数是一个可变参数列表
    • ApplicationRunnerrun方法的参数是一个ApplicationArguments类型的参数
  • 共同点:
    • 都是一个接口interface
    • 里面都有一个run()方法,返回值为void
    • 所有实现这两个接口的Beanspring boot启动后会自动调用
    • 可以定义多个Bean实现接口,但是调用的顺序可以使用@Order注解来指定,其中value属性的值越小,则会优先被调用
注意点

实现这两个接口的类,在执行run方法的时候默认是通过主线程的,如果在服务调用的时候,某个服务异常,那么该服务就会启动不起来,为了不影响服务的正常启动,我们可以采用try...catch的方法对执行run时的异常进行捕获,这样就不会影响服务的正常启动。

在这里插入图片描述

这篇关于项目实践缓存预热方案之CommandLineRunner和ApplicationRunner的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095600

相关文章

虚拟机Centos7安装MySQL数据库实践

《虚拟机Centos7安装MySQL数据库实践》用户分享在虚拟机安装MySQL的全过程及常见问题解决方案,包括处理GPG密钥、修改密码策略、配置远程访问权限及防火墙设置,最终通过关闭防火墙和停止Net... 目录安装mysql数据库下载wget命令下载MySQL安装包安装MySQL安装MySQL服务安装完成

SpringBoot整合(ES)ElasticSearch7.8实践

《SpringBoot整合(ES)ElasticSearch7.8实践》本文详细介绍了SpringBoot整合ElasticSearch7.8的教程,涵盖依赖添加、客户端初始化、索引创建与获取、批量插... 目录SpringBoot整合ElasticSearch7.8添加依赖初始化创建SpringBoot项

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

SpringBoot3.X 整合 MinIO 存储原生方案

《SpringBoot3.X整合MinIO存储原生方案》本文详细介绍了SpringBoot3.X整合MinIO的原生方案,从环境搭建到核心功能实现,涵盖了文件上传、下载、删除等常用操作,并补充了... 目录SpringBoot3.X整合MinIO存储原生方案:从环境搭建到实战开发一、前言:为什么选择MinI

全面掌握 SQL 中的 DATEDIFF函数及用法最佳实践

《全面掌握SQL中的DATEDIFF函数及用法最佳实践》本文解析DATEDIFF在不同数据库中的差异,强调其边界计算原理,探讨应用场景及陷阱,推荐根据需求选择TIMESTAMPDIFF或inte... 目录1. 核心概念:DATEDIFF 究竟在计算什么?2. 主流数据库中的 DATEDIFF 实现2.1

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依