聊聊PowerJob的AliOssService
序
本文主要研究一下PowerJob的AliOssService
DFsService
tech/powerjob/server/extension/dfs/DFsService.java
public interface DFsService {/*** 存储文件* @param storeRequest 存储请求* @throws IOException 异常*/void store(StoreRequest storeRequest) throws IOException;/*** 下载文件* @param downloadRequest 文件下载请求* @throws IOException 异常*/void download(DownloadRequest downloadRequest) throws IOException;/*** 获取文件元信息* @param fileLocation 文件位置* @return 存在则返回文件元信息* @throws IOException 异常*/Optional<FileMeta> fetchFileMeta(FileLocation fileLocation) throws IOException;/*** 清理 powerjob 认为“过期”的文件* 部分存储系统自带生命周期管理(如阿里云OSS,则不需要单独实现该方法)* @param bucket bucket* @param days 天数,需要清理超过 X 天的文件*/default void cleanExpiredFiles(String bucket, int days) {}
}
DFsService接口定义了store、download、fetchFileMeta、cleanExpiredFiles方法
AbstractDFsService
tech/powerjob/server/persistence/storage/AbstractDFsService.java
@Slf4j
public abstract class AbstractDFsService implements DFsService, ApplicationContextAware, DisposableBean {protected ApplicationContext applicationContext;public AbstractDFsService() {log.info("[DFsService] invoke [{}]'s constructor", this.getClass().getName());}abstract protected void init(ApplicationContext applicationContext);protected static final String PROPERTY_KEY = "oms.storage.dfs";protected static String fetchProperty(Environment environment, String dfsType, String key) {String pKey = String.format("%s.%s.%s", PROPERTY_KEY, dfsType, key);return environment.getProperty(pKey);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;log.info("[DFsService] invoke [{}]'s setApplicationContext", this.getClass().getName());init(applicationContext);}
}
AbstractDFsService声明实现DFsService、ApplicationContextAware、DisposableBean接口,它在setApplicationContext方法执行了init
AliOssService
tech/powerjob/server/persistence/storage/impl/AliOssService.java
@Slf4j
@Priority(value = Integer.MAX_VALUE - 1)
@Conditional(AliOssService.AliOssCondition.class)
public class AliOssService extends AbstractDFsService {private static final String TYPE_ALI_OSS = "alioss";private static final String KEY_ENDPOINT = "endpoint";private static final String KEY_BUCKET = "bucket";private static final String KEY_CREDENTIAL_TYPE = "credential_type";private static final String KEY_AK = "ak";private static final String KEY_SK = "sk";private static final String KEY_TOKEN = "token";private OSS oss;private String bucket;private static final int DOWNLOAD_PART_SIZE = 10240;private static final String NO_SUCH_KEY = "NoSuchKey";//......void initOssClient(String endpoint, String bucket, String mode, String ak, String sk, String token) throws Exception {log.info("[AliOssService] init OSS by config: endpoint={},bucket={},credentialType={},ak={},sk={},token={}", endpoint, bucket, mode, ak, sk, token);if (StringUtils.isEmpty(bucket)) {throw new IllegalArgumentException("'oms.storage.dfs.alioss.bucket' can't be empty, please creat a bucket in aliyun oss console then config it to powerjob");}this.bucket = bucket;CredentialsProvider credentialsProvider;CredentialType credentialType = CredentialType.parse(mode);switch (credentialType) {case PWD:credentialsProvider = new DefaultCredentialProvider(ak, sk, token);break;case SYSTEM_PROPERTY:credentialsProvider = CredentialsProviderFactory.newSystemPropertiesCredentialsProvider();break;default:credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();}this.oss = new OSSClientBuilder().build(endpoint, credentialsProvider);log.info("[AliOssService] initialize successfully, THIS_WILL_BE_THE_STORAGE_LAYER.");}//......
}
AliOssService继承了AbstractDFsService
store
@Overridepublic void store(StoreRequest storeRequest) throws IOException {ObjectMetadata objectMetadata = new ObjectMetadata();PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, parseFileName(storeRequest.getFileLocation()), storeRequest.getLocalFile(), objectMetadata);oss.putObject(putObjectRequest);}
store方法创建PutObjectRequest,使用oss.putObject进行上传
download
@Overridepublic void download(DownloadRequest downloadRequest) throws IOException {FileLocation dfl = downloadRequest.getFileLocation();DownloadFileRequest downloadFileRequest = new DownloadFileRequest(bucket, parseFileName(dfl), downloadRequest.getTarget().getAbsolutePath(), DOWNLOAD_PART_SIZE);try {FileUtils.forceMkdirParent(downloadRequest.getTarget());oss.downloadFile(downloadFileRequest);} catch (Throwable t) {ExceptionUtils.rethrow(t);}}
download方法则根据DownloadRequest指定的FileLocation创建DownloadFileRequest,然后通过oss.downloadFile(downloadFileRequest)进行下载
fetchFileMeta
@Overridepublic Optional<FileMeta> fetchFileMeta(FileLocation fileLocation) throws IOException {try {ObjectMetadata objectMetadata = oss.getObjectMetadata(bucket, parseFileName(fileLocation));return Optional.ofNullable(objectMetadata).map(ossM -> {Map<String, Object> metaInfo = Maps.newHashMap();metaInfo.putAll(ossM.getRawMetadata());if (ossM.getUserMetadata() != null) {metaInfo.putAll(ossM.getUserMetadata());}return new FileMeta().setLastModifiedTime(ossM.getLastModified()).setLength(ossM.getContentLength()).setMetaInfo(metaInfo);});} catch (OSSException oe) {String errorCode = oe.getErrorCode();if (NO_SUCH_KEY.equalsIgnoreCase(errorCode)) {return Optional.empty();}ExceptionUtils.rethrow(oe);}return Optional.empty();}
fetchFileMeta方法通过oss.getObjectMetadata获取ObjectMetadata
cleanExpiredFiles
@Overridepublic void cleanExpiredFiles(String bucket, int days) {/*阿里云 OSS 自带生命周期管理,请参考文档进行配置,代码层面不进行实现(浪费服务器资源)https://help.aliyun.com/zh/oss/user-guide/overview-54阿里云 OSS 自带生命周期管理,请参考文档进行配置,代码层面不进行实现(浪费服务器资源)https://help.aliyun.com/zh/oss/user-guide/overview-54阿里云 OSS 自带生命周期管理,请参考文档进行配置,代码层面不进行实现(浪费服务器资源)https://help.aliyun.com/zh/oss/user-guide/overview-54*/}
cleanExpiredFiles则是空操作
init
protected void init(ApplicationContext applicationContext) {Environment environment = applicationContext.getEnvironment();String endpoint = fetchProperty(environment, TYPE_ALI_OSS, KEY_ENDPOINT);String bkt = fetchProperty(environment, TYPE_ALI_OSS, KEY_BUCKET);String ct = fetchProperty(environment, TYPE_ALI_OSS, KEY_CREDENTIAL_TYPE);String ak = fetchProperty(environment, TYPE_ALI_OSS, KEY_AK);String sk = fetchProperty(environment, TYPE_ALI_OSS, KEY_SK);String token = fetchProperty(environment, TYPE_ALI_OSS, KEY_TOKEN);try {initOssClient(endpoint, bkt, ct, ak, sk, token);} catch (Exception e) {ExceptionUtils.rethrow(e);}}
init则是通过environment获取相关属性,然后执行initOssClient
小结
DFsService接口定义了store、download、fetchFileMeta、cleanExpiredFiles方法;AbstractDFsService声明实现DFsService、ApplicationContextAware、DisposableBean接口,它在setApplicationContext方法执行了init;AliOssService继承了AbstractDFsService,通过ossClient实现了store、download、fetchFileMeta方法。
相关文章:
聊聊PowerJob的AliOssService
序 本文主要研究一下PowerJob的AliOssService DFsService tech/powerjob/server/extension/dfs/DFsService.java public interface DFsService {/*** 存储文件* param storeRequest 存储请求* throws IOException 异常*/void store(StoreRequest storeRequest) throws IOEx…...
【VRTK】【Unity】【PICO】PICO项目打包后闪退的根本原因
【背景】 一开始打包运行好好的PICO项目,中途用Preview模式开发了一阵后,再次打包就闪退了。 【分析】 项目设置没有动过,那么可能是Preview开发过程中引入的包导致的问题。 【答案】 千万不要在PICO项目中导入Oculus包。我原本想用一些…...
《PCI Express体系结构导读》随记 —— 第I篇 第2章 PCI总线的桥与配置(21)
接前一篇文章:《PCI Express体系结构导读》随记 —— 第I篇 第2章 PCI总线的桥与配置(20) 2.4 PCI总线的配置 PCI总线定义了两类配置请求,一个是Type 00h配置请求,另一个是Type 01h配置请求。PCI总线使用这些配置请求…...
大数据前馈神经网络解密:深入理解人工智能的基石
文章目录 大数据前馈神经网络解密:深入理解人工智能的基石一、前馈神经网络概述什么是前馈神经网络前馈神经网络的工作原理应用场景及优缺点 二、前馈神经网络的基本结构输入层、隐藏层和输出层激活函数的选择与作用网络权重和偏置 三、前馈神经网络的训练方法损失函…...
【新书推荐】Web3.0应用开发实战(从Web 2.0到Web 3.0)
第一部分 Flask简介 第1章 安装 1.1 创建应用目录 1.2 虚拟环境 1.2.1 创建虚拟环境 1.2.2 使用虚拟环境 1.3 使用pip安装Python包 1.4 使用pipregs输出包 1.5 使用requirements.txt 1.6 使用pipenv管理包 第2章 应用的基本结构 2.1 网页显示过程 2.2 初始化 2.3 路由和视图函数…...
vue3中状态管理库pinia的安装和使用方法介绍及和vuex的区别
文章目录 Pinia 的主要特点:如何使用:1.安装2.定义3.使用 pinia和vuex的对比 Pinia 与 Vuex 一样,是作为 Vue 的“状态存储库”,用来实现 跨页面/组件 形式的数据状态共享。它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的…...
领略指针之妙
𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - :来于“云”的“羽球人”。…...
迭代器模式介绍
目录 一、迭代器模式介绍 1.1 迭代器模式定义 1.2 迭代器模式原理 1.2.1 迭代器模式类图 1.2.2 模式角色说明 1.2.3 示例代码 二、迭代模式的应用 2.1 需求说明 2.2 需求实现 2.2.1 抽象迭代类 2.2.2 抽象集合类 2.2.3 主题类 2.2.4 具体迭代类 2.2.5 具体集合类 …...
算法每日一题: 最大字符串匹配数目 | 哈希 | 哈希表 | 题意分析
hello 大家好,我是星恒 今天给大家带来的是hash,思路有好几种,需要注意的是这中简单的题目需要仔细看条件,往往他们有对应题目的特殊的解法 题目:leetcode 2744给你一个下标从 0 开始的数组 words ,数组中包…...
自然语言处理(Natural Language Processing,NLP)解密
专栏集锦,大佬们可以收藏以备不时之需: Spring Cloud 专栏:http://t.csdnimg.cn/WDmJ9 Python 专栏:http://t.csdnimg.cn/hMwPR Redis 专栏:http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏:http://t.csdni…...
【DevOps-08-5】目标服务器准备脚本,并基于Harbor的最终部署
一、简要描述 告知目标服务器拉取哪个镜像判断当前服务器是否正在运行容器,停止并删除如果目标服务器已经存在当前镜像,删除当前版本的镜像目标服务器拉取Harbor上的镜像将拉取下来的镜像运行成容器二、准备目标服务器脚本文件 1、在部署的目标服务器准备deploy.sh部署脚本 …...
用Java实现01背包问题 用贪心算法
贪心算法不是解决01背包问题的有效方法,因为贪心算法只能保证得到一个近似最优解,而无法保证得到最优解。因此,我们需要使用动态规划来解决01背包问题。以下是使用Java实现的动态规划解法: public class KnapsackProblem {public…...
JUC并发编程-8锁现象
5. 8锁现象 如何判断锁的是谁!锁到底锁的是谁? 锁会锁住:对象、Class 深刻理解我们的锁 问题1 两个同步方法,先执行发短信还是打电话 public class dome01 {public static void main(String[] args) {Phone phone new Phon…...
集美大学“第15届蓝桥杯大赛(软件类)“校内选拔赛 D矩阵选数
经典的状态压缩DP int dp[15][(1<<14)10]; int a[15][15]; void solve() {//dp[i][st]考虑到了第i行 并且当前考虑完第i行以后的选择状态是st的所有方案中的最大值for(int i1;i<13;i)for(int j1;j<13;j)cin>>a[i][j];for(int i1;i<13;i){for(int j0;j<…...
Android System Service系统服务--1
因为工作中经常需要解决一些framework层的问题,而framework层功能一般都是system service 的代理stub,然后封装相关接口,并提供给APP层使用,system service则在不同的进程中运行,这样实现了分层,隔离&#…...
【RT-DETR有效改进】华为 | Ghostnetv1一种专为移动端设计的特征提取网络
前言 大家好,这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进,内容持续更新,每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本,同时修改内容也支持ResNet32、ResNet101和PP…...
45个经典Linux面试题!赶紧收藏!
问题一: 绝对路径用什么符号表示?当前目录、上层目录用什么表示?主目录用什么表示? 切换目录用什么命令? 答案:绝对路径:如/etc/init.d当前目录和上层目录:./ …/主目录:~/切换目…...
将字符串中可能被视为正则表达式的特殊字符进行转义re.escape()
【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将字符串中可能被视为 正则表达式的特殊字符 进行转义 re.escape() [太阳]选择题 请问以下代码最后输出的结果是? import re s [a-z] print("【显示】s ",s) print(&q…...
C语言:函数指针的使用
在C语言中,函数指针是指向函数的指针变量。它可以存储函数的地址,使得可以通过该指针来调用函数。以下是函数指针的基本概念和用法: 一、基本概念: 声明函数指针: returnType (*pointerName)(parameterTypes); 这里 r…...
「实战应用」如何用DHTMLX Gantt构建类似JIRA式的项目路线图(二)
DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求,是最完善的甘特图图表库。 在web项目中使用DHTMLX Gantt时,开发人员经常需要满足与UI外观相关的各种需求。因此他们必须确定JavaScript甘特图库的…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
