LTS介绍

LTS(light-task-scheduler)主要用于解决分布式任务调度问题,支持实时任务,定时任务,Cron任务,Repeat任务。有较好的伸缩性,扩展性,健壮稳定性而被多家公司使用,同时也希望开源爱好者一起贡献。

主要功能

  • 支持分布式,解决多点故障,支持动态扩容,容错重试等
  • Spring扩展支持,SpringBoot支持,Spring Quartz Cron任务的无缝接入支持
  • 节点监控支持,任务执行监控支持,JVM监控支持
  • 后台运维操作支持, 可以动态提交,更改,停止 任务

项目地址

  • github地址:https://github.com/ltsopensource/light-task-scheduler
  • oschina地址:http://git.oschina.net/hugui/light-task-scheduler
  • 例子: https://github.com/ltsopensource/lts-examples
  • 文档地址(正在更新中): https://www.gitbook.com/book/qq254963746/lts/details

LTS技术架构

LTS 着力于解决分布式任务调度问题,将任务的提交者和执行者解耦,解决任务执行的单点故障,支持动态扩容,出错重试等机制。代码程序设计上,参考了优秀开源项目Dubbo,Hadoop的部分思想。

LTS目前支持四种任务

  • 实时任务:提交了之后立即就要执行的任务。
  • 定时任务:在指定时间点执行的任务,譬如 今天3点执行(单次)。
  • Cron任务:CronExpression,和quartz类似(但是不是使用quartz实现的)譬如 0 0/1 * ?
  • Repeat任务:譬如每隔5分钟执行一次,重复50次就停止。

架构设计上,LTS框架中包含以下五种类型的节点

  • JobClient :主要负责提交任务, 并接收任务执行反馈结果。
  • JobTracker :负责任务调度,接收并分配任务。
  • TaskTracker :负责执行任务,执行完反馈给JobTracker。
  • LTS-Monitor :主要负责收集各个节点的监控信息,包括任务监控信息,节点JVM监控信息
  • LTS-Admin :管理后台)主要负责节点管理,任务队列管理,监控管理等。

架构图

  • Registry: 注册中心,LTS提供多种实现,目前支持zookeeper(推荐)和redis, 主要用于LTS的节点信息暴露和master节点选举。
  • FailStore: 失败存储,主要用于在部分场景远程RPC调用失败的情况,采取现存储本地KV文件系统,待远程通信恢复的时候再进行数据补偿。目前FailStore场景,主要有RetryJobClient提交**任务失败的时候,存储FailStore;TaskTracker返回任务执行结果给JobTracker的失败 时候,FailStore;TaskTracker提交BizLogger的失败的时候,存储FailStore. 目前FailStore有四种实现:leveldb,rocksdb,berkeleydb,mapdb(当然用户也可以实现扩展接口实现自己的FailStore)
  • QueueManager: 任务队列,目前提供mysql(推荐)和mongodb两种实现(同样的用户可以自己扩容展示其他的,譬如oracle等),主要存储任务数据和任务执行日志等。
  • RPC: 远程RPC通信框架,目前也支持多种实现,LTS自带有netty和mina,用户可以自行选择,或者自己SPI扩展实现其他的。
  • NodeGroup: 节点组,同一个节点组中的任何节点都是对等的,等效的,对外提供相同的服务。譬如TaskTracker中有10个nodeGroup都是send_msg的节点组,专门执行发送短信的任务。每个节点组中都有一个master节点,这个master节点是由LTS动态选出来的,当一个master节点挂掉之后,LTS会立马选出另外一个master节点,框架提供API监听接口给用户。
  • ClusterName: LTS集群,就如上图所示,整个图就是一个集群,包含LTS的五种节点。

节点图

  • 一个节点组等同于一个集群,同一个节点组中的各个节点是对等的,外界无论连接节点组中的任务一个节点都是可以的。
  • 每个节点组中都有一个master节点,采用zookeeper进行master选举(master宕机,会自动选举出新的master节点),框架会提供接口API来监听master节点的变化,用户可以自己使用master节点做自己想做的事情。
  • JobClient和TaskTracker都可以存在多个节点组。譬如 JobClient 可以存在多个节点组。 譬如:JobClient 节点组为 ‘lts_WEB’ 中的一个节点提交提交一个 只有节点组为’lts_TRADE’的 TaskTracker 才能执行的任务。
  • (每个集群中)JobTacker只有一个节点组。
  • 多个JobClient节点组和多个TaskTracker节点组再加上一个JobTacker节点组, 组成一个大的集群。

工作流程

  • JobClient 提交一个 任务 给 JobTracker, 这里我提供了两种客户端API, 一种是如果JobTracker 不存在或者提交失败,直接返回提交失败。另一种客户端是重试客户端, 如果提交失败,先存储到本地leveldb(可以使用NFS来达到同个节点组共享leveldb文件的目的,多线程访问,做了文件锁处理),返回给客户端提交成功的信息,待JobTracker可用的时候,再将任务提交。
  • JobTracker 收到JobClient提交来的任务,先生成一个唯一的JobID。然后将任务储存在Mongo集群中。JobTracker 发现有(任务执行的)可用的TaskTracker节点(组) 之后,将优先级最大,最先提交的任务分发给TaskTracker。这里JobTracker会优先分配给比较空闲的TaskTracker节点,达到负载均衡。
  • TaskTracker 收到JobTracker分发来的任务之后,执行。执行完毕之后,再反馈任务执行结果给JobTracker(成功or 失败[失败有失败错误信息]),如果发现JobTacker不可用,那么存储本地leveldb,等待TaskTracker可用的时候再反馈。反馈结果的同时,询问JobTacker有没有新的任务要执行。
  • JobTacker收到TaskTracker节点的任务结果信息,生成并插入(mongo)任务执行日志。根据任务信息决定要不要反馈给客户端。不需要反馈的直接删除, 需要反馈的(同样JobClient不可用存储文件,等待可用重发)。
  • JobClient 收到任务执行结果,进行自己想要的逻辑处理。

Spring/Spring Boot支持

LTS可以完全不用Spring框架,但是考虑到很用用户项目中都是用了Spring框架,所以LTS也提供了对Spring的支持,包括Xml和注解,引入lts-spring.jar即可。

  • 业务日志记录器

在TaskTracker端提供了业务日志记录器,供应用程序使用,通过这个业务日志器,可以将业务日志提交到JobTracker,这些业务日志可以通过任务ID串联起来,可以在LTS-Admin中实时查看任务的执行进度。

  • SPI扩展支持

SPI扩展可以达到零侵入,只需要实现相应的接口,并实现即可被LTS使用,目前开放出来的扩展接口有 对任务队列的扩展,用户可以不选择使用mysql或者mongo作为队列存储,也可以自己实现。 对业务日志记录器的扩展,目前主要支持console,mysql,mongo,用户也可以通过扩展选择往其他地方输送日志。

  • 节点监控

可以对JobTracker,TaskTracker节点进行资源监控,任务监控等,可以实时的在LTS-Admin管理后台查看,进而进行合理的资源调配。

  • 多样化任务执行结果支持

LTS框架提供四种执行结果支持,EXECUTE_SUCCESS,EXECUTE_FAILED,EXECUTE_LATER,EXECUTE_EXCEPTION,并对每种结果采取相应的处理机制,譬如重试。 EXECUTE_SUCCESS: 执行成功,这种情况,直接反馈客户端(如果任务被设置了要反馈给客户端)。 EXECUTE_FAILED:执行失败,这种情况,直接反馈给客户端,不进行重试。 EXECUTE_LATER:稍后执行(需要重试),这种情况,不反馈客户端,重试策略采用30s的策略,默认最大重试次数为10次,用户可以通过参数设置修改这些参数。 EXECUTE_EXCEPTION:执行异常, 这中情况也会重试(重试策略,同上)

  • FailStore容错

采用FailStore机制来进行节点容错,Fail And Store,不会因为远程通信的不稳定性而影响当前应用的运行。

  • 负载均衡

    JobClient 和 TaskTracker会随机连接JobTracker节点组中的一个节点,实现JobTracker负载均衡。当连接上后,将一直保持连接这个节点,保持连接通道,知道这个节点不可用,减少每次都重新连接一个节点带来的性能开销。 JobTracker 分发任务时,是优先分配给最空闲的一个TaskTracker节点,实现TaskTracker节点的负载均衡。

  • 健壮性(故障转移)

    当节点组中的一个节点当机之后,自动转到其他节点工作。当整个节点组当机之后,将会采用存储文件的方式,待节点组可用的时候进行重发。 当执行任务的TaskTracker节点当机之后,JobTracker 会将这个TaskTracker上的未完成的任务(死任务),重新分配给节点组中其他节点执行。

  • 动态扩容

因为LTS各个节点都是无状态的,所以支持动态增加删除节点,达到负载均衡的目的

环境准备

  • 1. Java JDK

    因为LTS是使用Java语言编写的,所以必须要有个Java编译运行环境,目前LTS支持JDK1.6及以上版本。

  • 2. Maven

LTS项目是基于Maven做项目依赖管理的,所以用户机器上需要配置Maven环境

  • 3. Zookeeper/Redis

因LTS目前支持Zookeeper和Redis作为注册中心,主要用于节点信息暴露、监听、master节点选举。用于选择其一即可,建议zookeeper。

  • 4. Mysql/Mongodb

LTS目前支持Mysql和mongodb作为任务队列的存储引擎。用户同样的选择其中一个即可。

部署

部署建议

  1. Admin后台: 建议Admin后台单独部署,默认会嵌入一个Monitor
  2. Monitor:默认在Admin后台进程中有一个,如果一个不够,也可以单独启动多个
  3. JobTracker: 建议单独部署
  4. JobClient:,这个是提交任务的工程,一般是和业务相关的,所以会放在业 务工程中, 当然也要看业务场景
  5. TaskTracker,这个因为是跑任务的,具体看业务场景, 一般情况下也可以是独立部署

1. JobTracker和LTS-Admin部署

提供(cmd)windows和(shell)linux两种版本脚本来进行编译和部署:

  1. 运行根目录下的sh build.sh或build.cmd脚本,会在dist目录下生成lts-{version}-bin文件夹
  1. 下面是其目录结构,其中bin目录主要是JobTracker和LTS-Admin的启动脚本。jobtracker 中是 JobTracker的配置文件和需要使用到的jar包,lts-admin是LTS-Admin相关的war包和配置文件。 lts-{version}-bin的文件结构、
-- lts-${version}-bin|-- bin|   |-- jobtracker.cmd|   |-- jobtracker.sh|   |-- lts-admin.cmd|   |-- lts-admin.sh|   |-- lts-monitor.cmd|   |-- lts-monitor.sh|   |-- tasktracker.sh|-- conf|   |-- log4j.properties|   |-- lts-admin.cfg|   |-- lts-monitor.cfg|   |-- readme.txt|   |-- tasktracker.cfg|   |-- zoo|       |-- jobtracker.cfg|       |-- log4j.properties|       |-- lts-monitor.cfg|-- lib|   |-- *.jar|-- war|-- jetty|   |-- lib|       |-- *.jar|-- lts-admin.war

JobTracker启动

如果你想启动一个节点,直接修改下conf/zoo下的配置文件,然后运行 sh jobtracker.sh zoo start即可,如果你想启动两个JobTracker节点,那么你需要拷贝一份zoo,譬如命名为zoo2,修改下zoo2下的配置文件,然后运行sh jobtracker.sh zoo2 start即可。logs文件夹下生成jobtracker-zoo.out日志。

LTS-Admin启动

修改conf/lts-monitor.cfg和conf/lts-admin.cfg下的配置,然后运行bin下的sh lts-admin.sh或lts-admin.cmd脚本即可。logs文件夹下会生成lts-admin.out日志,启动成功在日志中会打印出访问地址,用户可以通过这个访问地址访问了。

2. JobClient(部署)使用

需要引入lts的jar包有lts-jobclient-{version}.jar,lts-core-{version}.jar 及其它第三方依赖jar。

API方式启动

1

2

3

4

5

6

7

8

9

10

11

12

13

14

JobClient jobClient = new RetryJobClient();

jobClient.setNodeGroup("test_jobClient");

jobClient.setClusterName("test_cluster");

jobClient.setRegistryAddress("zookeeper://127.0.0.1:2181");

jobClient.start();

// 提交任务

Job job = new Job();

job.setTaskId("3213213123");

job.setParam("shopId""11111");

job.setTaskTrackerNodeGroup("test_trade_TaskTracker");

// job.setCronExpression("0 0/1 * * * ?");  // 支持 cronExpression表达式

// job.setTriggerTime(new Date()); // 支持指定时间执行

Response response = jobClient.submitJob(job);

  Spring XML方式启动

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<bean id="jobClient" class="com.github.ltsopensource.spring.JobClientFactoryBean">

    <property name="clusterName" value="test_cluster"/>

    <property name="registryAddress" value="zookeeper://127.0.0.1:2181"/>

    <property name="nodeGroup" value="test_jobClient"/>

    <property name="masterChangeListeners">

        <list>

            <bean class="com.github.ltsopensource.example.support.MasterChangeListenerImpl"/>

        </list>

    </property>

    <property name="jobFinishedHandler">

        <bean class="com.github.ltsopensource.example.support.JobFinishedHandlerImpl"/>

    </property>

    <property name="configs">

        <props>

            <!-- 参数 -->

            <prop key="job.fail.store">leveldb</prop>

        </props>

    </property>

</bean>

  Spring 全注解方式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@Configuration

public class LTSSpringConfig {

    @Bean(name = "jobClient")

    public JobClient getJobClient() throws Exception {

        JobClientFactoryBean factoryBean = new JobClientFactoryBean();

        factoryBean.setClusterName("test_cluster");

        factoryBean.setRegistryAddress("zookeeper://127.0.0.1:2181");

        factoryBean.setNodeGroup("test_jobClient");

        factoryBean.setMasterChangeListeners(new MasterChangeListener[]{

                new MasterChangeListenerImpl()

        });

        Properties configs = new Properties();

        configs.setProperty("job.fail.store""leveldb");

        factoryBean.setConfigs(configs);

        factoryBean.afterPropertiesSet();

        return factoryBean.getObject();

    }

}

  

3. TaskTracker(部署使用)

需要引入lts的jar包有lts-tasktracker-{version}.jar,lts-core-{version}.jar 及其它第三方依赖jar。

定义自己的任务执行类

public class MyJobRunner implements JobRunner {private final static BizLogger bizLogger = LtsLoggerFactory.getBizLogger();@Overridepublic Result run(Job job) throws Throwable {try {// TODO 业务逻辑// 会发送到 LTS (JobTracker上)bizLogger.info("测试,业务日志啊啊啊啊啊");} catch (Exception e) {return new Result(Action.EXECUTE_FAILED, e.getMessage());}return new Result(Action.EXECUTE_SUCCESS, "执行成功了,哈哈");}
}

API方式启动

TaskTracker taskTracker = new TaskTracker();
taskTracker.setJobRunnerClass(MyJobRunner.class);
taskTracker.setRegistryAddress("zookeeper://127.0.0.1:2181");
taskTracker.setNodeGroup("test_trade_TaskTracker");
taskTracker.setClusterName("test_cluster");
taskTracker.setWorkThreads(20);
taskTracker.start();

Spring XML方式启动

<bean id="taskTracker" class="com.github.ltsopensource.spring.TaskTrackerAnnotationFactoryBean" init-method="start"><property name="jobRunnerClass" value="com.github.ltsopensource.example.support.MyJobRunner"/><property name="bizLoggerLevel" value="INFO"/><property name="clusterName" value="test_cluster"/><property name="registryAddress" value="zookeeper://127.0.0.1:2181"/><property name="nodeGroup" value="test_trade_TaskTracker"/><property name="workThreads" value="20"/><property name="masterChangeListeners"><list><bean class="com.github.ltsopensource.example.support.MasterChangeListenerImpl"/></list></property><property name="configs"><props><prop key="job.fail.store">leveldb</prop></props></property>
</bean>

Spring注解方式启动

@Configuration
public class LTSSpringConfig implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}@Bean(name = "taskTracker")public TaskTracker getTaskTracker() throws Exception {TaskTrackerAnnotationFactoryBean factoryBean = new TaskTrackerAnnotationFactoryBean();factoryBean.setApplicationContext(applicationContext);factoryBean.setClusterName("test_cluster");factoryBean.setJobRunnerClass(MyJobRunner.class);factoryBean.setNodeGroup("test_trade_TaskTracker");factoryBean.setBizLoggerLevel("INFO");factoryBean.setRegistryAddress("zookeeper://127.0.0.1:2181");factoryBean.setMasterChangeListeners(new MasterChangeListener[]{new MasterChangeListenerImpl()});factoryBean.setWorkThreads(20);Properties configs = new Properties();configs.setProperty("job.fail.store", "leveldb");factoryBean.setConfigs(configs);factoryBean.afterPropertiesSet();
//        factoryBean.start();return factoryBean.getObject();}
}

包引入说明

1. JobTracker,JobClient,TaskTracker都需要引入的包

1.1 lts-core

<dependency><groupId>com.github.ltsopensource</groupId><artifactId>lts-core</artifactId><version>${lts版本号}</version>
</dependency>

1.2 zk客户端包

二选一, 通过 addConfig(“zk.client”, “可选值: curator, zkclient, lts”) 设置, 如果用lts,可以不用引入包

zkclient

<dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId><version>0.1</version>
</dependency>

curator

<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>2.9.1</version>
</dependency>

zookeepe

<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>${zk.version}</version><exclusions><exclusion><groupId>org.jboss.netty</groupId><artifactId>netty</artifactId></exclusion><exclusion><groupId>log4j</groupId><artifactId>log4j</artifactId></exclusion></exclusions>
</dependency>

1.3 通讯包

netty或者mina, 二选一, 通过 addConfig(“lts.remoting”, “可选值: netty, mina”) 设置

netty

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.0.20.Final</version>
</dependency>

mina

<dependency><groupId>org.apache.mina</groupId><artifactId>mina-core</artifactId><version>2.0.9</version>
</dependency>

1.4 json包

fastjson或者jackson, 二选一, 通过 addConfig(“lts.json”, “可选值: fastjson, jackson”) 设置

fastjson

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.7</version>
</dependency>

jackson

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.6.3</version>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.6.3</version>
</dependency>

1.5 日志包

可以选用 slf4j, jcl, log4j, 或者使用jdk原生logger LoggerFactory.setLoggerAdapter(“可选值: slf4j, jcl, log4j, jdk”), 不手动设置, 默认按这个顺序加载

log4j

<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.16</version>
</dependency>

slf4j

<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.5</version>
</dependency>
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.5</version>
</dependency>

jcl

<dependency><groupId>commons-logging</groupId><artifactId>commons-logging-api</artifactId><version>1.1</version>
</dependency>

1.6

如果需要spring的话,需要引入lts-spring及spring的相关包

<dependency><groupId>com.github.ltsopensource</groupId><artifactId>lts-spring</artifactId><version>${lts版本号}</version>
</dependency>

2. 对于JobTracker端

2.1 必须引入的包:

<dependency><groupId>com.github.ltsopensource</groupId><artifactId>lts-jobtracker</artifactId><version>${lts版本号}</version>
</dependency>

2.2 除了基础包之外还需要引入任务队列的包(可以是mongo或者mysql)

mysql

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.26</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.14</version>
</dependency>

mongo

<dependency><groupId>org.mongodb.morphia</groupId><artifactId>morphia</artifactId><version>1.0.0-rc1</version>
</dependency>
<dependency><groupId>org.mongodb</groupId><artifactId>mongo-java-driver</artifactId><version>3.0.2</version>
</dependency>

3. JobClient需要引入的包

必须引入的包

<dependency><groupId>com.github.ltsopensource</groupId><artifactId>lts-jobclient</artifactId><version>${project.version}</version>
</dependency>

FailStore存储包(四选一)

通过 jobClient.addConfig(“job.fail.store”, “可选值: leveldb, mapdb, berkeleydb, rocksdb”) 设置

mapdb

<dependency><groupId>org.mapdb</groupId><artifactId>mapdb</artifactId><version>2.0-beta10</version>
</dependency>

leveldb

<dependency><groupId>org.fusesource.leveldbjni</groupId><artifactId>leveldbjni-all</artifactId><version>1.2.7<version>
</dependency>

berkeleydb

<dependency><groupId>com.sleepycat</groupId><artifactId>je</artifactId><version>5.0.73</version>
</dependency>

rocksdb

<dependency><groupId>org.rocksdb</groupId><artifactId>rocksdbjni</artifactId><version>3.10.1</version>
</dependency>

3. TaskTracker需要引入的包

必须引入的包

<dependency><groupId>com.github.ltsopensource</groupId><artifactId>lts-tasktracker</artifactId><version>${project.version}</version>
</dependency>

FailStore存储包(四选一)

通过 taskTracker.addConfig(“job.fail.store”, “可选值: leveldb, mapdb, berkeleydb, rocksdb”) 设置

mapdb

<dependency><groupId>org.mapdb</groupId><artifactId>mapdb</artifactId><version>2.0-beta10</version>
</dependency>

leveldb

<dependency><groupId>org.fusesource.leveldbjni</groupId><artifactId>leveldbjni-all</artifactId><version>1.2.7<version>
</dependency>

berkeleydb

<dependency><groupId>com.sleepycat</groupId><artifactId>je</artifactId><version>5.0.73</version>
</dependency>

rocksdb

<dependency><groupId>org.rocksdb</groupId><artifactId>rocksdbjni</artifactId><version>3.10.1</version>
</dependency>

LTS分布式任务调度文档相关推荐

  1. LTS分布式任务调度文档-转载

    转载:https://www.cnblogs.com/dion-90/articles/8674591.html LTS介绍 LTS(light-task-scheduler)主要用于解决分布式任务调 ...

  2. LTS分布式任务调度

    LTS文档 LTS(light-task-scheduler)主要用于解决分布式任务调度问题,支持实时任务,定时任务和Cron任务.有较好的伸缩性,扩展性,健壮稳定性而被多家公司使用,同时也希望开源爱 ...

  3. LTS 分布式任务调度框架- TaskTracker配置自定义分发jobRunner

    1.Spring扫描初始化配置所在包 <context:annotation-config /> <context:component-scan base-package=" ...

  4. Elasticsearch之文档document入门

    6.1. 默认自带字段解析 {"_index" : "book","_type" : "_doc","_id& ...

  5. 基于GitBook框架搭建技术文档平台

    源宝导读:为了向用户更好的传递ERP开放平台的价值与技术知识,我们基于GitBook框架搭建了一个文档中心站点,本文将介绍此站点的设计与实现过程. 一.项目架构图 因为文档会涉及到很多的产品线,所以目 ...

  6. semantic ui中文文档_求你别再用swagger了,给你推荐几个在线文档生成神器

    开局先推荐: Java面试刷题网站​www.javazhiyin.com 前言 最近公司打算做一个openapi开放平台,让我找一款好用的在线文档生成工具,具体要求如下: 必须是开源的 能够实时生成在 ...

  7. 几个在线文档接口生成工具

    好用的在线文档生成工具,具体要求如下: 1.能够实时生成在线文档 2.支持全文搜索 3.支持在线调试功能 4.界面美观 说实话,这个需求看起来简单,但是实际上一点的都不简单. 我花了几天时间到处百度, ...

  8. 编程学习文档 参考资料和文档

     视频编辑论坛 0山猪0的优酷视频空间 - 首页Adobe Premiere Pro CS4的安装与激活方法 - Premiere 软件与插件 - DV视频剪辑论坛 - Powered by Di ...

  9. 推荐几款接口文档生成神器用来代替Swagger

    前言 最近公司打算做一个openapi开放平台,让我找一款好用的在线文档生成工具,具体要求如下: 必须是开源的 能够实时生成在线文档 支持全文搜索 支持在线调试功能 界面优美 说实话,这个需求看起来简 ...

最新文章

  1. python 获取打印的内容并保存到记事本里面
  2. 分布式事务开局第一篇,从数据库事务隔离级别说起
  3. box_sizing
  4. 【Linux】35. python脚本重命名各子目录下的图片
  5. vim 树形目录插件NERDTree安装及简单用法
  6. Spring源码学习:day2
  7. 32MB块意味着比特币现金为大量采用做好准备
  8. 基于超大规模集群的本地存储系统优化
  9. 关于solaris中 crontab -e 出现数字0的解决办法
  10. 201671010129 2016—2017—2 《Java程序设计》Java总结
  11. 十大排序算法——归并排序(C语言)
  12. 设置谷歌浏览器和Edge浏览器为黑色背景
  13. 计算机ppt制作培训心得,ppt培训心得体会总结范文
  14. Navicat操作数据库
  15. Python入门数学类编程——抛物运动
  16. Linux编译QT项目时报错: error: cannot find -lGL 的解决方法
  17. 核心关键词排名优化技巧
  18. 推挽 matlab仿真,推挽电路简单介绍
  19. 你应该了解的工厂方法模式:优雅的代码永不过时
  20. EditPlus使用技巧集

热门文章

  1. ReleaseMutex函数
  2. yolo源码解析(1):代码逻辑
  3. Not all bytes are equal: Neural byte sieve for fuzzing(不是所有字节都是相等的:用于模糊的神经字节过滤)
  4. 5300年前木乃伊冰人奥兹胃内发现野山羊肉(图)
  5. SAP 自动编号工具【SNRO】
  6. Elasticsearch(009):es中index(索引)的新增、修改、删除、关闭等操作
  7. JS中的任务队列(详解)
  8. [3.0.0]性能调优之最大化资源配置
  9. Python神级操作,还原已撤回的微信消息
  10. JZ16 数值的整数次方