DRF生产环境API调用远慢于开发环境是何原因如何优化?
Django生产环境API接口性能差异排查
问题现象
- 部署架构:Django应用基于Docker+Nginx部署在AWS EC2实例,本地开发环境与生产环境均使用PostgreSQL数据库,两端存储数据完全一致,问题接口返回数据量仅为50KB
- 性能差异:本地环境无论是否开启DEBUG模式,该接口调用耗时稳定在600-800ms区间;生产环境同接口调用耗时达到15-20s
- 初步排查:已在所有适用场景使用
select_related与prefetch_related完成数据库查询优化,进一步定位发现14-19s的耗时集中在序列化器的to_representation方法执行阶段,其余API业务代码总耗时仅1-2s
待排查问题
- 造成本地与生产环境巨大性能差异的核心原因是什么?
- Django在DEBUG模式与生产环境下处理API调用的逻辑存在哪些区别?
- 除数据库查询优化外,还可以通过哪些调整提升生产环境的API调用速度?
- 当前给出的序列化器与对应模型定义中,是否存在导致序列化阶段性能阻塞的问题?
关联代码
DataSource序列化器定义
class DataSourceSerializer(serializers.ModelSerializer): instance = InstanceSerializer() id = serializers.IntegerField(required=False) class Meta: model = DataSource exclude = ('previous', 'version', ) extra_kwargs = { 'password': { 'write_only': True, 'required': False }, 'db_staging': { 'required': False } } def validate(self, data): password = data.get('password') if password in ['', None] and self.instance.password in ['', None]: raise serializers.ValidationError({"password": "This field is required"}) return data # TODO: Merge in ROAD-1234 def create(self, validated_data): session = self.context.get('request', None) if session is not None: session = Session.objects.get(session_key=session.session.session_key) instance_data = validated_data.pop('instance', None) # test config values try: test_connection(validated_data) except (exc.OperationalError, err.OperationalError): error = {'message': "Invalid credentials. Unable to connect to the data source."} raise serializers.ValidationError(error) except exc.TimeoutError: error = {'message': "Connection timed out. Unable to connect to the data source."} raise serializers.ValidationError(error) instance, _ = InstanceMetadata.objects.get_or_create(session=session, **instance_data) obj, _ = DataSource.objects.get_or_create(instance=instance, version=instance, **validated_data) return obj
DataSource模型定义
class DataSource(models.Model): id = models.AutoField(primary_key=True) instance = models.ForeignKey(InstanceMetadata, on_delete=models.CASCADE, related_name='instance') db_type = models.CharField(max_length=200) host = models.CharField(max_length=200) port = models.IntegerField() username = models.CharField(max_length=200) password = models.CharField(max_length=200) db_name = models.CharField(max_length=200) db_staging = models.CharField(max_length=200, default=None, null=True) version = models.ForeignKey(InstanceMetadata, on_delete=models.CASCADE, null=True) previous = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, default=None, to_field='id') objects = managers.DataSourceManager() def natural_key(self): return (self.db_name, ) + self.instance.natural_key() natural_key.dependences = ['spinner.InstanceMetadata'] class Meta: constraints = [ models.UniqueConstraint(fields=['version', 'instance', 'db_name'], name='unique source') ] def get_unique_attr(self): return { 'db_name': self.db_name, 'instance__name': self.instance.name}
内容的提问来源于stack exchange,提问作者Judy T Raj
相关产品推荐
相关产品推荐

