【发布时间】:2018-01-29 07:49:45
【问题描述】:
我已经构建了一个 Flask 应用程序,它计算图表中的一些路径。通常,这是一项非常贪婪的任务,需要花费大量时间来完成计算。当我忙于配置算法时,我并没有真正关注服务器端的实现。我们已经建立了一个 Nginx 服务器,它为整个事情提供服务器。这是主要的 Flask 路线:
@app.route('/paths', methods=['POST'])
def paths():
form = SampleForm(request.form)
if form.validate_on_submit():
point_a = form.point_a.data
point_b = form.point_b.data
start = form.start.data.strftime('%Y%m%d')
end = form.end.data.strftime('%Y%m%d')
hops = form.hops.data
rendering_time, collections = make_collection(point_a, point_b, start, end, hops)
return render_template(
'result.html',
searching_time=rendering_time,
collections=collections)
else:
logger.warning('Bad form: {}'.format(form.errors))
return render_template('index.html', form=form)
整个计算都在make_collection 方法下。因此,每当用户向server.com/path 发送请求时,他都必须等待,直到该方法完成计算并返回一些内容。这不是一个令人满意的解决方案,有时 Nginx 只是超时。
这个的下一个版本是一个简单的想法,将劳动工作委派给某个线程,然后只向用户返回一个空页面。稍后我们可以使用最新的搜索结果更新页面内容。
@app.route('/paths', methods=['POST'])
def paths():
form = SampleForm(request.form)
if form.validate_on_submit():
point_a = form.point_a.data
point_b= form.point_b.data
start = form.start.data.strftime('%Y%m%d')
end = form.end.data.strftime('%Y%m%d')
hops = form.hops.data
finder = threading.Thread(
target=make_collection,
kwargs={
'point_a': point_a,
'point_b': point_b,
'start': start,
'end': end,
'hops': hops})
finder.start()
rendering_time, collections = 0, []
return render_template(
'result.html',
searching_time=rendering_time
collections=collections)
else:
logger.warning('Bad form: {}'.format(form.errors))
return render_template('index.html', form=form)
上面的代码工作正常,搜索时间可接受(与第一个版本相比没有改变,如预期的那样)。问题是,它只能在我的本地机器上工作。当我将它部署到 Nginx 时,总性能甚至没有接近我的预期。作为比较,我在本地机器上找到的结果在 30 秒以下,Nginx 即使在 300 秒以下也无法完全找到。怎么办?
附:最初,设置 Nginx 服务器不是我工作的一部分,我也不是很熟悉 Nginx 的工作原理,但是如果您需要任何信息,请询问。
【问题讨论】:
-
有多种可能性。最明显的一个:如果
make_collection是一个cpu-bound 任务,那么性能取决于机器上的总可用cpu 功率(这意味着所有活动的进程/线程都试图获得它们的cpu 时间,从而降低了性能)。即使它不受 cpu 限制,它可能仍然会因为机器而变慢,例如,如果您在一台机器上拥有所有东西(即应用程序、数据库、nginx 等)。你检查过吗?您可能还想尝试调试 nginx,即检查延迟是否是由于 nginx(不太可能)或应用程序造成的。 -
另请注意,您所做的事情很糟糕。每个请求都会产生一个新线程。如果我多次调用
/paths,你最终会得到成百上千的后台线程。这也会影响性能。您需要一些队列和一个线程池。只是为了控制生成任务的数量。顺便说一句,您为 Flask 使用什么服务器?乌斯吉?独角兽?生烧瓶(不推荐)?还有什么?
标签: python multithreading nginx flask python-multithreading