Springboot整合Elastic-job
一 概述
Elastic-Job 最开始只有一个 elastic-job-core 的项目,定位轻量级、无中心化,最核心的服务就是支持弹性扩容和数据分片!从 2.X 版本以后,主要分为 Elastic-Job-Lite 和 Elastic-Job-Cloud 两个子项目。esjbo官网地址
- Elastic-Job-Lite 定位为轻量级 无 中 心 化 解 决 方 案 , 使 用jar 包 的 形 式 提 供 分 布 式 任 务 的 协 调 服 务 。
- Elastic-Job-Cloud 使用 Mesos + Docker 的解决方案,额外提供资源治理、应用分发以及进程隔离等服务(跟 Lite 的区别只是部署方式不同,他们使用相同的 API,只要开发一次)。
今天我们主要介绍的是Elastic-Job-Lite,最主要的功能特性如下:
- 分布式调度协调
- 弹性扩容缩容
- 失效转移
- 错过执行作业重触发
- 作业分片一致性,保证同一分片在分布式环境中仅一个执行实例
- 自诊断并修复分布式不稳定造成的问
- 支持并行调度
- 支持作业生命周期操作
- 丰富的作业类型
- Spring整合以及命名空间提供
- 运维平台
应用在各自的节点执行任务,通过 zookeeper 注册中心协调。节点注册、节点选举、任务分片、监听都在 E-Job 的代码中完成。下图是官网提供得架构图。
作业启动流程图:
作业执行流程图:
1.1 基本概念
1.1.1 分片概念
任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的服务器分别执行某一个或几个分片项。
例如:有一个遍历数据库某张表的作业,现有2台服务器。为了快速的执行作业,那么每台服务器应执行作业的50%。 为满足此需求,可将作业分成2片,每台服务器执行1片。作业遍历数据的逻辑应为:服务器A遍历ID以奇数结尾的数据;服务器B遍历ID以偶数结尾的数据。 如果分成10片,则作业遍历数据的逻辑应为:每片分到的分片项应为ID%10,而服务器A被分配到分片项0,1,2,3,4;服务器B被分配到分片项5,6,7,8,9,直接的结果就是服务器A遍历ID以0-4结尾的数据;服务器B遍历ID以5-9结尾的数据。
1.1.2 分片策略
shardingTotalCount:作业分片总数。jobShardingStrategyClass:作业分片策略实现类全路径。shardingItemParameters:分片序列号和个性化参数对照表。分片序列号和参数用等号分隔, 多个键值对用逗号分隔。分片序列号从0开始, 不可大于或等于作业分片总数。分片的维度通常有状态(state)、类型(accountType)、id分区等,需要按照业务合适选取。
elasticJob提供了如下三种分片策略,
- AverageAllocationJobShardingStrategy :(默认的分片策略) 基于平均分配算法的分片策略。
如果有3台服务器, 分成9片, 则每台服务器分到的分片是: 1=[0,1,2], 2=[3,4,5], 3=[6,7,8].
如果有3台服务器, 分成8片, 则每台服务器分到的分片是: 1=[0,1,6], 2=[2,3,7], 3=[4,5].
如果有3台服务器, 分成10片, 则每台服务器分到的分片是: 1=[0,1,2,9], 2=[3,4,5], 3=[6,7,8]
- OdevitySortByNameJobShardingStrategy:根据作业名的哈希值奇偶数决定IP升降序算法的分片策略。
作业名的哈希值为奇数则IP升序.
作业名的哈希值为偶数则IP降序.
用于不同的作业平均分配负载至不同的服务器.
eg:
如果有3台服务器, 分成2片, 作业名称的哈希值为奇数, 则每台服务器分到的分片是: 1=[0], 2=[1], 3=[].
如果有3台服务器, 分成2片, 作业名称的哈希值为偶数, 则每台服务器分到的分片是: 3=[0], 2=[1], 1=[].
- RotateServerByNameJobShardingStrategy:根据作业名的哈希值对服务器列表进行轮转的分片策略。
1.1.3 分片项与业务处理解耦
Elastic-Job并不直接提供数据处理的功能,框架只会将分片项分配至各个运行中的作业服务器,开发者需要自行处理分片项与真实数据的对应关系。
1.1.4 个性化参数
个性化参数即shardingItemParameter,可以和分片项匹配对应关系,用于将分片项的数字转换为更加可读的业务代码。
例如:按照地区水平拆分数据库,数据库A是北京的数据;数据库B是上海的数据;数据库C是广州的数据。 如果仅按照分片项配置,开发者需要了解0表示北京;1表示上海;2表示广州。 合理使用个性化参数可以让代码更可读,如果配置为0=北京,1=上海,2=广州,那么代码中直接使用北京,上海,广州的枚举值即可完成分片项和业务逻辑的对应关系。
1.1.5 任务类型
- Simple类型作业:意为简单实现,未经任何封装的类型。需实现SimpleJob接口。该接口仅提供单一方法用于覆盖,此方法将定时执行。与Quartz原生接口相似,但提供了弹性扩缩容和分片等功能。
- Dataflow类型:用于处理数据流,需实现DataflowJob接口。该接口提供2个方法可供覆盖,分别用于抓取(fetchData)和处理(processData)数据
- Script类型:作业意为脚本类型作业,支持shell,python,perl等所有类型脚本。只需通过控制台或代码配置scriptCommandLine即可,无需编码。执行脚本路径可包含参数,参数传递完毕后,作业框架会自动追加最后一个参数为作业运行时信息。
1.2 核心概念
1.2.1 分布式调度
Elastic-Job-Lite并无作业调度中心节点,而是基于部署作业框架的程序在到达相应时间点时各自触发调度。注册中心仅用于作业注册和监控信息存储。而主作业节点仅用于处理分片和清理等功能。
1.2.2 作业高可用
Elastic-Job-Lite提供最安全的方式执行作业。将分片总数设置为1,并使用多于1台的服务器执行作业,作业将会以1主n从的方式执行。
一旦执行作业的服务器崩溃,等待执行的服务器将会在下次作业启动时替补执行。开启失效转移功能效果更好,可以保证在本次作业执行时崩溃,备机立即启动替补执行。
1.2.3 最大限度利用资源
Elastic-Job-Lite也提供最灵活的方式,最大限度的提高执行作业的吞吐量。将分片项设置为大于服务器的数量,最好是大于服务器倍数的数量,作业将会合理的利用分布式资源,动态的分配分片项。
二 应用安装
2.1 zookeeper 安装
elastic-job-lite,是直接依赖 zookeeper 的,因此在开发之前我们需要先准备好对应的 zookeeper 环境,关于 zookeeper 的安装过程,就不多说了,非常简单,网上都有教程!
2.2 elastic-job-lite-console 安装
elastic-job-lite-console,主要是一个任务作业可视化界面管理系统。
可以单独部署,与平台不关,主要是通过配置注册中心和数据源来抓取数据。
获取的方式也很简单,直接访问https://github.com/apache/shardingsphere-elasticjob地址,然后切换到2.1.5的版本号,然后执行mvn clean install进行打包,获取对应的安装包将其解压,进行bin文件夹启动服务即可!
如果你的网速像蜗牛一样的慢,还有一个办法就是从这个地址https://gitee.com/elasticjob/elastic-job获取对应的源码!
启动服务后,在浏览器访问http://127.0.0.1:8899,输入账户、密码(都是root)即可进入控制台页面,类似如下界面!
进入之后,将上文所在的 zookeeper 注册中心进行配置,包括数据库 mysql 的数据源也可以配置一下!
2.3 创建工程(自集成方式)
2.3.1 引入依赖和配置
本文采用springboot来搭建工程为例,创建工程并添加elastic-job-lite依赖!
<!-- 使用springframework自定义命名空间时引入 --><dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-spring</artifactId><version>2.1.5</version></dependency><!-- elastic-job-lite 默认依赖如下的模块,否则ZookeeperRegistryCenter无法注册 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>2.10.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>2.10.0</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>18.0</version></dependency>
在配置文件application.properties中提前配置好 zookeeper 注册中心相关信息!
#zookeeper config
zookeeper.serverList=127.0.0.1:2181
zookeeper.namespace=example-elastic-job-test
2.3.2 新建 ZookeeperConfig 配置类
@Configuration
@ConditionalOnExpression("'${zookeeper.serverList}'.length() > 0")
public class ZookeeperConfig {/*** zookeeper 配置* @return*/@Bean(initMethod = "init")public ZookeeperRegistryCenter zookeeperRegistryCenter(@Value("${zookeeper.serverList}") String serverList, @Value("${zookeeper.namespace}") String namespace){return new ZookeeperRegistryCenter(new ZookeeperConfiguration(serverList,namespace));}}
2.3.4 新建Simple任务处理类
- 编写一个SimpleJob接口的实现类MySimpleJob,当前工作主要是打印一条日志。
@Slf4j
public class MySimpleJob implements SimpleJob {@Overridepublic void execute(ShardingContext shardingContext) {log.info(String.format("Thread ID: %s, 作业分片总数: %s, " +"当前分片项: %s.当前参数: %s," +"作业名称: %s.作业自定义参数: %s",Thread.currentThread().getId(),shardingContext.getShardingTotalCount(),shardingContext.getShardingItem(),shardingContext.getShardingParameter(),shardingContext.getJobName(),shardingContext.getJobParameter()));}
}
- 创建一个MyElasticJobListener任务监听器,用于监听MySimpleJob的任务执行情况。
@Slf4j
public class MyElasticJobListener implements ElasticJobListener {private long beginTime = 0;@Overridepublic void beforeJobExecuted(ShardingContexts shardingContexts) {beginTime = System.currentTimeMillis();log.info("===>{} MyElasticJobListener BEGIN TIME: {} <===",shardingContexts.getJobName(), DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));}@Overridepublic void afterJobExecuted(ShardingContexts shardingContexts) {long endTime = System.currentTimeMillis();log.info("===>{} MyElasticJobListener END TIME: {},TOTAL CAST: {} <===",shardingContexts.getJobName(), DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"), endTime - beginTime);}
}
- 创建一个MySimpleJobConfig类,将MySimpleJob其注入到zookeeper。
@Configuration
public class MySimpleJobConfig {/*** 任务名称*/@Value("${simpleJob.mySimpleJob.name}")private String mySimpleJobName;/*** cron表达式*/@Value("${simpleJob.mySimpleJob.cron}")private String mySimpleJobCron;/*** 作业分片总数*/@Value("${simpleJob.mySimpleJob.shardingTotalCount}")private int mySimpleJobShardingTotalCount;/*** 作业分片参数*/@Value("${simpleJob.mySimpleJob.shardingItemParameters}")private String mySimpleJobShardingItemParameters;/*** 自定义参数*/@Value("${simpleJob.mySimpleJob.jobParameters}")private String mySimpleJobParameters;@Autowiredprivate ZookeeperRegistryCenter registryCenter;@Beanpublic MySimpleJob mySimpleJob() {return new MySimpleJob();}@Bean(initMethod = "init")public JobScheduler simpleJobScheduler(final MySimpleJob mySimpleJob) {//配置任务监听器MyElasticJobListener elasticJobListener = new MyElasticJobListener();return new SpringJobScheduler(mySimpleJob, registryCenter, getLiteJobConfiguration(), elasticJobListener);}private LiteJobConfiguration getLiteJobConfiguration() {// 定义作业核心配置JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(mySimpleJobName, mySimpleJobCron, mySimpleJobShardingTotalCount).shardingItemParameters(mySimpleJobShardingItemParameters).jobParameter(mySimpleJobParameters).build();// 定义SIMPLE类型配置SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, MySimpleJob.class.getCanonicalName());// 定义Lite作业根配置LiteJobConfiguration simpleJobRootConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).overwrite(true).build();return simpleJobRootConfig;}
}
- 在配置文件application.properties中配置好对应的mySimpleJob参数!
#elastic job
#simpleJob类型的job
simpleJob.mySimpleJob.name=mySimpleJob
simpleJob.mySimpleJob.cron=0/15 * * * * ?
simpleJob.mySimpleJob.shardingTotalCount=3
simpleJob.mySimpleJob.shardingItemParameters=0=a,1=b,2=c
simpleJob.mySimpleJob.jobParameters=helloWorld
5.运行程序,查看效果
在上图demo中,配置的分片数为3,这个时候会有3个线程进行同时执行任务,因为都是在一台机器上执行的,这个任务被执行来3次,下面修改一下端口配置,创建三个相同的服务实例,在看看效果如下:
2.3.5 新建DataFlowJob类型作业
- 创建一个DataflowJob类型的实现类MyDataFlowJob。
@Slf4j
public class MyDataFlowJob implements DataflowJob<String> {private boolean flag = false;@Overridepublic List<String> fetchData(ShardingContext shardingContext) {log.info("开始获取数据");if (flag) {return null;}return Arrays.asList("qingshan", "jack", "seven");}@Overridepublic void processData(ShardingContext shardingContext, List<String> data) {for (String val : data) {// 处理完数据要移除掉,不然就会一直跑,处理可以在上面的方法里执行。这里采用 flaglog.info("开始处理数据:" + val);}flag = true;}
}
- 接着创建MyDataFlowJob的配置类,将其注入到zookeeper注册中心。
Configuration
public class MyDataFlowJobConfig {/*** 任务名称*/@Value("${dataflowJob.myDataflowJob.name}")private String jobName;/*** cron表达式*/@Value("${dataflowJob.myDataflowJob.cron}")private String jobCron;/*** 作业分片总数*/@Value("${dataflowJob.myDataflowJob.shardingTotalCount}")private int jobShardingTotalCount;/*** 作业分片参数*/@Value("${dataflowJob.myDataflowJob.shardingItemParameters}")private String jobShardingItemParameters;/*** 自定义参数*/@Value("${dataflowJob.myDataflowJob.jobParameters}")private String jobParameters;@Autowiredprivate ZookeeperRegistryCenter registryCenter;@Beanpublic MyDataFlowJob myDataFlowJob() {return new MyDataFlowJob();}@Bean(initMethod = "init")public JobScheduler dataFlowJobScheduler(final MyDataFlowJob myDataFlowJob) {MyElasticJobListener elasticJobListener = new MyElasticJobListener();return new SpringJobScheduler(myDataFlowJob, registryCenter, getLiteJobConfiguration(), elasticJobListener);}private LiteJobConfiguration getLiteJobConfiguration() {// 定义作业核心配置JobCoreConfiguration dataflowCoreConfig = JobCoreConfiguration.newBuilder(jobName, jobCron, jobShardingTotalCount).shardingItemParameters(jobShardingItemParameters).jobParameter(jobParameters).build();// 定义DATAFLOW类型配置DataflowJobConfiguration dataflowJobConfig = new DataflowJobConfiguration(dataflowCoreConfig, MyDataFlowJob.class.getCanonicalName(), false);// 定义Lite作业根配置LiteJobConfiguration dataflowJobRootConfig = LiteJobConfiguration.newBuilder(dataflowJobConfig).overwrite(true).build();return dataflowJobRootConfig;}
}
- 最后,在配置文件application.properties中配置好对应的myDataflowJob参数!
#dataflow类型的job
dataflowJob.myDataflowJob.name=myDataflowJob
dataflowJob.myDataflowJob.cron=0/15 * * * * ?
dataflowJob.myDataflowJob.shardingTotalCount=1
dataflowJob.myDataflowJob.shardingItemParameters=0=a,1=b,2=c
dataflowJob.myDataflowJob.jobParameters=myDataflowJobParamter
- 运行程序,查看效果
需要注意的地方是,如果配置的是流式处理类型,它会不停的拉取数据、处理数据,在拉取的时候,如果返回为空,就不会处理数据!如果配置的是非流式处理类型,和上面介绍的simpleJob类型,处理一样!
2.3.6 新建ScriptJob类型作业
- ScriptJob 类型的任务配置:主要是用于定时执行某个脚本,一般用的比较少!因为目标是脚本,没有执行的任务,所以无需编写任务作业类型!只需要编写一个ScriptJob类型的配置类即可,命令是echo 'Hello World !内容!
@Configuration
public class MyScriptJobConfig {/*** 任务名称*/@Value("${scriptJob.myScriptJob.name}")private String jobName;/*** cron表达式*/@Value("${scriptJob.myScriptJob.cron}")private String jobCron;/*** 作业分片总数*/@Value("${scriptJob.myScriptJob.shardingTotalCount}")private int jobShardingTotalCount;/*** 作业分片参数*/@Value("${scriptJob.myScriptJob.shardingItemParameters}")private String jobShardingItemParameters;/*** 自定义参数*/@Value("${scriptJob.myScriptJob.jobParameters}")private String jobParameters;@Autowiredprivate ZookeeperRegistryCenter registryCenter;@Bean(initMethod = "init")public JobScheduler scriptJobScheduler() {MyElasticJobListener elasticJobListener = new MyElasticJobListener();return new JobScheduler(registryCenter, getLiteJobConfiguration(), elasticJobListener);}private LiteJobConfiguration getLiteJobConfiguration() {// 定义作业核心配置JobCoreConfiguration scriptCoreConfig = JobCoreConfiguration.newBuilder(jobName, jobCron, jobShardingTotalCount).shardingItemParameters(jobShardingItemParameters).jobParameter(jobParameters).build();// 定义SCRIPT类型配置ScriptJobConfiguration scriptJobConfig = new ScriptJobConfiguration(scriptCoreConfig, "echo 'Hello World !'");// 定义Lite作业根配置LiteJobConfiguration scriptJobRootConfig = LiteJobConfiguration.newBuilder(scriptJobConfig).overwrite(true).build();return scriptJobRootConfig;}
}
- 在配置文件application.properties中配置好对应的myScriptJob参数!
#script类型的job
scriptJob.myScriptJob.name=myScriptJob
scriptJob.myScriptJob.cron=0/15 * * * * ?
scriptJob.myScriptJob.shardingTotalCount=3
scriptJob.myScriptJob.shardingItemParameters=0=a,1=b,2=c
scriptJob.myScriptJob.jobParameters=myScriptJobParamter
- 运行程序,看看效果
2.3.7 任务状态持久化
可能有的人会发出疑问,elastic-job是如何存储数据的,用ZooInspector客户端链接zookeeper注册中心,你发现对应的任务配置被存储到相应的树根上!而具体作业任务执行轨迹和状态结果是不会存储到zookeeper,需要我们在项目中通过数据源方式进行持久化!
将任务状态持久化到数据库配置过程也很简单,只需要在对应的配置类上注入数据源即可,以MySimpleJobConfig为例,代码如下:
@Configuration
public class MySimpleJobConfig {/*** 任务名称*/@Value("${simpleJob.mySimpleJob.name}")private String mySimpleJobName;/*** cron表达式*/@Value("${simpleJob.mySimpleJob.cron}")private String mySimpleJobCron;/*** 作业分片总数*/@Value("${simpleJob.mySimpleJob.shardingTotalCount}")private int mySimpleJobShardingTotalCount;/*** 作业分片参数*/@Value("${simpleJob.mySimpleJob.shardingItemParameters}")private String mySimpleJobShardingItemParameters;/*** 自定义参数*/@Value("${simpleJob.mySimpleJob.jobParameters}")private String mySimpleJobParameters;@Autowiredprivate ZookeeperRegistryCenter registryCenter;@Autowiredprivate DataSource dataSource;;@Beanpublic MySimpleJob stockJob() {return new MySimpleJob();}@Bean(initMethod = "init")public JobScheduler simpleJobScheduler(final MySimpleJob mySimpleJob) {//添加事件数据源配置JobEventConfiguration jobEventConfig = new JobEventRdbConfiguration(dataSource);MyElasticJobListener elasticJobListener = new MyElasticJobListener();return new SpringJobScheduler(mySimpleJob, registryCenter, getLiteJobConfiguration(), jobEventConfig, elasticJobListener);}private LiteJobConfiguration getLiteJobConfiguration() {// 定义作业核心配置JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(mySimpleJobName, mySimpleJobCron, mySimpleJobShardingTotalCount).shardingItemParameters(mySimpleJobShardingItemParameters).jobParameter(mySimpleJobParameters).build();// 定义SIMPLE类型配置SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, MySimpleJob.class.getCanonicalName());// 定义Lite作业根配置LiteJobConfiguration simpleJobRootConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).overwrite(true).build();return simpleJobRootConfig;}
}
同时,需要在配置文件application.properties中配置好对应的datasource参数!
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/example-elastic-job-test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
运行程序,然后在elastic-job-lite-console控制台配置对应的数据源!
注意:该功能Mysql数据库的话只支持5.7,其他版本则无法连接
最后,点击【作业轨迹】即可查看对应作业执行情况!
2.4 创建工程(start集成方式)
具体 参考(推荐):https://blog.csdn.net/baidu_21349635/article/details/106317774
三 常见问题集锦
参考文献:
https://blog.csdn.net/qq_34350584/article/details/119754657
https://blog.csdn.net/lvlei19911108/article/details/118633115
https://blog.csdn.net/cicada_smile/article/details/104810958
相关文章:
Springboot整合Elastic-job
一 概述 Elastic-Job 最开始只有一个 elastic-job-core 的项目,定位轻量级、无中心化,最核心的服务就是支持弹性扩容和数据分片!从 2.X 版本以后,主要分为 Elastic-Job-Lite 和 Elastic-Job-Cloud 两个子项目。esjbo官网地址 Ela…...
VsCode的介绍和入门
目录 编辑 介绍 我应该切换到 VS Code 吗?为什么? 入门 Explorer 搜索 源代码控制 调试器 扩展 终点站 命令面板 主题 定制化 不错的配置选项 最适合编码的字体 工作空间 编辑 智能感知 代码格式化 错误和警告 键盘快捷键 键位图…...
C++:自创小游戏
欢迎来玩,每次都有不一样的结果。 长达142行。 #include<bits/stdc.h> #include<windows.h> #define random(a,b) (rand()%(b-a1)a) using namespace std; int main(){int n;cout<<"输1~10,越小越好,不告诉你有什么用,当然也可…...
AIGC带给开发者的冲击
未来会有两种开发者,一种是会使用AIGC工具的开发者另一种是不会使用AIGC的开发者,AIGC的出现提高了开发效率和代码质量,对开发者意味着需要不断学习和适应新的技术和工作范式,开发者可以把更多的精力放在高级抽象的定义以及更高维…...
利用蚁剑钓鱼上线CS
前言 中国蚁剑使用Electron构建客户端软件,Electron实现上用的是Node.js,并且Node.js能执行系统命令,故可以利用蚁剑的webshell页面嵌入js来直接执行命令,进而钓鱼来上线CS。(类似Goby,Goby也是使用Electr…...
宣传照(私密)勿转发
精美的海报通常都是由UI进行精心设计的,现在有100 件商品需要进行宣传推广,如果每个商品都出一张图显然是不合理的,且商品信息各异。因此需要通过代码的形式生成海报。对此,我也对我宣传一波,企图实现我一夜暴富的伟大…...
【Spring】19 AOP介绍及实例详解
文章目录 1. 定义1)什么意思呢?2)如何解决呢? 2. 基本概念1)切面(Aspect)2)切点(Pointcut)3)通知(Advice)4)连…...
ES(Elasticsearch)的基本使用
一、常见的NoSQL解决方案 1、redis Redis是一个基于内存的 key-value 结构数据库。Redis是一款采用key-value数据存储格式的内存级NoSQL数据库,重点关注数据存储格式,是key-value格式,也就是键值对的存储形式。与MySQL数据库不同࿰…...
【JVM面试题】Java中的静态方法为什么不能调用非静态方法
昨晚京东大佬勇哥在群里分享了一道他新创的JVM面试题,我听完后觉得还挺有意思的,分享给大家 小佬们先别急着看我的分析,先自己想想答案 你是不是想说 因为静态方法是属于类的,而非静态方法属于实例对象 哈,有人这样回答…...
对‘float16_t’的引用有歧义
float16_t 是一个半精度浮点数类型,通常在一些需要高性能和低精度的场合被使用。 如果加了using namespace cv;后,OpenCV库中也有一个名为float16_t的类型定义,与最初的float16_t存在冲突,导致编译失败。 为了解决这个问题&#…...
Windows重装升级Win11系统后 恢复Mysql数据
背景 因为之前电脑硬盘出现问题,换了盘重装了系统,项目的数据库全部没了,还好之前的Mysql是安装在的D盘里,还有留存文件 解决办法 1.设置环境变量 我的路径是 D:\SoftWare\Application\mysql-5.7.35-winx64 此电脑右键属性 …...
MySQL之四大引擎、账号管理以及建库
目录 数据库存储引擎 简介 存储引擎得查看 support字段说明 InnoDB MyISAM MEMORY Archive 数据库管理 元数据库简介 元数据库分类 相关操作 MySQL库 数据表管理 三大范式 基本数据类型 优化原则 整形 实数 字符串 text&blob 日期类型 选中标识符 数…...
shell编程——查找局域网内存活主机
题目要求:写一个shell脚本,探测局域网内存活主机 首先,我们的思路是在循环中不断ping主机,然后根据ping的结果来判断主机是否存活 本题中ping语句如下: ping -c 3 -i 0.3 -W 1 192.168.1.1 解释一下参数࿱…...
python django 个人记账管理系统
python django 个人记账管理系统。 功能:登录,新用户注册,个人信息修改,收入,支出记录,收入记账管理,支出记账管理,收入,支出统计 技术:python django&…...
C#的Char 结构的方法之IsLetterOrDigit()
目录 一、Char 结构 二、Char.IsLetterOrDigit 方法 1.定义 2.重载 3.示例 4.IsLetterOrDigit(Char) 5.IsLetterOrDigit(String, Int32) 一、Char 结构方法 CompareTo(Char)将此实例与指定的 Char 对象进行比较,并指示此实例在排序顺序中是位于指定的 Char …...
配置Docker私有仓库
# 打开要修改的文件 vi /etc/docker/daemon.json # 添加内容: "insecure-registries":["http://自己服务器的ip地址:设置的端口号"] # 重加载 systemctl daemon-reload # 重启docker systemctl restart docker在自己设定的文件夹内使用DockerCo…...
计算机网络-动态路由
网络层协议:ip,ospf,rip,icmp共同组成网络层体系 ospf用于自治系统内部。 一个路由器或者网关需要能够支持多个不同的路由协议,以适应不同的网络环境。特别是在连接不同自治系统的边缘路由器或边界网关的情况下&#…...
光耀未来 第一届能源电子产业创新大赛太阳能光伏赛道决赛在宜宾举行
1月3日,第一届能源电子产业创新大赛太阳能光伏赛道决赛在宜宾盛大举行,本次比赛吸引了全国范围内的光伏行业顶尖人才和创新团队参与。 为深入贯彻《关于推动能源电子产业发展的指导意见》,推动我国能源电子产业升级,工业和信息化部…...
【小沐学NLP】Python实现TF-IDF算法(nltk、sklearn、jieba)
文章目录 1、简介1.1 TF1.2 IDF1.3 TF-IDF2.1 TF-IDF(sklearn)2.2 TF-IDF(nltk)2.3 TF-IDF(Jieba)2.4 TF-IDF(python) 结语 1、简介 TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF是词频(Term Fr…...
.cer格式证书文件和 .pfx格式证书文件有什么区别?
这里我们将讨论.cer和.pfx文件类型之间的差异。 什么是数字证书? 数字证书在电子通信中用作验证身份的密码机制。我们需要这些证书来建立安全的在线通信渠道,并确保数字数据的隐私、真实性和正确性。 数字证书包括主题(实体详细信息…...
【docker实战】安装tomcat并连接mysql数据库
本节用docker来安装tomcat,并用这个tomcat连接我们上一节安装好的mysql数据库 一、拉取镜像 我们安装8.5.69版本 先搜索一下 [rootlocalhost ~]# docker search tomcat NAME DESCRIPTION …...
LeetCode 每日一题 Day 32 ||递归单调栈
2487. 从链表中移除节点 给你一个链表的头节点 head 。 移除每个右侧有一个更大数值的节点。 返回修改后链表的头节点 head 。 示例 1: 输入:head [5,2,13,3,8] 输出:[13,8] 解释:需要移除的节点是 5 ,2 和 3 。…...
【mars3d】FixedRoute的circle没有跟polyline贴着模型的解决方案
问题:【mars3d】官网的贴模型示例中,参考api文档增加了circle的配置,但是FixedRoute的circle没有跟polyline贴着模型 circle: { radius: 10, materialType: mars3d.MaterialType.CircleWave, materialOptions: { color: "#ffff00"…...
Day7 vitest 之 vitest配置第三版
项目目录 runner Type: VitestRunnerConstructor Default: node, 当运行test的时候 benchmark,当运行bench测试的时候 功能 自定义测试运行程序的路径。 要求 应与自定义库运行程序一起使用。 如果您只是运行测试,则可能不需要这个。它主要由library作者使用 …...
git补充上次提交
1.首先,确保你还没有执行 git push 操作。如果尚未推送到远程仓库,那么可以在本地进行修正。 2.添加遗漏的文件: git add <遗漏的文件路径>3.提交新修改或新增的文件,并将它与上一次提交合并(如果希望保持提交历…...
计算机网络名词解释
1.ICMP 网际控制报文 允许主机或路由器报告差错情况和提供有关异常情况的报告 2.RIP路由信息协议 是一种分布式的,基于距离向量的路由选择协议 3.BGP 外部网关协议 是不同自治系统的路由器之间交换路由信息的协议 4.IGMP 网际管理协议 使用多播路由器知道多播…...
flink table view datastream互转
case class outer(f1:String,f2:Inner) case class outerV1(f1:String,f2:Inner,f3:Int) case class Inner(f3:String,f4:Int) 测试代码 package com.yy.table.convertimport org.apache.flink.streaming.api.scala.StreamExecutionEnvironment import org.apache.flink.tabl…...
redis重启后数据丢失问题解决(亲测好用)
redis修改密码重启后发现redis中的数据丢失了 解决办法: 首先在redis的安装目录下查找重启之前的dump.rdb文件,发现只有当天的一个dump.rdb文件,确认不是重启备份的文件 然后我就全盘找一下dump.rdb的备份文件,找到前一天的备份…...
敬请期待……
敬请期待…… 《Python百宝箱》 序号文章目录直达链接表白系列1无法拒绝的表白界面https://want595.blog.csdn.net/article/details/1347448942满屏飘字表白代码https://want595.blog.csdn.net/article/details/1350373883无限弹窗表白代码...
3.10 Android eBPF HelloWorld调试(四)
一,读取eBPF map的android应用程序示例 1.1 C++源码及源码解读 /system/memory/bpfmapparsed/hello_world_map_parser.cpp //基于aosp android12#define LOG_TAG "BPF_MAP_PARSER"#include <log/log.h> #include <stdlib.h> #include <unistd.h&g…...
常州做网站公司有哪些/哪里能买精准客户电话
胎压监测 (15分) 小轿车中有一个系统随时监测四个车轮的胎压,如果四轮胎压不是很平衡,则可能对行车造成严重的影响。 taiya.JPG 让我们把四个车轮 —— 左前轮、右前轮、右后轮、左后轮 —— 顺次编号为 1、2、3、4。本题就请你编写一个监测程序&#x…...
赣县企业网站建设/产品营销策划方案
Linux 性能测试与分析 Revision History Version Date Author Description 1.0 2011/5/26 dengwutaobao.com 初稿 1.1 2011/6/23 dengwutaobao.com 添加CPU分析 1.2 2012/2/20 dengwutaobao.com 添加MEM,IO分析 1.3 2012/2/23 dengwutaobao.com 更新工作原…...
2017还有人做网站吗/百度24小时人工电话
在命令行下运行 msdtc -uninstall ,卸载 msdtc 服务; 再运行 msdtc -install ,安装 msdtc 服务转载于:https://www.cnblogs.com/wlwjc/articles/1690230.html...
成品网站安装/最近新闻大事
SPI是一种总线协议。 总线,一个主设配(FPGA)只用三四个引脚和n个从设备进行通信。 例如FPGA通过SPI配置SI4133频综模块。 spi是一种通信协议。但是有时候我们看到对spi进行配置,配置什么时钟极性(cpol)时钟…...
网页设计实训内容/seo营销推广公司
转载于:https://www.cnblogs.com/jasonlixuetao/p/5557845.html...
招聘网站比对表怎么做/网站排名seo培训
本文转自:http://www.cnblogs.com/henw/archive/2011/09/23/2186387.html 1. 需要引用的类库 ?1234using System.Net; using System.IO; using System.Text; using System.Text.RegularExpressions;2. 获取其他网站网页内容的关键代码 ?12345WebRequest request …...