控制接口超时的两种方法

需求:当接口耗时比较长,超过 20/30s 时,能够在超时之前返回给前端

在这里主要介绍两种方式:

  • 信号:配合 signal 模块使用(Windows 不支持)
  • 多线程

1. signal 信号

import signal
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/query')
def query():
    # 设置超时时间为20秒
    timeout = 20

    # 设置超时信号处理函数
    def handler(signum, frame):
        raise TimeoutError('Query timed out after {} seconds'.format(timeout))

    # 注册超时信号处理函数
    signal.signal(signal.SIGALRM, handler)

    # 设置超时时间
    signal.alarm(timeout)

    # 查询表数据
    try:
        # 执行查询操作
        result = db.query()

        # 取消超时信号
        signal.alarm(0)

        # 返回查询结果
        return jsonify({'result': result})
    except TimeoutError as e:
        # 查询超时,返回超时信息
        return jsonify({'error': str(e)})
    except Exception as e:
        # 查询出错,返回错误信息
        return jsonify({'error': str(e)})

在上述代码中,首先使用signal.signal()方法注册了一个超时信号处理函数handler。在handler函数中,抛出TimeoutError异常表示超时。然后使用signal.alarm()方法设置了超时时间,这里是20秒。在查询表数据之前,通过signal.alarm(0)方法取消超时信号。如果查询过程中出现异常,也会返回错误信息。

这样,在接口查询表数据时,如果查询时间超过20秒,就会触发超时信号,从而中断接口执行,并返回超时信息。

2. 多线程

采用 signal 信号机制需中断耗时操作,如果想耗时操作继续在后台执行,可以使用多线程方案。

import threading
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/query')
def query():
    # 设置超时时间为20秒
    timeout = 20

    # 获取连接对象
    conn = current_app.config['HIVE_CONNECTION']
    
    # 创建游标对象
    cursor = conn.cursor()

    # 创建线程对象
    hql = params.get("hql", "")
    
    # 启动线程
    query_thread = HiveQueryThread(query_hive, args=(cursor, hql, current_app._get_current_object()))
    query_thread.start()

    # 等待线程结束,超时时间为 20s
    query_thread.join(timeout)

    # 若线程任然在运行,就中断线程并返回超时信息
    if query_thread.is_alive():
        # cursor.cancel_operation()  # 中断 hive 查询 thrift.Thrift.TApplicationException: CancelOperation failed: unknown result

        # 返回超时信息
        return jsonify({'code': 408, 'msg': '执行超过20s,任务进入后台运行!'})

    # 获取查询结果
    results = query_thread.get_result()
    return jsonify({"code": 200, "msg": "success", "data": results})

多线程:

def query_hive(cursor, hql, task_id, current_thread_app):
    """
    hive 查询
    """
    res = []
    try:
        print(f"query: {hql}")
        cursor.execute(hql)
        
        # 获取查询结果
        res = cursor.fetchall()
        print(f"res: {res}")  
    except:
        print(traceback.format_exc())

    return res


class HiveQueryThread(Thread):
    def __init__(self, func, args):
        super(HiveQueryThread, self).__init__()
        self.func = func
        self.args = args

    def run(self):
        self.results = self.func(*self.args)

    def get_result(self):
        """获取结果"""
        try:
            return self.results
        except Exception:
            return []
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风老魔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值