-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
all workers are being blocked through the use of Unix sockets #2878
Comments
The issue has nothing to do with the use of your own socket object. The blocking nature is related to two things
Sanic works on the premise of asyncio and therefore you may want to do a little research on how async Python works. Hope this helps. Good luck. |
Hi @ahopkins, thanks for your response. I understand that Python has async/await to handle asynchronous operations. However, it appears normal when modified as follows. In my opinion, this behavior is not normal, and it may have nothing to do with asynchronous operation. import os
import time
from sanic import Sanic, HTTPResponse, Request, response
app = Sanic(__name__)
@app.get("/a")
def base(request: Request) -> HTTPResponse:
print(f"PID: {os.getpid()}")
time.sleep(10)
return response.text("Done")
@app.get("/b")
def fast(request: Request) -> HTTPResponse:
print(f"PID: {os.getpid()}")
return response.text("Fast Done")
if __name__ == '__main__':
app.run(host="127.0.0.1", port=4444, workers=4, debug=True) |
Seems to work as expected, blocks for 10 seconds on /a, blocks until completed on b. Still blocks if async keyword is added because time.sleep() is a blocking call. same behavior over unix socket or tcp. If all workers are exhausted blocking on the /a route call, /b is in a pending state until a worker frees up to handle the route. Can you clarify what you think is broken? |
Demo1: https://imgur.com/OepbE4u Hi @sjsadowski, It's my fault that the first original code snippet had the wrong section. I've edited it and noticed another issue that describes a situation reminiscent of this one: #2467 (comment). I provide two demos using time.sleep(). However, Demo2 differs from Demo1 in that Sanic starts up without a unix socket object. During normal usage, when API B is called after API A, all workers function correctly, and you can observe the printed PID. In Demo1, only a single worker is utilized instead of multiple workers, despite having four workers available. In summary, by replacing the 'unix' parameter with the 'sock' parameter, all workers function correctly. Do you believe this is the expected behavior? app.run(host="127.0.0.1", port=4444, workers=4, unix="/tmp/api.sock", debug=True) -> blocked
app.run(host="127.0.0.1", port=4444, workers=4, sock=sock, debug=True) -> ok
app.run(host="127.0.0.1", port=4444, workers=4, debug=True) -> ok |
I'll have to dig into the connection handler to identify whether that behavior should be expected. If it is, we should document it. I will update after I've had a chance to investigate. |
Is there an existing issue for this?
Describe the bug
In the following code, two APIs using Unix sockets are implemented. API B returns results easily, while API A requires a 10-second wait. When only API B is called, everything appears normal. However, an abnormal behavior is observed when API B is called after API A. Despite having four workers, API A blocks API B.
Demo: https://imgur.com/OepbE4u
Code snippet
Expected Behavior
Everything appears normal when calling API B after API A.
How do you run Sanic?
Sanic CLI
Operating System
Linux
Sanic Version
23.6.0
Additional context
No response
The text was updated successfully, but these errors were encountered: