Django生产环境API响应时快时慢问题排查求助
问题描述
我有一个以提供API为核心的Django应用,包含三个URL:
api/:从数据库渲染数据test/:仅返回HttpResponse("Done")的测试页insert/:向数据库插入数据
该应用在开发环境响应速度正常(255ms),但在生产环境中有时快(260ms),多数时候极慢(30-40秒),甚至加载仅显示单个单词的test页面也是如此。请问该问题是与代码相关还是托管服务商相关?
补充信息:
- 前端使用React,路由为
mainsite.com/home - 后端使用子域名
api.mainsite.com/api或api.mainsite.com/insert
相关代码
抽象模型类(Equipment和Machine模型与此类似)
class Device(models.Model): class Meta: abstract = True gas1 = models.FloatField() gas2= models.FloatField() gas3= models.FloatField() gas4= models.FloatField() gas5= models.FloatField() gas6= models.FloatField() humidity = models.FloatField() temperature = models.FloatField() created_datetime = models.DateTimeField(auto_now_add=True, null=True) display_datetime = models.DateTimeField(null=True, db_index=True) def save(self, *args, **kwargs): super(Device, self).save(*args, **kwargs) time = f"{str(self.created_datetime.date())}{(format(self.created_datetime.hour,'02d'))}:{(format(self.created_datetime.minute // 5 * 5, '02d'))}:00" formatt = "%Y-%m-%d%H:%M:%S" self.display_datetime = datetime.datetime.strptime(time, formatt) super(Device, self).save(*args, **kwargs)
序列化器(Equipment和Machine序列化器与此类似)
class Deviceserializer(serializers.ModelSerializer): class Meta: model = Device fields = [ "id", "name", "room", "deviceName", "total gas", "gas1", "gas2", "gas3", "gas4", "gas5", "gas6", "humidity", "temperature", "method1", "method2", "method3", "method4", "method5", "method6", "slug", "display_datetime", ]
视图
@api_view(["GET"]) def getData(request): device_101 = device_101.objects.last() device_102 = device_102.objects.last() device_103 = device_103.objects.last() device_104 = device_104.objects.last() device_105 = device_105.objects.last() device_106 = device_106.objects.last() device_108 = device_108.objects.last() device_109 = device_109.objects.last() device_110 = device_110.objects.last() device_111 = device_111.objects.last() device_112 = device_112.objects.last() device_113 = device_113.objects.last() device_114 = device_114.objects.last() device_115 = device_115.objects.last() device_116 = device_116.objects.last() device_124 = device_124.objects.last() device_125 = device_125.objects.last() device_126 = device_126.objects.last() device_127 = device_127.objects.last() device_128 = device_128.objects.last() device_129 = device_129.objects.last() device_130 = device_130.objects.last() list_device = [ device_101, device_102, device_103, device_104, device_105, device_106, device_108, device_109, device_110, device_111, device_112, device_113, device_114, device_115, device_116, device_124, device_125, device_126, device_127, device_128, device_129, device_130, ] serialzer_device = Deviceserializer(list_device, many=True) serializer_machine = machineserializer(list_machine, many=True) serializer_equipment = equipmentserializer(list_equipment, many=True) return Response( { "device": serialzer_device.data, "equipment": serializer_equipment.data, "machine": serializer_machine.data, } )
回答
结论:优先排查托管服务商/基础设施问题,同时优化代码中的低效点
一、为什么怀疑托管服务商/基础设施问题?
你的test/页面完全不涉及数据库或复杂逻辑,只是返回简单字符串,但生产环境依然会出现极慢的情况。开发环境响应稳定,生产环境波动极大(从260ms到30-40秒),这种无规律的响应延迟通常和代码本身无关,更可能是以下基础设施问题:
- 服务器资源不足(CPU/内存过载,导致请求排队)
- 网络链路问题(子域名解析延迟、跨域请求的网络波动、反向代理配置异常)
- 数据库连接池耗尽(即使test页面不直接查库,如果数据库连接被其他请求占满,可能导致进程阻塞)
- 托管平台的自动扩缩容机制触发(比如流量突增时实例启动/切换的延迟)
二、代码中存在的低效点(虽不是主因,但会放大问题)
虽然代码问题不是导致test页面变慢的原因,但会加重生产环境的负载,间接加剧延迟:
模型save方法的重复调用:
你在save方法中调用了两次super().save(),第一次保存生成created_datetime,第二次更新display_datetime,这会触发两次数据库写入操作,增加数据库负载。可以修改为仅在首次创建时计算并保存:def save(self, *args, **kwargs): if not self.pk: # 仅新建对象时执行 now = datetime.datetime.now() rounded_minute = (now.minute // 5) * 5 self.display_datetime = now.replace(minute=rounded_minute, second=0, microsecond=0) super().save(*args, **kwargs)这样只需一次数据库写入,减少不必要的开销。
视图中多次查询
objects.last():
视图中对每个设备模型单独调用objects.last(),发起20+次独立数据库查询,若没有合适索引会触发全表扫描。可以优化为:- 确保
created_datetime字段添加索引(created_datetime = models.DateTimeField(auto_now_add=True, null=True, db_index=True)) - 若所有设备都是Device子类,通过批量查询获取最新数据:
# 假设子类有device_type字段区分设备 latest_device_ids = Device.objects.values('device_type').annotate(last_id=Max('id')).values_list('last_id', flat=True) list_device = Device.objects.filter(id__in=latest_device_ids)
把20+次查询减少到1-2次,大幅降低数据库查询时间。
- 确保
三、排查步骤建议
先验证基础设施问题:
- 在生产环境直接访问服务器IP的test页面,跳过域名解析,看是否依然延迟
- 查看服务器监控:CPU使用率、内存占用、数据库连接数、请求队列长度
- 检查托管平台的日志,是否有超时、资源不足的告警
- 在生产服务器上执行简单SQL查询,测试数据库连接速度
再优化代码:
先解决基础设施问题,再处理代码低效点,避免因次要问题浪费排查时间。
内容的提问来源于stack exchange,提问作者webdeveloper
相关产品推荐
相关产品推荐

