在web服务下是否可以启用定时任务? 在2021年的时候其实就有这个疑问了,当时也没有去验证,今天找了个时间测试了一下,结果是可行的,就是程序结构设计会比较麻烦一些。 验证方法其实很简单,写一个简单的web接口和定时任务,然后将两者放在一块,同时启动,查看定时任务的结果是否可以输出以及web接口是否可以访问即可
第一次测试时直接将两个任务同时启动,结果是那个任务在前,就会只执行那个任务,简单排查后考虑是线程阻塞,具体原因其实还是需要继续排查,因为如果是不启动web服务,同时启动别的任务时,不会出现线程阻塞。这个是原来已经测试过的结果。如果以上述两个结果来做对比,应该是可以说明问题来自于线程阻塞。在这里也猜测web服务会把一整个进程占用。因为在python中多线程实际上是一个线程执行结束后又去执行另外一个线程。关于使用多线程去启动,在这里其实还未进行相关测试,可以尝试一下。 多线程测试完成后发现手动启用多线程其实也是不可以的。只会有一个任务运行,而且是只有web服务在运行。应该是web服务占用了一整个进程。 如果是启用多个进程来处理的话,在这里已经经过测试,发现是可行的。任务可以同时运行了,多进程其实有好处也有坏处,好处是并发处理,cpu利用率会增加,但是坏处就是对于任务的控制需要更加精细。常规的我们不去指定进程和线程,操作系统会主动去处理,这是操作系统本身的机制所决定的,我们就没有必要去处理并发和并行所带来的一些问题。降低了开发难度。
在这里附一下代码吧,防止后续遇到类似任务,就不必再次进行模拟。 from flask import Flask,request import requests import json import datetime from multiprocessing import Process from threading import Thread from apscheduler.schedulers.blocking import BlockingScheduler scheduler = BlockingScheduler()
app = Flask(__name__)
@app.route('/index/<int:id>',methods=['POST','GET']) def get_data(id): ? ? if request.method == 'POST': ? ? ? ? # a = request.get_data() ? ? ? ? # print(json.dumps(str(a))) ? ? ? ? # b = request.data.decode('utf-8') ? ? ? ? # print(json.dumps(b)) ? ? ? ? # print(type(b)) ? ? ? ? # url = 'http://127.0.0.1:8000/index' ? ? ? ? # resutl = requests.post(url).content.decode('utf-8') ? ? ? ? # print(a) ? ? ? ? # print(resutl) ? ? ? ? return 'hello post' ? ? else: ? ? ? ? # a = request.args ? ? ? ? # print(a) ? ? ? ? print(id) ? ? ? ? return 'hello get' ? ? # return 'hello world'
def print_time(): ? ? data = datetime.datetime.now().strftime('%H:%M:%S') ? ? print(data)
def contral(): ? ? scheduler.add_job(print_time,'interval',seconds=5) ? ? scheduler.start()
def web_run(): ? ? app.run()
def multip(): ? ? # t = Process(target=web_run) ? ? # t1 = Process(target=contral) ? ? t = Thread(target=web_run) ? ? t1 = Thread(target=contral) ? ? # t.join() ? ? # t1.join()
? ? t.start() ? ? t1.start()
if __name__ == '__main__': ? ? # app.run() ? ? # scheduler.add_job(print_time,'interval',seconds=5) ? ? # scheduler.start() ? ? # print_time() ? ? multip() ?
同时启动多个任务,其实在flask本身提供了对应的定时任务模块,在这里没有进行相关的模拟,也许使用框架本身的定时任务,可能会使代码结构更加简洁,在这里就不做相关的模拟了。因为工具本身,原理大同小异,一般来说我们更多关注的是实现。当然,这是就目前而言。因为当开发进行到某种程度,效率和资源都要进行优化的时候,就需要去考虑了。
在这里其实还有一个重点要去说明,app.run不可以直接放在指定进程中启动,尝试了一下,发现会报错,具体原因也没有做过多的排查,可能是target参数中,函数不可以带括号,而app.run()中入参可以省略,但是如果需要添加参数时就会造成不可添加的问题了。
|