分布式调度方案:Elastic-Job
文章目录
- 一、什么是分布式调度
- 二、Elastic-Job 介绍
- 三、Elastic-Job 实战
- 3.1 环境搭建
- 3.1.1 本地部署
- 3.1.2 服务器部署
- 3.1.3 Zookeeper 管控台界面
- 3.2 入门案例
- 3.3 SpringBoot 集成 Elastic-Job
- 3.4 任务分片(★)
- 3.5 Dataflow 类型调度任务
一、什么是分布式调度
什么是任务调度?
我们可以思考一下下面业务场景的解决方案:
① 某电商平台需要每天上午10点,下午3点,晚上8点发放一批优惠券
② 某银行系统需要在信用卡到期还款日的前三天进行短信提醒
③ 某财务系统需要在每天凌晨0:10分结算前一天的财务数据,统计汇总
以上场景就是任务调度所需要解决的问题。
任务调度是为了自动完成特定任务,在约定的特定时刻去执行任务的过程
以上的场景可以使用定时任务注解 @Scheduled 贴在业务方法上,并在启动类上贴上 @EnableScheduling 注解,以实现任务调度。
@Scheduled(cron = "0/20 * * * * ? ")
public void doWork(){//doSomething
}
什么是分布式调度?
感觉 Spring 给我们提供的这个注解可以完成任务调度的功能,为什么还需要分布式呢?主要有如下这几点原因:
- 单机处理极限:原本 1 分钟内需要处理 1 万个订单,但是现在需要 1 分钟内处理 10 万个订单;原来一个统计需要1小时,现在业务方需要10分钟就统计出来。你也许会说,你也可以多线程、单机多进程处理。的确,多线程并行处理可以提高单位时间的处理效率,但是单机能力毕竟有限(主要是CPU、内存和磁盘),始终会有单机处理不过来的情况。
- 高可用:单机版的定式任务调度只能在一台机器上运行,如果程序或者系统出现异常就会导致功能不可用。虽然可以在单机程序实现的足够稳定,但始终有机会遇到非程序引起的故障,而这个对于一个系统的核心功能来说是不可接受的。
- 防止重复执行:在单机模式下,定时任务是没什么问题的。但当我们部署了多台服务,同时又每台服务又有定时任务时,若不进行合理的控制在同一时间,只有一个定时任务启动执行,这时,定时执行可能存在执复、混乱和错误的情况了。
这个时候就需要分布式的任务调度来实现了。
二、Elastic-Job 介绍
Elastic-Job 是一个分布式调度的解决方案,它由两个相互独立的子项目 Elastic-job-Lite 和 Elastic-Job-Cloud 组成,使用 Elastic-Job 可以快速实现分布式任务调度。
官方地址:https://shardingsphere.apache.org/elasticjob/
功能列表:
- 分布式调度协调:在分布式环境中,任务能够按照指定的调度策略执行,并且能够避免同一任务多实例重复执行。
- 丰富的调度策略:基于成熟的定时任务作业框架 Quartz cron 表达式执行定时任务。
- 弹性拓容缩容:当集群中增加一个实例,它应当能够被选举被执行任务;当集群减少一个实例时,他所执行的任务能被转移到别的示例中执行。
- 失效转移:某示例在任务执行失败后,会被转移到其他实例执行。
- 错过执行任务重触发:若因某种原因导致作业错过执行,自动记录错误执行的作业,并在下次作业完成后自动触发。
- 支持并行调度:支持任务分片,任务分片是指将一个任务分成多个小任务在多个实例同时执行。
- 作业分片一致性:当任务被分片后,保证同一分片在分布式环境中仅一个执行实例。
- 支持作业生命周期操作:可以动态对任务进行开启及停止操作,丰富的作业类型。
执行架构如下:

三、Elastic-Job 实战
3.1 环境搭建
zookeeper 可以理解为 elastic-job 的注册中心,分布式调度等功能由它实现,首先要下载资源。
csdn搜索资源: zookeeper-3.4.11.tar.gz
3.1.1 本地部署
将 zookeeper-3.4.11.tar.gz 解压,并将 conf 目录下 zoo_sample.cfg 拷贝一份命名成 zoo.cfg

其中 zookeeper 默认端口是 2181

切换到 bin 目录下,双击 zkServer.cmd,即可启动 zookeeper

3.1.2 服务器部署
step1:将 zookeeper-3.4.11.tar.gz上传到 /usr/local/software目录下
step2:解压文件到指定目录
tar -zxvf /usr/local/software/zookeeper-3.4.11.tar.gz -C /usr/local/
step3:拷贝配置文件
cp /usr/local/software/zookeeper-3.4.11/conf/zoo_sample.cfg /usr/local/software/zookeeper-3.4.11/conf/zoo.cfg
step4:启动
/usr/local/zookeeper-3.4.11/bin/zkServer.sh start
step5:检查进程是否开启,需要查看到QuorumPeerMain进程,如果存在则证明启动成功。
jps
zookeeper常用名称参考: linux下的zookeeper启动、停止 常用命令
注:如果启动显示 Starting zookeeper ... already running as process 7827. 但是 jps 中没有 QuorumPeerMain 进程。则需查看 zookeeper_server.pid 文件的位置并删除。
# 查看该文件位置
find / -name "zookeeper_server.pid"
# 跳转到该文件的位置,并删除
rm -rf zookeeper_server.pid
另外:服务器需要暂时关闭防火墙 systemctl stop firewalld,并可使用 firewall-cmd --state 查看防火墙状态。
具体可参考:Linux关闭防火墙命令
3.1.3 Zookeeper 管控台界面
搜索下载:zooInspector.zip
解压后进入 build 目录,运行 jar 包:java -jar zookeeper-dev-ZooInspector.jar

点击绿色按钮,输入连接的IP和端口号即可。

3.2 入门案例
版本要求:JDK 要求1.7 以上版本;Maven 要求 3.0.4 及以上版本;Zookeeper 要求 3.4.6 以上版本
1、引入 pom 依赖
<dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-core</artifactId><version>2.1.5</version>
</dependency>
2、调度任务类
public class MyElasticJob implements SimpleJob {@Overridepublic void execute(ShardingContext shardingContext) {System.out.println("执行任务:" + new Date());}
}
3、zookeeper 的配置类
启动类定义 JobScheduler 对象,里面传入两个对象:定时任务配置对象、注册中心配置,并调用 init() 方法完成初始化。
定时任务配置对象中要设置:任务名称、cron表达式和分片数量,并设置 任务对象的全路径类名。
注册中心配置对象中要设置:注册中心的地址、项目名以及节点的超时时间。
public class JobDemo {public static void main(String[] args) {new JobScheduler(createRegistryCenter(), createJobConfiguration()).init();}/*** Zookeeper注册中心配置** @return 注册中心配置对象*/private static CoordinatorRegistryCenter createRegistryCenter() {// ZookeeperConfiguration("zookeeper地址", "项目名")ZookeeperConfiguration configuration = new ZookeeperConfiguration("localhost:2181", "elastic-job");// 设置节点超时时间,即每隔一段时间查看当前节点是否下线configuration.setConnectionTimeoutMilliseconds(100);ZookeeperRegistryCenter center = new ZookeeperRegistryCenter(configuration);center.init();return center;}/*** 定时任务配置** @return 定时任务配置对象*/private static LiteJobConfiguration createJobConfiguration() {// 定义作业核心配置 newBuilder("任务名称", "corn表达式", "分片数量")JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder("myElasticJob", "0/10 * * * * ?", 1).build();// 定义simple类型配置,MyElasticJob.class.getCanonicalName() 是获取MyElasticJob的全限定类名(全路径类名)SimpleJobConfiguration configuration = new SimpleJobConfiguration(simpleCoreConfig, MyElasticJob.class.getCanonicalName());// 定义Lite作业根配置,并返回// 设置overwrite(true),允许覆盖cron表达式(默认不允许,会每5s执行一次)return LiteJobConfiguration.newBuilder(configuration).overwrite(true).build();}
}
注: .overwrite(true) 如果不设置,默认 5 秒执行一次。
4、运行main方法。当开启第二个实例的时候,第一个实例停止打印,当关闭第二个实例的时候,第一个实例又重新开始运行。

3.3 SpringBoot 集成 Elastic-Job
1、添加 pom 依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.axy</groupId><artifactId>elastic-job-boot</artifactId><packaging>jar</packaging><version>1.0-SNAPSHOT</version><name>elastic-job-boot</name><url>http://maven.apache.org</url><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-spring</artifactId><version>2.1.5</version></dependency>...</dependencies><build><finalName>elastic-job-boot</finalName></build>
</project>
2、因为配置中心的地址并不是固定的,所以我们应该把这个地址信息配置在配置文件中,所以在配置文件
application.yml 中添加配置如下:
zookeeper:url: localhost:2181groupName: elastic-job-boot
3、调度任务类交给 Spring 进行管理
@Component
public class MyElasticJob implements SimpleJob {@Overridepublic void execute(ShardingContext shardingContext) {System.out.println("定时调度:" + new Date());}
}
4、zookeeper 的配置类
elastic-job 集成 SpringBoot 以后,需要创建的不是 JobScheduler 对象,而是 SpringJobScheduler 对象,并交给 Spring 管理。其次,初始化该对象还需要传入需要分布式调度的任务对象当参数。
@Configuration
public class TestJobConfig {@Bean(initMethod = "init") // 创建bean后调用init方法public SpringJobScheduler testScheduler(MyElasticJob job, CoordinatorRegistryCenter registryCenter) {// 方法形参,自动会去spring的容器中寻找,首先会去看类型匹配,然后才会去看变量名,匹配方式和@Autowird一样LiteJobConfiguration configuration = createJobConfiguration(job.getClass(), "0/4 * * * * ?", 1);return new SpringJobScheduler(job, registryCenter, configuration);}@Beanpublic CoordinatorRegistryCenter registryCenter(@Value("${zookeeper.url}") String url,@Value("${zookeeper.groupName}") String groupName) {// ZookeeperConfiguration("zookeeper地址", "项目名")ZookeeperConfiguration configuration = new ZookeeperConfiguration(url, groupName);// 设置节点超时时间configuration.setConnectionTimeoutMilliseconds(100);ZookeeperRegistryCenter center = new ZookeeperRegistryCenter(configuration);center.init();return center;}/*** 定时任务配置* 这个定时任务使用的场景比较灵活,因此不建议放在spring的容器当中** @param clazz 定时任务的字节码* @param cron cron表达式* @param shardingCount 分片数量* @return 定时任务配置对象*/private static LiteJobConfiguration createJobConfiguration(Class clazz, String cron, int shardingCount) {// 定义作业核心配置 newBuilder("任务名称", "corn表达式", "分片数量")JobCoreConfiguration.Builder jobBuilder = JobCoreConfiguration.newBuilder(clazz.getSimpleName(), cron, shardingCount);JobCoreConfiguration simpleCoreConfig = jobBuilder.build();// 定义simple类型配置,MyElasticJob.class.getCanonicalName() 是获取MyElasticJob的全限定类名(全路径类名)System.out.println("MyElasticJob.class.getCanonicalName(): " + MyElasticJob.class.getCanonicalName());JobTypeConfiguration configuration;configuration = new SimpleJobConfiguration(simpleCoreConfig, clazz.getCanonicalName());// 定义Lite作业根配置,并返回// 设置overwrite(true),允许覆盖cron表达式(默认不允许)return LiteJobConfiguration.newBuilder(configuration).overwrite(true).build();}
}
5、启动项目

3.4 任务分片(★)
分片就是在就是在机器中分线程执行,分片的数量决定了最终分得线程的数量,将一个任务拆分为多个独立的任务项,然后由分布式的应用实例分别执行某一个或者几个分布项,下面以案例来逐步带入分片的概念。
现要处理下图表中数据的 backedUp 属性设置为 1。表一共有 20 条数据,根据 type 进行分类可以分成 text、image、radio 和 video 四类,那我们可以自定义任务分 4 片,分片索引分别为:0、1、2、3。
- 当只有一台机器的情况下,在机器 A 启动四个线程,分别处理四个分片的内容。
- 当有两台机器的情况下,机器 A 启动两个线程负责索引 0 1 的分片内容,机器 B 负责 2 3 的分片内容。
- 当有三台机器的情况下,机器 A 负责索引 0 1 的分片内容,机器 B 负责 2,机器 C 负责 3。
- 当有四台机器的情况下,机器 A 负责索引 0 的分片内容,机器 B 负责 1,机器 C 负责 2,机器 D 负责 3。

注:分片数建议等于机器个数的倍数。如:分片四个在两台机器上,那么就是每台机器分两个线程来执行任务。
如何实现上文的案例呢?这里我们忽略关于数据库层面的配置,主要的类与配置如下:
1、这里我们新建文件对象
@AllArgsConstructor
@NoArgsConstructor
@Data
public class FileCustom {// 唯⼀标识private Long id;//⽂件名private String name;//⽂件类型private String type;//⽂件内容private String content;// 是否已备份private Boolean backedUp = false;
}
2、这里我们先定义 zookeeper 的配置类
在初始化定时任务配置的时候,以字符串的形式传入分片参数,传入"0=text,1=image,2=radio,3=vedio",设置分片个数为 4,并添加分片功能 shardingItemParameters(...)。
- 如果 分片个数 小于 分片参数,则取参数中前几个。如:分片取 2,则只会对
0=text,1=image进行处理 - 如果 分片个数 大于 分片参数,则多出的参数补 null。如:分片取 5,则参数字符串会变为
0=text,1=image,2=radio,3=vedio,4=null
@Configuration
public class TestJobConfig {@Bean(initMethod = "init")public SpringJobScheduler fileScheduler(FileCustomElasticJob job, CoordinatorRegistryCenter registryCenter) {LiteJobConfiguration configuration = createJobConfiguration(job.getClass(), "0 0/1 * * * ?", 4, "0=text,1=image,2=radio,3=vedio");return new SpringJobScheduler(job, registryCenter, configuration);}@Beanpublic CoordinatorRegistryCenter registryCenter(@Value("${zookeeper.url}") String url, @Value("${zookeeper.groupName}") String groupName) {// ZookeeperConfiguration("zookeeper地址", "项目名")ZookeeperConfiguration configuration = new ZookeeperConfiguration(url, groupName);// 设置节点超时时间configuration.setConnectionTimeoutMilliseconds(100);ZookeeperRegistryCenter center = new ZookeeperRegistryCenter(configuration);center.init();return center;}/*** 定时任务配置* 这个定时任务使用的场景比较灵活,因此不建议放在spring的容器当中** @param clazz 定时任务的字节码* @param cron cron表达式* @param shardingCount 分片数量* @param shardingParam 分片参数* @return 定时任务配置对象*/private static LiteJobConfiguration createJobConfiguration(Class clazz, String cron, int shardingCount,String shardingParam) {// 定义作业核心配置 newBuilder("任务名称", "corn表达式", "分片数量")JobCoreConfiguration.Builder jobBuilder = JobCoreConfiguration.newBuilder(clazz.getSimpleName(), cron, shardingCount);if (!StringUtils.isEmpty(shardingParam)) {jobBuilder.shardingItemParameters(shardingParam); // 添加分片功能}JobCoreConfiguration simpleCoreConfig = jobBuilder.build();// 定义simple类型配置JobTypeConfiguration configuration;configuration = new SimpleJobConfiguration(simpleCoreConfig, clazz.getCanonicalName());// 定义Lite作业根配置,并返回// 设置overwrite(true),允许覆盖cron表达式(默认不允许)return LiteJobConfiguration.newBuilder(configuration).overwrite(true).build();}
}
3、文件对象的调度任务类
@Slf4j
@Component
public class FileCustomElasticJob implements SimpleJob {@Autowiredprivate FileCustomMapper fileCustomMapper;@Overridepublic void execute(ShardingContext shardingContext) {long threadId = Thread.currentThread().getId();System.out.printf("线程ID:{},任务的名称:{},任务参数:{},分片个数L:{},分片索引号:{},分片参数:{}\n",threadId,shardingContext.getJobName(),shardingContext.getJobParameter(),shardingContext.getShardingTotalCount(),shardingContext.getShardingItem(),shardingContext.getShardingParameter());doWorkByParameter(shardingContext.getShardingParameter());}/*** 根据类型查询出所有的备份任务** @param shardingParameter 线程对应处理的文件类型*/private void doWorkByParameter(String shardingParameter) {List<FileCustom> fileCustoms = fileCustomMapper.selectByType(shardingParameter);for (FileCustom fileCustom : fileCustoms) {backUp(fileCustom);}}/*** 模拟备份操作** @param fileCustom 备份对象*/private void backUp(FileCustom fileCustom) {System.out.println("备份的方法名:" + fileCustom.getName() + ",备份的类型:" + fileCustom.getType());System.out.println("==================================");try {TimeUnit.SECONDS.sleep(1); // 延时一秒} catch (InterruptedException e) {throw new RuntimeException(e);}fileCustomMapper.changeState(fileCustom.getId(), 1); // 修改数据的 backedUp}
}
4、这里我们模拟有两台机器,即两个实例。
从运行结果我们可以看出,机器 A 开启了两个线程来处理分片索引为 0 1 的分片内容,机器 B 开启了两个线程来处理分片索引为 2 3 的分片内容。


因此,通过对任务的合理分片化,可以达到任务并行处理的效果。分片的优点如下:
- 分片项与业务处理解耦:Elastic-ob并不直接提供数据处理的功能,框架只会将分片项分配至各个运行中的作业服务器,开发者需要自行处理分片项与真实数据的对应关系。
- 最大限度利用资源:将分片项设置大于服务器的数据,最好是大于服务器倍数的数量,作业将会合理利用分布式资源,动态的分配分片项。
3.5 Dataflow 类型调度任务
Dataflow 类型适用于要处理的数据量很大的情况,Dataflow 类型的定时任务需要实现 Datafowjob 接口,该接口提供 2 个方法供覆盖,分别用于抓取 fetchData 和处理 processData 数据,我们继续对例子进行改造。
Dataflow 类型用于处理数据流,他和 Simplejob 不同,它以数据流的方式执行,调用 fetchData 抓取数据,知道抓取不到数据才停止作业。
1、修改 zookeeper 配置类,增加数据类型判断和逻辑
@Configuration
public class TestJobConfig {@Bean(initMethod = "init")public SpringJobScheduler fileScheduler(FileDataFlowJob job, CoordinatorRegistryCenter registryCenter) {LiteJobConfiguration configuration = createJobConfiguration(job.getClass(), "0 0/1 * * * ?", 4, "0=text,1=image,2=radio,3=vedio", true);return new SpringJobScheduler(job, registryCenter, configuration);}@Beanpublic CoordinatorRegistryCenter registryCenter(@Value("${zookeeper.url}") String url, @Value("${zookeeper.groupName}") String groupName) {// ZookeeperConfiguration("zookeeper地址", "项目名")ZookeeperConfiguration configuration = new ZookeeperConfiguration(url, groupName);// 设置节点超时时间configuration.setConnectionTimeoutMilliseconds(100);ZookeeperRegistryCenter center = new ZookeeperRegistryCenter(configuration);center.init();return center;}/*** 定时任务配置* 这个定时任务使用的场景比较灵活,因此不建议放在spring的容器当中** @param clazz 定时任务的字节码* @param cron cron表达式* @param shardingCount 分片数量* @param shardingParam 分片参数* @param isDataFlow 是否是DataFlow类型* @return 定时任务配置对象*/private static LiteJobConfiguration createJobConfiguration(Class clazz, String cron, int shardingCount,String shardingParam, boolean isDataFlow) {// 定义作业核心配置 newBuilder("任务名称", "corn表达式", "分片数量")JobCoreConfiguration.Builder jobBuilder = JobCoreConfiguration.newBuilder(clazz.getSimpleName(), cron, shardingCount);if (!StringUtils.isEmpty(shardingParam)) {jobBuilder.shardingItemParameters(shardingParam); // 添加分片功能}JobCoreConfiguration simpleCoreConfig = jobBuilder.build();// 定义simple类型配置JobTypeConfiguration configuration;if (isDataFlow) {// true 代表流处理configuration = new DataflowJobConfiguration(simpleCoreConfig, clazz.getCanonicalName(), true);} else {configuration = new SimpleJobConfiguration(simpleCoreConfig, clazz.getCanonicalName());}// 定义Lite作业根配置,并返回// 设置overwrite(true),允许覆盖cron表达式(默认不允许)return LiteJobConfiguration.newBuilder(configuration).overwrite(true).build();}
}
2、定义新的 DataFlow 任务调度对象
@Component
public class FileDataFlowJob implements DataflowJob<FileCustom> {@Autowiredprivate FileCustomMapper fileCustomMapper;/*** 抓取数据** @param shardingContext* @return*/@Overridepublic List<FileCustom> fetchData(ShardingContext shardingContext) {// 取决于数据能否抓取到数据,有数据会继续调用该方法// 如果没数据就会停止,此次定时任务执行停止// 直到下次任务调度接着抓取System.out.println("开始抓取数据...");// select * from t_file_custom where backedUp = 0 and type = #{type} limit #{count}List<FileCustom> fileCustomList = fileCustomMapper.selectLimit(shardingContext.getShardingParameter(), 2); // 查找 backedUp=0 的前两条数据return fileCustomList; // 如果为null,则直接返回;如果不为null,则调用下方方法处理数据}/*** 处理数据** @param shardingContext* @param list*/@Overridepublic void processData(ShardingContext shardingContext, List<FileCustom> list) {for (FileCustom fileCustom : list) {backUp(fileCustom);}}/*** 模拟备份操作** @param fileCustom 备份对象*/private void backUp(FileCustom fileCustom) {System.out.println("备份的方法名:" + fileCustom.getName() + ",备份的类型:" + fileCustom.getType());System.out.println("==========================");try {TimeUnit.SECONDS.sleep(1); // 延时一秒} catch (InterruptedException e) {throw new RuntimeException(e);}fileCustomMapper.changeState(fileCustom.getId(), 1);}
}
3、启动项目发现,每次抓取两条数据,重复执行,有数据会继续调用该方法,如果没数据就会停止,此次定时任务执行停止。直至下次任务调度接着抓取。

文章参考:Java微服务商城高并发秒杀项目实战|Spring Cloud Alibaba真实项目实战+商城双11秒杀+高并发+消息+支付+分布式事物Seata
相关文章:
分布式调度方案:Elastic-Job
文章目录 一、什么是分布式调度二、Elastic-Job 介绍三、Elastic-Job 实战3.1 环境搭建3.1.1 本地部署3.1.2 服务器部署3.1.3 Zookeeper 管控台界面 3.2 入门案例3.3 SpringBoot 集成 Elastic-Job3.4 任务分片(★)3.5 Dataflow 类型调度任务 一、什么是分…...
网络安全工程师(白帽子)企业级学习路线
第一阶段:安全基础(入门) 第二阶段:Web渗透(初级网安工程师) 第三阶段:进阶部分(中级网络安全工程师)...
数据结构详细解释
数据结构 1. 线性数据结构 数组(Array) 定义:数组是一种固定大小的、元素类型相同的线性数据结构。元素在内存中是连续存储的,可以通过索引直接访问。 特点: 支持常数时间的随机访问(O(1))。…...
7.1图像平移
目录 实验原理 示例代码1 运行结果1 示例代码2 运行结果2 实验原理 OpenCV中,图像平移是一种基本的几何变换,指的是将图像中的每一个像素点沿着水平方向或垂直方向移动一定的距离。图像平移不改变图像…...
海外云手机是否适合运营TikTok?
随着科技的迅猛发展,海外云手机逐渐成为改变工作模式的重要工具。这种基于云端技术的虚拟手机,不仅提供了更加便捷、安全的使用体验,还在电商引流和海外社媒管理等领域展示了其巨大潜力。那么,海外云手机究竟能否有效用于运营TikT…...
IT 行业中常见的专业名称及其含义
API(Application Programming Interface) API 是应用程序编程接口,定义了不同软件系统之间如何互相通信的规则和方式。开发人员使用 API 将应用程序与外部服务集成,进行数据交换或调用外部功能。 IDE(Integrated Deve…...
全球开店,Shopee东南亚入驻指南|用友BIP电商通引领电商出海新潮流
在全球化的浪潮中,东南亚市场以其蓬勃的发展态势成为中国企业出海的首选之地。得益于其语言、物流、仓储、距离及政策的友好性,东南亚市场已成为企业海外拓展的必争之地。作为东南亚领先的电商平台,Shopee以其庞大的用户基础和高度的用户活跃…...
java当中什么是NIO
Java中的NIO(Non-blocking I/O)即非阻塞I/O,是Java 1.4中引入的一种新的I/O API,用于替代传统的I/O(即BIO, Blocking I/O)。与传统的阻塞式I/O相比,NIO提供了更高效的I/O操作,特别是…...
【基础】Three.js 自定义几何体和复制几何体
通过自定义顶点数据,可以创建任意的几何体。像threejs的长方体BoxGeometry、球体SphereGeometry等几何体都是基于BufferGeometry类构建的,它表示一个没有任何形状的空几何体。 1. 自定义点模型 通过javascript 类型化数组 Float32Array创建一组xyz坐标…...
如何使用ChatGPT进行高效的对话生成与优化
目录 一、对话生成的基础原理 二、如何优化对话生成的流畅性与上下文关联性 1. 提示词优化:明确上下文和期望目标 示例:提示词优化 2. 调整生成参数:控制生成长度与内容多样性 示例:调整生成参数 3. 上下文管理:…...
MySQL系列—8.存储结构
目录 1.系统表空间 ibdata 2.通用表空间 .ibd 3.独立表空间 4.Undo 表空间 5.临时表空间 6.Redo Log File 1.系统表空间 ibdata 系统表空间由参数innodb_data_file_path定义路径、初始化大小、自动扩展策略 如: innodb_data_file_path/dayta/mysql/ibdata1:…...
vue2、vue3生成二维码
Vue2版: 工具:使用 qrcodejs插件来生成二维码 安装:npm install qrcodejs2 qrcodejs官网地址: https://davidshimjs.github.io/qrcodejs/https://davidshimjs.github.io/qrcodejs/ 代码示例: <template><…...
Spring Cloud全解析:熔断之Hystrix线程隔离导致的问题
Hystrix线程隔离 在微服务框架中,可能一个服务需要调用多个微服务,在tomcat中运行时,tomcat只是分配了100个线程,由于多个服务之间调用的时间消耗过长,可能会导致线程耗尽,而在Hystrix中存在线程隔离&…...
网络编程项目(云词典项目)
目录 一、功能要求 服务器 用户客户端 二、演示效果 1.登录、注册功能 2. 查单词功能 3.查看历史纪录功能 三、项目代码 1.头文件 2.服务器 3.用户端 一、功能要求 仿照云词典的原理,实现云词典功能,用户可以查询输入的单词的英文解释&…...
Java Spring Boot 项目中的密码加密与验证开发案例手册
本手册主要针对Java项目中的账号密码加密与验证进行详细的步骤讲解和代码示例。适用于开发登录认证、用户管理等功能的场景。文档包含工具类的创建、数据库配置、服务层和控制器层的集成等常见操作。 1. 常用加密操作 在实现安全的登录功能时,密码加密与验证是不可…...
VueSax-解决Vue3报错问题,并支持typescript
以下为坑点 根据官方提示,本人在vue3typescript的项目中添加了vuesax的组件依赖 根据正常的导入依赖思路编写代码,发现typescript一直报 查询vuesax的目录文件发现存在ts文件,于是乎觉得是自己的问题,就查阅gpt与网上资料&#x…...
回归预测 | Matlab基于贝叶斯算法优化XGBoost(BO-XGBoost/Bayes-XGBoost)的数据回归预测+交叉验证
回归预测 | Matlab基于贝叶斯算法优化XGBoost(BO-XGBoost/Bayes-XGBoost)的数据回归预测交叉验证 目录 回归预测 | Matlab基于贝叶斯算法优化XGBoost(BO-XGBoost/Bayes-XGBoost)的数据回归预测交叉验证效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现基于贝叶…...
[数据集][目标检测]电动车入梯进电梯电单车入梯检测数据集VOC+YOLO格式7106张3类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):7106 标注数量(xml文件个数):7106 标注数量(txt文件个数):7106 标注…...
大数常用API
package API;public class BigNum {//如果普通的long和double的精度不足以满足要求,那么可以使用java.math包中的两个类//BigInteger和BigDecimal//前者实现任意精度的整数运算,后者实现任意精度的浮点数运算//BigInteger add(BigInteger other)//BigInt…...
Gartner发布ASCA自动化安全控制评估创新洞察:三年后40%的综合安全厂商都将提供ASCA功能
复杂的安全控制网络、技能差距和快速变化的攻击技术使维持技术安全控制的最佳配置的问题更加复杂。安全和风险管理领导者可以通过自动化安全控制评估来改善他们的安全状况。 主要发现 技术安全控制配置错误是与安全漏洞相关的长期问题。薄弱的安全默认值、配置漂移、为减少误报…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
