Как заставить CherryPy обслуживать одновременные запросы?

Я читал, что Cherpy использует собственный пул потоков. Но я не вижу в этом преимущества.

Допустим, я запускаю запрос, который займет много времени, а затем на другой вкладке я запускаю запрос, который займет короткое время. Если он действительно использует многопоточность, короткий запрос должен завершиться раньше длинного. Но я вижу, что сначала выполняется длинный запрос, а затем короткий, как будто все обрабатывается последовательно.

Я пытался интегрироваться с различными фреймворками uWSGI, такими как Tornado и Twistd, но все равно не вижу разницы. http://cherrypy.readthedocs.org/en/latest/deploy.html#tornado

Это мой стартовый код. Может кто-нибудь помочь мне здесь?

cfg = {
'global' : {
  'server.socket_host' : Utils.gflags.FLAGS.bind_addr,
  'server.socket_port' : Utils.gflags.FLAGS.bind_port,
  'server.thread_pool' : 10,
  'engine.timeout_monitor.frequency' : gflags.FLAGS.request_time_out_secs,
},
'/static' : {"tools.sessions.on": False, 'tools.auth.on': False},
'/favicon.ico' : {"tools.sessions.on": False, 'tools.auth.on': False},
}

# To turn off the cherrypy errors on screen.
cfg['global'].update({'log.screen': False})
cfg['/static'].update({'tools.staticdir.on': True})
cfg['/static'].update({'tools.staticdir.dir': Utils.gflags.FLAGS.static_dir})
cfg['/favicon.ico'].update({'tools.staticfile.on': True})
cfg['/favicon.ico'].update({'tools.staticfile.filename':
                          Utils.gflags.FLAGS.favicon_file})


# Disable the auto reload on code change.
cherrypy.engine.autoreload.unsubscribe()

# Start the cherrypy
#Root() is defined somewhere else. Don't worry about that
cherrypy.quickstart(Root(), config = cfg)

person Agniva De Sarker    schedule 28.01.2015    source источник
comment
Привет. Вы уверены, что браузер использует другое соединение на второй вкладке? Он может просто повторно использовать первый, что означает последовательное выполнение обоих запросов.   -  person Sylvain Hellegouarch    schedule 28.01.2015
comment
Что ж, то, что вы говорите, кажется правильным. Но мне действительно нужен параллелизм на уровне запроса, а не на уровне соединения. Отключение сеансов может быть способом, я проверю.   -  person Agniva De Sarker    schedule 29.01.2015
comment
Связанный? stackoverflow.com/questions/21758014/   -  person jwalker    schedule 31.01.2015


Ответы (2)


Да, похоже, у вас возникла та же проблема, что и в этом сообщении блога о блокировке сеанса: http://blog.schmichael.com/2007/09/20/session-locking-and-performance-in.-cherrypy/

В основном решение состоит в том, чтобы явно заблокировать ваши сеансы в другой точке кода, где он не будет блокировать все другие запросы.

cherrypy.session.acquire_lock()
cherrypy.session.release_lock()
person Isa Hassen    schedule 29.01.2015
comment
Спасибо. В этом была проблема. Ух ты, какую тонкую вещь можно упустить, и какое большое влияние она производит! - person Agniva De Sarker; 29.01.2015

Я вижу, что вы отключаете инструмент сеанса для статических файлов, поэтому я предполагаю, что блокировка вызвана блокировкой сеансов, проверьте документация, связанная с блокировкой сеанса.

Этот пример может быть показательным:

"""Show the difference between explicit and implicit locking
on the cherrypy sessions.

To see the effects make sure your client can handle cookies,
for example any conventional web browser or curl with
a cookie jar.

The exposed routes are:

   /e/
   /e/block/[minutes]
   /e/blocked_hi/
   /e/unblocked_hi
   /i/
   /i/block/[minutes]
   /i/blocked_hi/
   /i/unblocked_hi

The application mounted on /e/ has the sessions *explicitly* locked and
the applicaiton mounted on /i/ has the sessions *implicitly* locked.

You can make any concurrent request on the /e branch and you
will not have any blocking.

If you do the requests on the following steps:
  1. /i/
  2. /i/block
  3. /i/blocked_hi

The step 3 is going to be blocked because of the step 2, you can wait a minute
and when the request on step 2 ends it will inmediatly complete the step 3.
Also any request that you do to /i/unblocked_hi will respond immediately regardless
of any blocking.

In general if you call:

 1. /i/ or /e/ and then
 2. /i/block
 3. Any request to:
        /i/
        /i/blocked_hi
        /e/
    are going to be blocked in until /i/block finish.
"""
import time

import cherrypy as cp


class _App:

    @cp.expose
    def block(self, m=1):
        """Sleep for `m` minutes and return."""
        time.sleep(float(m) * 60)
        return "I have blocked this request {}".format(m)

    @cp.expose
    def blocked_hi(self):
        """It can be blocked if the blocked method is executing,
        the session have content and is locked.
        """
        return """Hi, I could have been blocked by a session.
        Session content: {}\n""".format(dict(cp.session))

    @cp.expose
    def unblocked_hi(self):
        return "Hi, I'm not blocked!"


class ImplicitlyLockedApp(_App):

    @cp.expose
    def index(self):
        cp.session['foo'] =  'bar'
        return "I've just set the session content to {}".format(dict(cp.session))


class ExplicitlyLockedApp(_App):

    @cp.expose
    def index(self):
        # This method can be blocked by /i/block because of the
        # acquire_lock/release_lock calls.
        cp.session.acquire_lock()
        cp.session['foo'] =  'bar'
        cp.session.release_lock()
        return "I've just set the session content to {}".format(dict(cp.session))


if __name__ == '__main__':
    cp.tree.mount(ImplicitlyLockedApp(), '/i', config={
        '/': {
            'tools.sessions.on': True
        },
        '/unblocked_hi': { # Disable the session tool to avoid any locking
            'tools.sessions.on': False
        }
    })
    cp.tree.mount(ExplicitlyLockedApp(), '/e', config={
        '/': {
            'tools.sessions.on': True,
            'tools.sessions.locking': 'explicit' # This is the magic bit.
        },
        '/unblocked_hi': { # Rather irrelevant on this case
            'tools.sessions.on': False
        }
    })
    cp.engine.start()
    cp.engine.block()
person cyraxjoe    schedule 29.01.2015
comment
Спасибо, отключу сеансы и посмотрю, как пойдет. - person Agniva De Sarker; 29.01.2015