Python 如何使用Gunicorn for Flask API接受并发请求?

Python 如何使用Gunicorn for Flask API接受并发请求?,python,flask,concurrency,gunicorn,Python,Flask,Concurrency,Gunicorn,我想接受对Flask API的多个并发请求。API目前正在通过POST方法获取“公司名称”,并调用爬虫引擎,每个爬虫过程需要5-10分钟才能完成。我想为不同的请求并行运行多个爬虫引擎。我跟着,但没能让它工作。目前,第二个请求正在取消第一个请求。如何实现这种并行性 当前API实现: app.py app = Flask(__name__) app.debug = True @app.route("/api/v1/crawl", methods=['POST']) def crawl_end_po

我想接受对Flask API的多个并发请求。API目前正在通过
POST
方法获取“公司名称”,并调用爬虫引擎,每个爬虫过程需要5-10分钟才能完成。我想为不同的请求并行运行多个爬虫引擎。我跟着,但没能让它工作。目前,第二个请求正在取消第一个请求。如何实现这种并行性

当前API实现:

app.py

app = Flask(__name__)
app.debug = True

@app.route("/api/v1/crawl", methods=['POST'])
def crawl_end_point():
    if not request.is_json:
        abort(415)

    inputs = CompanyNameSchema(request)
    if not inputs.validate():
        return jsonify(success=False, errros=inputs.errors)

    data = request.get_json()
    company_name = data.get("company_name")
    print(company_name)
    if company_name is not None:
        search = SeedListGenerator(company_name)
        search.start_crawler()

        scrap = RunAllScrapper(company_name)
        scrap.start_all()
        subprocess.call(['/bin/bash', '-i', '-c', 'myconda;scrapy crawl company_profiler;'])
    return 'Data Pushed successfully to Solr Index!', 201

if __name__ == "__main__":
    app.run(host="10.250.36.52", use_reloader=True, threaded=True)
gunicorn.sh

#!/bin/bash
NAME="Crawler-API"
FLASKDIR=/root/Public/company_profiler
SOCKFILE=/root/Public/company_profiler/sock
LOG=./logs/gunicorn/gunicorn.log
PID=./guincorn.pid

user=root
GROUP=root

NUM_WORKERS=10 #  generally in the 2-4 x $(NUM_CORES)+1 range
TIMEOUT=1200
#preload_apps = False

# The maximum number of requests a worker will process before restarting.
MAX_REQUESTS=0


echo "Starting $NAME"

# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

# Start your gunicorn
exec gunicorn app:app -b 0.0.0.0:5000 \
  --name $NAME \
  --worker-class gevent \
  --workers 5 \
  --keep-alive 900 \
  --graceful-timeout 1200 \
  --worker-connections 5 \
  --user=$USER --group=$GROUP \
  --bind=unix:$SOCKFILE \
  --log-level info \
  --backlog 0 \
  --pid=$PID \
  --access-logformat='%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s' \
  --error-logfile $LOG \
  --log-file=-

提前谢谢

更好的方法-将作业队列与Redis或类似工具一起使用。 您可以为作业创建队列,获取结果,并通过API请求组织与前端的交换。每个作业都将在单独的进程中工作,而不会卡住主应用程序。在另一种情况下,您需要解决每一步都存在瓶颈的问题

良好的实现——RQlib或RQfoRedis

  • Redis的启动实例(我正在使用docker)
  • 这样写你自己的工人:
  • 导入redis
    从rq导入工作程序、队列、连接
    listen=['high','default','low']
    redis_url=os.getenv('REDISTOGO_url','redis://localhost:6379')
    conn=redis.from_url(redis_url)
    如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
    带连接(conn):
    worker=worker(映射(队列,侦听))
    工人工作
    
  • 通过烧瓶或控制台启动工人(更适合调试过程) 并在队列中创建作业并控制结果
  • 从redis导入redis
    从rq导入队列
    q=队列(连接=Redis())
    def爬网_端点()
    ... 
    #将任务添加到队列
    结果=q.enqueue(爬网结束点,超时=3600)
    #保存作业id的最简单方法
    会话['j_id']=result.get_id()
    #获取工作状态
    job=job.fetch(会话['j_id'],连接=conn)
    作业。获取_状态()
    #取得工作成果
    工作结果
    
    此外,您还可以检查芹菜,以便:

    安装gevent时,我没有指定版本。所以很可能是最新版本。