动态修改django.db.connections.databases实现多租户数据库连接的可行性与优化方案咨询
动态修改django.db.connections.databases实现多租户数据库连接的可行性与优化方案咨询
我这是第一次用Django开发多租户SaaS应用,每个公司都有独立的PostgreSQL数据库,这些数据库会在公司注册时动态创建。我没法在settings.DATABASES里预先定义所有数据库,因为公司可以随时注册,而且不需要重启服务器。
我目前的解决方案是用中间件从子域名或者JWT令牌中识别公司,然后在运行时修改connections.databases来配置对应公司的数据库连接:
import redis from django.db import connections from django.core.exceptions import ImproperlyConfigured from django.utils.connection import ConnectionDoesNotExist from rest_framework_simplejwt.authentication import JWTAuthentication from myapp.models import Company # Company model stored in the global database class CompanyDBMiddleware: def __init__(self, get_response): self.get_response = get_response self.jwt_authenticator = JWTAuthentication() self.cache = redis.Redis(host='localhost', port=6379, db=0) def __call__(self, request): company_db = self.get_database_for_company(request) if not company_db: raise ImproperlyConfigured("Could not determine the company's database.") # Register connection only if it does not exist in `connections.databases` if company_db not in connections.databases: connections.databases[company_db] = { 'ENGINE': 'django.db.backends.postgresql', 'NAME': company_db, 'USER': 'postgres', 'PASSWORD': 'your_password', 'HOST': 'localhost', 'PORT': '5432', 'CONN_MAX_AGE': 60, # To avoid opening and closing connections on each request } request.company_db = company_db response = self.get_response(request) # Close connection after the response try: connections[company_db].close() except ConnectionDoesNotExist: pass return response def get_database_for_company(self, request): subdomain = request.get_host().split('.')[0] company_db = None cache_key = f"company_db_{subdomain}" company_db = self.cache.get(cache_key) if company_db: return company_db.decode("utf-8") try: company = Company.objects.using('default').get(subdomain=subdomain, active=True) company_db = company.db_name self.cache.setex(cache_key, 300, company_db) # Cache the database name for 5 minutes return company_db except Company.DoesNotExist: return None
我的问题如下:
- 每次请求时动态修改connections.databases来处理多数据库的方式是否正确?
- 在Django中有没有更好的方法,可以在注册新数据库时不用重启应用?
- 这种做法在负载均衡和多Django实例的环境中对性能有什么影响?
- 是不是给每个客户部署独立的API到各自的Django容器会更好?
- 我正在考虑给每个客户一个独立域名的门户,只把他们的前端部署在容器里,而API保持集中式。这种方法效率更高吗?
我很感谢任何关于最佳实践或者这种方法潜在问题的建议。
备注:内容来源于stack exchange,提问作者Br0k3nS0u1
相关产品推荐
相关产品推荐

