-
-
Notifications
You must be signed in to change notification settings - Fork 800
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
Idle database connections not reaped #871
Comments
@michaelhays If you want to verify this would fix it, you can try calling |
End of the consumer method: # consumers.py
class ChatbotConsumer(JsonWebsocketConsumer):
def connect(self):
self.accept()
def receive_json(self, content):
# create Chat in scope if one doesn't exist
if 'chat' not in self.scope:
chat = Chat.objects.create_chat(self.scope['user'])
self.scope['chat'] = chat
# process chatbot response, store messages, and send response to client
response_data = some_func(content['message'])
self.scope['chat'].add_message(content['message'])
self.scope['chat'].add_message(response_data)
self.send_json(response_data)
close_old_connections() End of the model method: # models.py
class Chat(models.Model):
body = JSONField()
...
def add_message(self, message):
self.body.append(message)
self.save()
close_old_connections() Setting |
Probably need the startup method connected as well. I'll look into it more tomorrow when I have time to work on Channels! |
OK, I have replicated this, and the temporary workaround is calling Working on a proper fix now. |
OK, this should be fixed in 6afd423 - any code inside of a If someone could confirm this fixes it for them, I can close this. |
Confirmed to fix the issue for me! |
Great! I'll put this out in a release in the next day or two, depending on what else I land. |
Hey, @andrewgodwin ! I'm steel having the same problem. And it's not only about consumer. I was following your tutorial (multichat). I have database_sync_to_async decorator that covers get_room_or_error in chat.utils. The main thing is that every page refresh (not only chat page) creates new database connection! Django + PostgreSQL + Daphne + Heroku |
If you can reduce it to a simple set of code that reliably reproduces the problem, using the latest versions of all of the repositories, then please open a new issue with that code snippet, and steps to replicate locally (I can't debug things that only happen in Heroku) |
It's exact same issue as @michaelhays described at django/daphne#163. In my case there is no such issue in local but it is in Heroku. |
I just recreated everything on your clear multichat example here and deployed to heroku https://django-channels-2-test.herokuapp.com/ (user: demo, pass: demo) and get same issue. Refresh page 20 times and you'll get
|
Can you confirm what exact versions of each channels package you're running using a |
Looks like packages in heroku are exactly the same as in local env... And yes, the problem only appears at Heroku, works fine at local though... |
Unless I can replicate it locally I'm afraid I can't fix it, sorry - I'm not sure what's different about the Heroku environment that would cause this. |
Hmmmm |
Same issue, Django + PostgreSQL + Daphne + Heroku. Originally had this issue with the consumers, but was fixed with the prior release. On any DB lookup within the Django app, postgres connections are left idle and never close. This occurs on any DB lookup, not the very narrow area where I use channels. Relevant versions: One additional item, I verified that these idle connections don't close after the conn_max_age 500 second have elapsed. db_from_env = dj_database_url.config(conn_max_age=500) UPDATE: Perhaps this article provides a clue: https://devcenter.heroku.com/articles/forked-pg-connections |
what happens if you drop |
I was experiencing the exact same problem @burcaw described. I can confirm @kennethreitz, dropping |
✨🍰✨ |
Hello, I have encountered the same issue as @burcaw , Nginx + Uwsgi(WSGI Layer) + Daphne (only ASGI Layer), I have already updated all packages to latest ones, but even when I dropped Is there any workaround for current issue? Thanks in advance |
If you are still having the issue it means you are using code that talks to a database outside of |
Thanks for your reply, I have double checked my code and didn`t found any database access in methods without database_sync_to_async decorator. So the problem was in my server configuration and
P.S Maybe it can be usefull to add some info about Also one more question, while load testing with an external tool, sometimes I get
Is it a channels issue or just some problem in testing tool, that it doesn`t close the connections properly to ws? |
For me, the only thing that worked was setting |
Daphne and Channels both don't have enough visibility into the threadpool system to close any connections in there, sadly. This is something that has to be remedied in Django itself, which I am in the process of. |
I removed
|
Any update with this issue? @andrewgodwin |
@LgArcida It's a big project. The first steps are made here: https://github.com/django/deps/blob/master/draft/0009-async.rst |
For those who keep finding this issue, here's what I did:
I then was able to send 1,000 messages through my channels code on Heroku and it all worked fine (previously I would have issues after 20-30 messages). |
I have to say I'm still a little confused by this issue, even though setting Where am I supposed to use
Where does |
I was having this problem with channels and heroku postgres but it seems to have resolved itself when I changed my runtime from 3.6 to 3.8.1. I don't need to use close_old_connections() |
@Paulcappaert I don’t suppose we have any idea what changed there do we? |
@carltongibson No idea, all I know is that I made that single change and the problem went away. |
Hmmm. Yes... 🙂 Thanks for the follow-up. (asyncio is changing rapidly, still, but 🤷♂️) |
which change do you perform so problem went away ? |
I updated the runtime to python 3.8.1 |
ok thanks, i also updated runtime to python 3.8.2 and done |
You now what? i was struggling from last two days on this stupid error. I am glad you fixed it. Thanks a lot. I am really happy |
I'm happy to see @Paulcappaert's suggestion to switch runtimes helped some here, unfortunately for some of us that's impossible as we may be using other libraries that don't support 3.8 yet. I for one rely on Celery for background processing and cannot really update. |
For what it's worth, merely getting off of 3.6 may be enough - asyncio was a little underbaked in 3.6, and is much better in 3.7, and so most issues just need 3.7, not 3.8. |
OK, just a heads up that from my experience - that's not true. I was (and still am) using Channels 1, and when I upgraded to Python 3.7.2 to enjoy a Celery feature, I also had to upgrade to Channels 2 (all sorts of dependency clashes). That's when I encountered this issue again, and reverted my whole setup so Channels 2 didn't kill my server. I am hoping to give this upgrade another chance soon enough, after multiple failed attempts. I'm hosted at Heroku; YMMV. |
Channels 2 versus Channels 1 is a very different conversation given that they use completely different asynchronous styles under the hood. Generally, this issue is caused by Django not identifying the connections with threads or coroutines that are already-dead. For Django itself this was fixed in the latest |
Let me clarify. Maybe I shouldn't have mentioned Channels 1 at all. What I was talking about is Channels 2 on Python 3.7.2, it's why I had to revert back to Channels 1, which is working perfectly fine. |
I'm using Python 3.7.6 on heroku. My main server runs fine on with guinicorn. I observed this issue when I run daphne on my dev server. On my dev server, I incorporated Channels 2 + Websocket and daphne into my app and saw this issue whenever I refreshed my page. I changed my app to use AJAX instead and still see this issue. I only have one view function that return JSONresponse for the AJAX call. That AJAX view function was decorated with 'login_required' and a database update. So i did the following: Using AJAX + daphne:
Using websocket(Channels2) + daphne
I looked at the heroku logs and found that in all instances, the fatal occurred when Django was doing session validation. I don't observe this behavior on my main server when I refresh the login_required view 20+ times. My main server uses guinicorn.
I believe that Django session management is causing this issue when I use daphne. When either Django View or a WebSocket consummer requires validation, a connection is opened to the DATABASE but it never closes. This behavior is not apparent on the local machine because we don't have the limitation on database connection. |
Hi. Are you able to reproduce on a laptop, or only on Heroku? (That still seems to be the issue...) |
I only observe this behavior on heroku. I don't know how to limit database connection on my laptop. |
Hey i fixed this by changing my heroku runtime to python 3.8. This fixed the issue. So, it is worth trying. |
I switched to 3.8 and it has fixed my issue. That was very helpful, thank you. |
So glad I found this thread. Just chiming in here - the following manifested this behavior:
Dropping I haven't tried upgrading Python yet, but I should do that and report back. |
Fix bug in live updates.
Initially reported in django/daphne#163
I suspect this is due to the lack of calling close_old_connections, as seen in Channels 1 here: https://github.com/django/channels/blob/1.x/channels/signals.py#L10
The text was updated successfully, but these errors were encountered: