У меня есть веб-приложение Tornado, это приложение может получать запросы GET и POST от клиента.Как получить несколько запросов в приложении Tornado
Запрос POSTs отправляет информацию, полученную в очередь Tornado Queue, затем я вывожу эту информацию из очереди, и с ней я выполняю операцию в базе данных, эта операция может быть очень медленной, это может занять несколько секунд!
Тем временем, когда эта операция с базой данных продолжается, я хочу иметь возможность получать другие POST (которые помещают другую информацию в очередь) и GET. GET вместо этого очень быстро и должны немедленно возвращать клиенту их результат.
Проблема в том, что когда я выхожу из очереди и медленная операция начинается, сервер не принимает другие запросы от клиента. Как я могу это решить?
Это код, который я упрощенный написал до сих пор (импорт опущены для избегайте стен текста):
# URLs are defined in a config file
application = tornado.web.Application([
(BASE_URL, Variazioni),
(ARTICLE_URL, Variazioni),
(PROMO_URL, Variazioni),
(GET_FEEDBACK_URL, Feedback)
])
class Server:
def __init__(self):
http_server = tornado.httpserver.HTTPServer(application, decompress_request=True)
http_server.bind(8889)
http_server.start(0)
transactions = TransactionsQueue() #contains the queue and the function with interact with it
IOLoop.instance().add_callback(transactions.process)
def start(self):
try:
IOLoop.instance().start()
except KeyboardInterrupt:
IOLoop.instance().stop()
if __name__ == "__main__":
server = Server()
server.start()
class Variazioni(tornado.web.RequestHandler):
''' Handle the POST request. Put an the data received in the queue '''
@gen.coroutine
def post(self):
TransactionsQueue.put(self.request.body)
self.set_header("Location", FEEDBACK_URL)
class TransactionsQueue:
''' Handle the queue that contains the data
When a new request arrive, the generated uuid is putted in the queue
When the data is popped out, it begin the operation on the database
'''
queue = Queue(maxsize=3)
@staticmethod
def put(request_uuid):
''' Insert in the queue the uuid in postgres format '''
TransactionsQueue.queue.put(request_uuid)
@gen.coroutine
def process(self):
''' Loop over the queue and load the data in the database '''
while True:
# request_uuid is in postgres format
transaction = yield TransactionsQueue.queue.get()
try:
# this is the slow operation on the database
yield self._load_json_in_db(transaction)
finally:
TransactionsQueue.queue.task_done()
Кроме того, я не понимаю, почему, если я делаю 5 в ряде, он положил все пять данных в очереди, хотя максимальный размер равен 3.
Да, я использую psycopg2 для доступа к базе данных. Я попытаюсь использовать «ThreadPoolExecutor», кажется, это самая простая вещь. Вопрос: если я использую драйвер db для торнадо (momoko или запросы), '_load_json_in_db' всегда должен быть сопрограммой? – k4ppa
Исправить; любая функция в приложении Tornado, выполняющая операции ввода-вывода, должна быть написана асинхронно, то есть она должна быть сопрограммой, или она должна выполнить обратный вызов, который будет выполнен позже с результатом ввода-вывода. –