什么是分布式任务调度
分布式任务调度是指将一个大型任务拆分成多个较小的子任务,并在多台计算机上并行执行这些子任务的过程。在这个过程中,需要一个分布式任务调度系统来协调和管理每个子任务的调度和执行。分布式任务调度系统通常具有以下特点:
-
高可用性:当某个计算节点出现故障时,可以将任务重新分配给其他计算节点执行,以保证任务可以按时完成。
-
可扩展性:可以轻松地添加或删除节点,以满足处理不同规模任务的需求。
-
高效性:可以根据任务的特点和实际情况动态地调整任务的切分和分配方式,以达到更好的任务执行效率。
分布式任务调度系统通常运行在一个集群环境中,同时利用各个计算节点的计算能力来加速任务执行的速度,并且保证任务的可靠性和稳定性。常见的分布式任务调度系统包括Apache Hadoop中的YARN、Apache Spark中的Cluster Manager等。
分布式调度要实现的目标
不管是任务调度程序集成在应用程序中,还是单独构建的任务调度系统,如果采用分布式调度任务的方式就相当于将任务调度程序分布式构建,这样就可以具有分布式系统的特点,并且提高任务的调度处理能力:
1、并行任务调度
并行任务调度实现靠多线程,如果有大量任务需要调度,此时光靠多线程就会有瓶颈了,因为一台计算机CPU的处理能力是有限的。
如果将任务调度程序分布式部署,每个结点还可以部署为集群,这样就可以让多台计算机共同去完成任务调度,我们可以将任务分割为若干个分片,由不同的实例并行执行,来提高任务调度的处理效率。
2、高可用
若某一个实例宕机,不影响其他实例来执行任务。
3、弹性扩容
当集群中增加实例就可以提高并执行任务的处理效率。
4、任务管理与监测
对系统中存在的所有定时任务进行统一的管理及监测。让开发人员及运维人员能够时刻了解任务执行情况,从而做出快速的应急处理响应。
5、避免任务重复执行
当任务调度以集群方式部署,同一个任务调度可能会执行多次,比如在上面提到的电商系统中到点发优惠券的例子,就会发放多次优惠券,对公司造成很多损失,所以我们需要控制相同的任务在多个运行实例上只执行一次。
XXL-JOB
XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
官网
文档
XXL-JOB主要有调度中心、执行器、任务:
调度中心:
负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码;
主要职责为执行器管理、任务管理、监控运维、日志管理等
任务执行器:
负责接收调度请求并执行任务逻辑;
只要职责是注册服务、任务执行服务(接收到任务后会放入线程池中的任务队列)、执行结果上报、日志服务等
任务:负责执行具体的业务处理。
调度中心与执行器之间的工作流程如下:
执行流程:
1. 任务执行器根据配置的调度中心的地址,自动注册到调度中心
2. 达到任务触发条件,调度中心下发任务
3. 执行器基于线程池执行任务,并把执行结果放入内存队列中、把执行日志写入日志文件中
4. 执行器消费内存队列中的执行结果,主动上报给调度中心
5. 当用户在调度中心查看任务日志,调度中心请求任务执行器,任务执行器读取任务日志文件并返回日志详情
什么是模板引擎
模板引擎是一种在Web应用程序中用于生成动态HTML页面的工具。简单来说,它们是将数据和模板混合在一起,以生成HTML的软件组件。模板引擎用来减少页面和代码之间的重复性,以及在服务器端和客户端之间细化数据的传递方式。
在模板引擎中,我们可以使用一系列的语法和控制结构,来生成具有可变内容的HTML页面。最常用的一种语法是变量替换,例如我们可以定义一个变量,并在HTML页面中插入该变量,这样我们可以根据数据的不同动态生成不同的页面。除了变量替换,一些模板引擎还支持循环、条件语句、过滤器等功能,可以更加灵活地控制模板的输出。
常见的模板引擎有很多种,例如Jinja2、mustache、Handlebars、Pug等等。不同的模板引擎具有不同的语法和特性,开发者可以根据自己的需求和喜好来选择合适的模板引擎。
早期我们采用的jsp技术就是一种模板引擎技术,如下图:
1、浏览器请求web服务器
2、服务器渲染页面,渲染的过程就是向jsp页面(模板)内填充数据(模型)。
3、服务器将渲染生成的页面返回给浏览器。
所以模板引擎就是:模板+数据=输出,Jsp页面就是模板,页面中嵌入的jsp标签就是数据,两者相结合输出html网页。
常用的java模板引擎还有哪些?
Jsp、Freemarker、Thymeleaf 、Velocity 等。
什么是页面静态化?
课程预览功能通过模板引擎技术在页面模板中填充数据,生成html页面,这个过程是当客户端请求服务器时服务器才开始渲染生成html页面,最后响应给浏览器,服务端渲染的并发能力是有限的。
页面静态化则强调将生成html页面的过程提前,提前使用模板引擎技术生成html页面,当客户端请求时直接请求html页面,由于是静态页面可以使用nginx、apache等高性能的web服务器,并发性能高。
什么时候能用页面静态化技术?
当数据变化不频繁,一旦生成静态页面很长一段时间内很少变化,此时可以使用页面静态化。因为如果数据变化频繁,一旦改变就需要重新生成静态页面,导致维护静态页面的工作量很大。
根据课程发布的业务需求,虽然课程发布后仍可以修改课程信息,但需要经过课程审核,且修改频度不大,所以适合使用页面静态化。
ThreadPoolTaskExecutor
ThreadPoolTaskExecutor 是 Spring 中的一个线程池管理器,提供了对 Java 线程池的封装和扩展功能。功能强大,使用方便,是异步处理、任务调度等场景下的一个很好的选择。
ThreadPoolTaskExecutor 主要提供以下功能:
-
线程池的创建和配置:可以通过 setCorePoolSize、setMaxPoolSize、setKeepAliveSeconds 等方法,灵活地配置线程池的基本属性,例如线程池大小、线程池类型(固定大小或者弹性大小)、线程存活时间、队列容量等。
-
线程池的调度和管理:通过 execute、submit 等方法,可以向线程池提交任务。对于一些不满足执行条件的任务,如线程池已满、队列已满等,可以通过拒绝策略 RejectedExecutionHandler 处理。ThreadPoolTaskExecutor 提供了四种默认的拒绝策略,分别是 AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy 和 DiscardPolicy。
-
多线程并发处理:ThreadPoolTaskExecutor 可以有效地进行多线程并发处理,提高程序的响应速度和处理能力。通过 setTaskExecutor、setWaitForTasksToCompleteOnShutdown 方法可以对多线程任务进行管理和控制。
ThreadPoolTaskExecutor 深度集成了 Spring 的其他组件,以支持 Spring 的异步任务执行、任务调度等功能,并提供了比较完整的可扩展性和重载方法,可以定制化地实现自定义的线程池调度和管理。
在编写多线程程序时,通常我们应该尽量利用 ThreadPoolTaskExecutor 这样的线程池工具类,来优化线程池性能并简化线程池操作。
ThreadPoolTaskExecutor 和 ThreadPoolExecutor比较
ThreadPoolTaskExecutor 和 ThreadPoolExecutor 都是 Java 中的线程池实现,它们之间有以下几点区别:
-
抽象程度不同: ThreadPoolExecutor 是 Java 标准库提供的线程池实现,而 ThreadPoolTaskExecutor 则是 Spring 框架封装的线程池实现,它在 ThreadPoolExecutor 的基础上做了更高层次的抽象,简化了线程池的配置和管理。
-
功能扩展不同:ThreadPoolTaskExecutor 相比 ThreadPoolExecutor,在任务调度和管理上做了更多的扩展,提供了更多的方便实用的方法供编程者使用。例如,ThreadPoolTaskExecutor 提供了线程池关闭等待任务结束的方法 setWaitForTasksToCompleteOnShutdown,提供了默认的拒绝执行策略,支持异步执行和任务调度等。
-
实例化方式不同:ThreadPoolExecutor 对象可以直接通过 new 关键字进行实例化,而 ThreadPoolTaskExecutor 是 Spring 容器中的一个 Bean,需要在 Spring 配置文件中进行声明和注入。ThreadPoolTaskExecutor 是一个 Spring 管理的单例 Bean,可以通过注入方式在不同程序组件之间共享,提高了线程池的可用性和可重用性。
-
配置方式不同:ThreadPoolExecutor 需要通过 new 关键字手动创建并配置线程池中的各种参数,ThreadPoolTaskExecutor 则提供了更加面向接口的可扩展配置方式,支持通过配置 Bean 属性和设置回调函数来实现配置的灵活和扩展。
综上所述,ThreadPoolTaskExecutor 更适合在 Spring 环境下使用,可以方便地与 Spring 的其他组件集成,简化多线程编程的复杂度和提高代码的可读性、可维护性。而 ThreadPoolExecutor 则更适合在 Java 标准库中使用。