0

I developed an API with Bottle and some requests takes long time to send the response, the problem is if during this time I send another short request, I have to wait until the first request is finished.

Here is an example :

from gevent import monkey
monkey.patch_all()
from bottle import route, run


@route('/test', method='GET')
def test():
    return 'hello'


@route('/loop', method='GET')
def loop():
    for i in range(0, 1000000000):
        a = 0


if __name__ == '__main__':

    run(host='127.0.0.1', port=45677, debug=True, server='gevent')

If you run /loop and then /test you will have to wait until the /loop is finished to get the /test response.

I tried with many server, always the same problem.

What I'm doing wrong ? Thank you for your help.

Julien
  • 357
  • 2
  • 11

1 Answers1

0

You need to understand the async approach. For instance with gevent async doesn't mean multithreaded, so anything that requires CPU will still block. But this is great for stuff that relies on IO, like SQL queries.

So inside your for loop since that is merely cpu bound you will block until it's over unless you provide a sleep condition to allow other contexts to run during the process.

import gevent
from gevent import monkey,spawn as gspawn, sleep as gsleep, socket, signal_handler as sig
monkey.patch_all()
import signal
from bottle import Bottle, static_file, get, post, request, response, template, redirect, hook, route, abort
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler


def sample():
    gspawn(myfunc)


@get('/')
def app():
    return 'Hello World!'

@get('/test')
def test():
    return 'hello'

@route('/loop')
def loop():
    for i in range(0, 1000000000):
        gsleep(0)
        a = 0

 if __name__ == '__main__':
    botapp = bottle.app()
    server = WSGIServer(("0.0.0.0", int(port)), botapp , handler_class=WebSocketHandler)
    def shutdown():
        print('Shutting down ...')
        server.stop(timeout=60)
        exit(signal.SIGTERM)
    sig(signal.SIGTERM, shutdown)
    sig(signal.SIGINT, shutdown)
    server.serve_forever()
eatmeimadanish
  • 3,809
  • 1
  • 14
  • 20
  • Thank you for your help, it works with the test code, but not with my API, I have to do ```gevent.sleep(0.001)```. There is an other solution with multithreaded ? I tried to create a process for the loop function with ```multiprocessing.Process()``` but it was the same problem. – Julien Oct 13 '20 at 09:04
  • It not solve the problem if in my loop function I have a long MySQL requests :/ – Julien Oct 13 '20 at 12:28
  • Are you spawning new contexts for your requests? Long SQL queries will not block if you are using a threaded connection to MYSQL – eatmeimadanish Oct 13 '20 at 15:42
  • I use this for postgres: https://stackoverflow.com/questions/48532301/python-postgres-psycopg2-threadedconnectionpool-exhausted/49366850#49366850 – eatmeimadanish Oct 13 '20 at 15:43
  • I'm using MySQLdb, I will check about contexts, thank you – Julien Oct 14 '20 at 11:08