Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request.post to a high latency external URL causes interruption in SocketIO , Running inside Docker. #961

Closed
Fizmath opened this issue Apr 29, 2019 · 11 comments
Labels

Comments

@Fizmath
Copy link

Fizmath commented Apr 29, 2019

Hello dear Miguel ,

Below is the simplified code : the x thread does real-time Posting mydata ( this came from fronted within SocketIo then get processed before POST) to an external website that loads slowly so the whole SocketIo hangs for a second until the POST accomplished . I also used Timeout but the website gets the POST not less than 1 second , i need to send every 1 millisecond .
Anyway , websites might be slow or proxies or whatsoever . How can i POST not blocking the main thread dd ?

api_url = 'https://example.com'
head = {'Connection': 'keep-alive'}

import eventlet
eventlet.monkey_patch()
import threading
requests = eventlet.import_patched('requests.__init__')
.
.

def bg_task():
          ..
        mydata = { ... }


def posting():
             .
             requests.post(api_url, json=mydata, headers=head)

@socketio.on('connect', namespace='/test')
def test_connect():
            dd = socketio.start_background_task(bg_task)
            x = threading.Thread(target=posting,daemon=True)
            x.start()
            print("client connected",request.sid)

.
.
@app.route('/')
def index():
    return render_template('index.html',async_mode=socketio.async_mode)
@miguelgrinberg
Copy link
Owner

First of all, move the monkey patching to the top of your application's main module. You do not need to do the import_patched for requests, the monkey patching should take care of that, so you can do import requests normally.

Besides that I'm not sure what the problem might be. With the monkey patching socket operations become non-blocking so I don't see anything in the code snippet you posted that could cause blocking.

@Fizmath
Copy link
Author

Fizmath commented Apr 29, 2019

Thank you for the instant reply ,

So , there should not be any blocking issue . I'll search for the bottleneck .

Can we yet use asyncio inside that socketio.start_background_task({has async function}) ? or the asyncio also get monkey patched by eventlet ?

@miguelgrinberg
Copy link
Owner

No, eventlet and asyncio are competing async frameworks, they don't work together.

@Fizmath
Copy link
Author

Fizmath commented Apr 30, 2019

Is it possible to emit to an external url ? either from server or fronted , i want to do the following functionality using emit :

api_url = 'https://example.com'
requests.post(api_url, json=mydata, headers=head)

@miguelgrinberg
Copy link
Owner

@Fizmath you can only emit to a Socket.IO server. The code that you pasted above sends an HTTP request, which is a more basic protocol than Socket.IO. Why do you need to use Socket.IO for this? If your server accepts HTTP requests, then use requests.post() as you show above, there is nothing wrong with that.

@Fizmath
Copy link
Author

Fizmath commented Apr 30, 2019

Because this is real-time data analysis : fronted sends streaming data to the server via socket.emit() , afterwards , the flask server do the analysis on the data then sends back to both fronted again through socket.emit() and partly to external url via request.post
But , as i mentioned above when comes to request.post , due to high latency of the external url the whole Gunicorn Eventlet server hangs a little bit ..... despite the fact that it runs on a separate thread

@Fizmath Fizmath changed the title Fast request.post to a slow website not blocking the main thread Fast request.post to a high latency URL not blocking the main thread Apr 30, 2019
@Fizmath
Copy link
Author

Fizmath commented May 2, 2019

Can i use Celery and Redis ... for request.post while the Gunicorn Eventlet is running ?

@miguelgrinberg
Copy link
Owner

Do you have control over this external server? If you do, then add a Socket.IO server there, and then you can emit to it.

@Fizmath
Copy link
Author

Fizmath commented May 11, 2019

No , i can only post to that sluggish external server which causes delay in my server . So , while my server running in Gunicorn Eventlet would't it possible to create asynchronous massage queue with Celery and Redis ?
https://github.com/miguelgrinberg/flack/blob/master/flack/__init__.py#L39-L52

My app runs from Docker image , if yes , i should make docker-compose.yaml , i read this problem also which you kindly had made comments :
https://www.reddit.com/r/flask/comments/9ufidg/socketio_with_celeryredis_on_docker_torture/

What is your suggestion ?

@miguelgrinberg
Copy link
Owner

@Fizmath there are a hundred different ways to do this. Yes, you can use Celery, you can also use a child process, or a background thread. Regardless, sending a post request from an eventlet app is non-blocking, so your server should be operational. If you don't want to delay the response to your client, then start a background task and do it from there. Something like this:

socketio.start_background_task(posting)

That is as non-blocking as using Celery, etc.

@Fizmath Fizmath changed the title Fast request.post to a high latency URL not blocking the main thread Request.post to a high latency external URL causes interruption in SocketIO , Running inside Docker. May 13, 2019
@Fizmath
Copy link
Author

Fizmath commented May 13, 2019

SOLVED ! :

I found the solution . I did not mention that i ran the code inside Docker , when i launched the program without Docker , the request.post'ing out of Flask-SocketIO did not hinder the main thread . After lots of digging i found a similar problem :

https://github.com/kennethreitz/requests/issues/3948

from there , i degraded the libraries in my requirements.txt to :

requests==2.7.0
cryptography==1.9
pyOpenSSL==17.4.0

then rebuilt and launched the docker image and the request.post went smoothly .

Anyway , thank you Miguel for your kind remarks and instant replies . I changed the title for those who google .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants