tornadoweb / tornado

Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.
http://www.tornadoweb.org/
Apache License 2.0
21.66k stars 5.52k forks source link

v6.1,CPU increased to 100% when the client closes the connection #3401

Closed zhubijia closed 2 months ago

zhubijia commented 2 months ago

My Code : class BaseHandler(RequestHandler): @gen.coroutine def post(self): for i_ in range(0, 300): print("sleep") time.sleep(0.1) self.write("xxx") image

And I start Tornado in multi-process mode. However, when client closes normally(close after more than 30 seconds), it works ok.After analysis with cProfile,I got this picture: image When the client is closed for 5 seconds, it means that the server will continue to execute. CPU increased to 100%: image and I got this picture with cProfile: image It looks like selectors error, Anybody has an idea?

bdarnell commented 2 months ago

I don't think this is related to the 100% cpu, but you should use asyncio.sleep instead of time.sleep (https://www.tornadoweb.org/en/stable/faq.html#id2).

Which version of python are you using?

How exactly are you setting up multi-process mode? I assume both of these profiles are from a child process?

zhubijia commented 2 months ago

I don't think this is related to the 100% cpu, but you should use asyncio.sleep instead of time.sleep (https://www.tornadoweb.org/en/stable/faq.html#id2).

I just use time.sleep to simply represent my real logic, which is actually a slow query of MySQL. If the user feels it is slow and closes the page, the CPU will rise to 100%. If the user is willing to continue waiting, it is normal. I shielded a machine and used requests to set different timeouts of 5s and 40s to simulate request verification, which was consistent with the above performance. When I set the timeout to 5 seconds, the CPU was abnormal while the server continued to execute, and there were no other requests at this time. When the timeout was set to 40s, the CPU was normal, and there were no other requests.

Which version of python are you using?

Python 3.6, in docker environment.

How exactly are you setting up multi-process mode? I assume both of these profiles are from a child process?

app = tornado.web.Application(APP_URLS) http_server = tornado.httpserver.HTTPServer(app, xheaders=True) http_server.listen(8080) http_server.start(num_processes=2)

bdarnell commented 2 months ago

http_server.start is used with http_server.bind, not listen. listen is only for single-process mode and I think it might be able to cause problems like this when used in multi-process mode. Look at the docs for add_sockets multi-process mode in the HTTPServer docs: https://www.tornadoweb.org/en/stable/httpserver.html#tornado.httpserver.HTTPServer (use add_sockets instead of bind/start because bind/start is deprecated for future versions of python)

zhubijia commented 2 months ago

Thanks, I tried the above method and it works fine now!