You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Channels后端报错:进程关闭超时被终止

Fixing "took too long to shut down and was killed" in Django Channels

Here are the key issues in your code that are likely causing the shutdown timeout, along with corrected implementations:

1. Syntax Error in Connect Handler

Your teacher role block has an orphaned except statement with no corresponding try block. This invalid syntax causes runtime errors that disrupt proper connection lifecycle management.

2. Conflicting Disconnect Handlers

You’ve implemented both a synchronous disconnect method and an asynchronous websocket_disconnect method. For WebsocketConsumer (synchronous), only the disconnect method is needed—having both leads to duplicate cleanup logic and potential hangs.

3. Deprecated Channel Layer Method

group_discard is deprecated; use group_remove instead for removing a channel from a group.

4. Unhandled Exceptions in Disconnect

Database operations in disconnect lack error handling. If a Station or WorkClass doesn’t exist, uncaught exceptions will delay shutdown as the server processes the error.

Corrected WSConsumer Code

import json
from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync
from .models import WorkClass, Station

class WSConsumer(WebsocketConsumer):

    def connect(self):
        self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
        self.stid = self.scope["url_route"]["kwargs"]["stid"]
        self.types = self.scope["url_route"]["kwargs"]["types"]

        self.room_group_name = f"station_{self.room_name}"

        if self.types == "student":
            try:
                workclass = WorkClass.objects.get(workclass_id=self.room_name)
                st = Station.objects.get(id=self.stid)
                if st in workclass.stations.all():
                    st.state = True
                    st.save()
                    async_to_sync(self.channel_layer.group_add)(
                        self.room_group_name, self.channel_name
                    )
                    self.accept()
                else:
                    self.disconnect(10)
            except (WorkClass.DoesNotExist, Station.DoesNotExist):
                self.disconnect(10)
        elif self.types == "teacher":
            try:
                # Optional: Verify workclass exists for teachers
                WorkClass.objects.get(workclass_id=self.room_name)
                async_to_sync(self.channel_layer.group_add)(
                    self.room_group_name, self.channel_name
                )
                self.accept()
            except WorkClass.DoesNotExist:
                raise StopConsumer()
        else:
            raise StopConsumer()

    def disconnect(self, close_code):
        # Remove channel from group
        async_to_sync(self.channel_layer.group_remove)(
            self.room_group_name, self.channel_name
        )
        
        if self.types == "student":
            try:
                st = Station.objects.get(id=self.stid)
                st.state = False
                st.save()
                async_to_sync(self.channel_layer.group_send)(
                    self.room_group_name,
                    {"type": "list_stations", "message": self.room_name, "role": "stations"}
                )
            except Station.DoesNotExist:
                # Skip if station doesn't exist to avoid delays
                pass

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]
        role = text_data_json.get('roles', '')
        types = text_data_json.get('type', '')
        
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {"type": types, "message": message, "role": role}
        )

    # Example group message handler
    def list_stations(self, event):
        message = event["message"]
        self.send(text_data=json.dumps({
            "type": "list_stations",
            "message": message
        }))

Additional Server-Side Tweaks

If the issue persists after fixing code, adjust Daphne’s shutdown timeout:

  • Start Daphne with the --shutdown-timeout flag to increase the allowed shutdown window (e.g., daphne --shutdown-timeout 60 backend.asgi:application).
  • Ensure Redis is running smoothly and there are no connection delays between Channels and Redis.

内容的提问来源于stack exchange,提问作者Ammar Salahi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 10:20:54