gpt4 book ai didi

python - 樱桃皮 : which solutions for pages with large processing time

转载 作者:太空宇宙 更新时间:2023-11-03 13:44:41 25 4
gpt4 key购买 nike

我有一个由 cherrypy 提供支持的网站。对于某些页面,我需要相当长的处理时间(对数百万行 DB 的多连接 SQL 请求)。处理有时需要 20 秒或更长时间,浏览器会因为太长而崩溃。

我想知道这里有什么好的解决方案。

最佳答案

这里的一切都取决于网站的数量。 CherryPy 是一个线程服务器,一旦每个线程都在等待数据库,新的请求将不会被处理。还有请求队列方面,但一般情况下是这样。

穷人的解决方案

如果您知道自己的流量较小,则可以尝试解决方法。如果需要,增加 response.timeout(默认为 300 秒)。增加 server.thread_pool(默认为 10)。如果您在 CherryPy 应用程序前面使用保留代理,例如 nginx,请同时增加那里的代理超时。

以下解决方案将要求您重新设计您的网站。特别是让它异步,客户端代码发送一个任务,然后使用拉或推来获得它的结果。这将需要改变电线的两侧。

CherryPy 后台任务

您可以使用 cherrypy.process.plugins.BackgroundTask和服务器端的一些中间存储(例如数据库中的新表)。用于拉取的 XmlHttpRequest 或用于推送到客户端的 WebSockets。 CherryPy 可以处理这两者。

请注意,由于 CherryPy 在单个 Python 进程中运行,后台任务的线程也会在其中运行。如果你做一些 SQL 结果集后处理,你会受到 GIL 的影响。 .因此,您可能希望重写它以改用进程,这会稍微复杂一些。

工业解决方案

如果您的网站运行或被认为是大规模运行,您最好考虑像 Rq 这样的分布式任务队列。或 Celery .它使服务器端有所不同。客户端是相同的拉或推。

例子

下面是一个带有 XHR 轮询的 BackgroundTags 的玩具实现。

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import time
import uuid

import cherrypy
from cherrypy.process.plugins import BackgroundTask


config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8,
}
}


class App:

_taskResultMap = None


def __init__(self):
self._taskResultMap = {}

def _target(self, task, id, arg):
time.sleep(10) # long one, right?
try:
self._taskResultMap[id] = 42 + arg
finally:
task.cancel()

@cherrypy.expose
@cherrypy.tools.json_out()
def schedule(self, arg):
id = str(uuid.uuid1())
self._taskResultMap[id] = None
task = BackgroundTask(
interval = 0, function = self._target, args = [id, int(arg)],
bus = cherrypy.engine)
task.args.insert(0, task)
task.start()
return str(id)

@cherrypy.expose
@cherrypy.tools.json_out()
def poll(self, id):
if self._taskResultMap[id] is None:
return {'id': id, 'status': 'wait', 'result': None}
else:
return {
'id' : id,
'status' : 'ready',
'result' : self._taskResultMap.pop(id)
}

@cherrypy.expose
def index(self):
return '''<!DOCTYPE html>
<html>
<head>
<title>CherryPy BackgroundTask demo</title>
<script type='text/javascript'
src='http://cdnjs.cloudflare.com/ajax/libs/qooxdoo/3.5.1/q.min.js'>
</script>
<script type='text/javascript'>
// Do not structure you real JavaScript application this way.
// This callback spaghetti is only for brevity.

function sendSchedule(arg, callback)
{
var xhr = q.io.xhr('/schedule?arg=' + arg);
xhr.on('loadend', function(xhr)
{
if(xhr.status == 200)
{
callback(JSON.parse(xhr.responseText))
}
});
xhr.send();
};

function sendPoll(id, callback)
{
var xhr = q.io.xhr('/poll?id=' + id);
xhr.on('loadend', function(xhr)
{
if(xhr.status == 200)
{
callback(JSON.parse(xhr.responseText))
}
});
xhr.send();
}

function start(event)
{
event.preventDefault();

// example argument to pass to the task
var arg = Math.round(Math.random() * 100);

sendSchedule(arg, function(id)
{
console.log('scheduled (', arg, ') as', id);
q.create('<li/>')
.setAttribute('id', id)
.append('<span>' + id + ': 42 + ' + arg +
' = <img src="http://sstatic.net/Img/progress-dots.gif" />' +
'</span>')
.appendTo('#result-list');

var poll = function()
{
console.log('polling', id);
sendPoll(id, function(response)
{
console.log('polled', id, '(', response, ')');
if(response.status == 'wait')
{
setTimeout(poll, 2500);
}
else if(response.status == 'ready')
{
q('#' + id)
.empty()
.append('<span>' + id + ': 42 + ' + arg + ' = ' +
response.result + '</span>');
}
});
};
setTimeout(poll, 2500);
});
}

q.ready(function()
{
q('#run').on('click', start);
});
</script>
</head>
<body>
<p>
<a href='#' id='run'>Run a long task</a>, look in browser console.
</p>
<ul id='result-list'></ul>
</body>
</html>
'''


if __name__ == '__main__':
cherrypy.quickstart(App(), '/', config)

关于python - 樱桃皮 : which solutions for pages with large processing time,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22630147/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com