问题描述
情况
我们正在开发我们项目的后端,该后端由两个用 Django 和 FastAPI 编写的服务组成。这两个服务都使用 MongoDB 作为它们的数据库系统。
在 Django 中,我们使用 djongo==1.3.0
来实现 ORM 兼容性。
在 FastAPI 中,我们使用 odmantic==0.3.4
。
这两个库都在下面使用 pymongo==3.11.3
。
自从我们创建 Django 服务以来,这个 MongoDB SRV 错误一直是我们的问题,但我们设法通过不使用最新的软件包来解决它,例如:
Django==2.2.20
djongo==1.3.0
pymongo==3.11.3
最近由于安全风险,我们不得不升级:
urllib3 from 1.25.8 to 1.26.5
pydantic from 1.8.1 to 1.8.2
Django from 2.2.20 to 2.2.22
这些是由 GitHub 的 dependabot 推荐的。
问题
当我们现在在本地运行任何这些服务时,它们会因以下基本异常而中断:
dns.resolver.NoAnswer: The DNS response does not contain an answer to the question: _mongodb._tcp.cluster0.k1eh0.mongodb.net. IN SRV
Django 的完整日志:
> python manage.py test
Creating test database for alias 'default'...
Traceback (most recent call last):
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/djongo/database.py",line 10,in connect
return clients[db]
KeyError: 'djongo_test'
During handling of the above exception,another exception occurred:
Traceback (most recent call last):
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/dns/resolver.py",line 212,in __init__
rrset = response.find_rrset(response.answer,qname,File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/dns/message.py",line 341,in find_rrset
raise KeyError
KeyError
During handling of the above exception,line 220,in __init__
crrset = response.find_rrset(response.answer,another exception occurred:
Traceback (most recent call last):
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/pymongo/srv_resolver.py",line 72,in _resolve_uri
results = resolver.query('_mongodb._tcp.' + self.__fqdn,'SRV',File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/dns/resolver.py",line 1100,in query
return get_default_resolver().query(qname,rdtype,rdclass,tcp,source,line 1003,in query
answer = Answer(_qname,response,line 232,in __init__
raise NoAnswer(response=response)
dns.resolver.NoAnswer: The DNS response does not contain an answer to the question: _mongodb._tcp.database-test.avxhw.mongodb.net. IN SRV
During handling of the above exception,another exception occurred:
Traceback (most recent call last):
File "manage.py",line 21,in <module>
main()
File "manage.py",line 17,in main
execute_from_command_line(sys.argv)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/core/management/__init__.py",line 381,in execute_from_command_line
utility.execute()
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/core/management/__init__.py",line 375,in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/core/management/commands/test.py",line 23,in run_from_argv
super().run_from_argv(argv)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/core/management/base.py",line 323,in run_from_argv
self.execute(*args,**cmd_options)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/core/management/base.py",line 364,in execute
output = self.handle(*args,**options)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/core/management/commands/test.py",line 53,in handle
failures = test_runner.run_tests(test_labels)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/test/runner.py",line 629,in run_tests
old_config = self.setup_databases(aliases=databases)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/test/runner.py",line 552,in setup_databases
return _setup_databases(
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/test/utils.py",line 170,in setup_databases
connection.creation.create_test_db(
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/db/backends/base/creation.py",line 58,in create_test_db
self._create_test_db(verbosity,autoclobber,keepdb)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/db/backends/base/creation.py",line 168,in _create_test_db
with self._nodb_connection.cursor() as cursor:
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/db/backends/base/base.py",line 256,in cursor
return self._cursor()
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/db/backends/base/base.py",line 233,in _cursor
self.ensure_connection()
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/db/backends/base/base.py",line 217,in ensure_connection
self.connect()
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/django/db/backends/base/base.py",line 195,in connect
self.connection = self.get_new_connection(conn_params)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/djongo/base.py",line 185,in get_new_connection
self.client_connection = Database.connect(db=name,**connection_params)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/djongo/database.py",line 13,in connect
clients[db] = MongoClient(**kwargs,connect=False)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/pymongo/mongo_client.py",line 639,in __init__
res = uri_parser.parse_uri(
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/pymongo/uri_parser.py",line 500,in parse_uri
nodes = dns_resolver.get_hosts()
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/pymongo/srv_resolver.py",line 102,in get_hosts
_,nodes = self._get_srv_response_and_hosts(True)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/pymongo/srv_resolver.py",line 83,in _get_srv_response_and_hosts
results = self._resolve_uri(encapsulate_errors)
File "/home/bk/inz/backend/authservice/venv/lib/python3.8/site-packages/pymongo/srv_resolver.py",line 79,in _resolve_uri
raise ConfigurationError(str(exc))
pymongo.errors.ConfigurationError: The DNS response does not contain an answer to the question: _mongodb._tcp.database-test.avxhw.mongodb.net. IN SRV
FastAPI 的完整日志:
> python -m src.main
Traceback (most recent call last):
File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/pymongo/srv_resolver.py",File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/dns/resolver.py",line 1321,in query
return resolve(qname,line 1305,in resolve
return get_default_resolver().resolve(qname,line 1202,in resolve
(answer,done) = resolution.query_result(response,None)
File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/dns/resolver.py",line 674,in query_result
raise NoAnswer(response=answer.response)
dns.resolver.NoAnswer: The DNS response does not contain an answer to the question: _mongodb._tcp.cluster0.k1eh0.mongodb.net. IN SRV
During handling of the above exception,another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.8/runpy.py",line 194,in _run_module_as_main
return _run_code(code,main_globals,None,File "/usr/lib/python3.8/runpy.py",line 87,in _run_code
exec(code,run_globals)
File "/home/bk/inz/backend/testservice/src/main.py",line 20,in <module>
client = AsyncIOMotorClient(MONGODB_URL)
File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/motor/core.py",line 156,in __init__
delegate = self.__delegate_class__(*args,**kwargs)
File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/pymongo/mongo_client.py",in __init__
res = uri_parser.parse_uri(
File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/pymongo/uri_parser.py",in parse_uri
nodes = dns_resolver.get_hosts()
File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/pymongo/srv_resolver.py",nodes = self._get_srv_response_and_hosts(True)
File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/pymongo/srv_resolver.py",in _get_srv_response_and_hosts
results = self._resolve_uri(encapsulate_errors)
File "/home/bk/inz/backend/testservice/venv/lib/python3.8/site-packages/pymongo/srv_resolver.py",in _resolve_uri
raise ConfigurationError(str(exc))
pymongo.errors.ConfigurationError: The DNS response does not contain an answer to the question: _mongodb._tcp.cluster0.k1eh0.mongodb.net. IN SRV
在我们在 GitHub Actions 上的 CI 设置中,Django 服务测试仍然成功运行。很明显,问题出在 DNS 方面。
问题
- 是否有不支持 MongoDB 的特定 DNS 服务器?在它坏掉之前和之后,我都在使用 Google 的
8.8.8.8
。 - 为什么升级列出的依赖项会导致问题?这两项服务仅升级了
urllib
。 - 有什么解决方法吗?
解决方法
查看 https://github.com/mongodb/specifications/blob/master/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.rst 以了解 SRV URI 的工作原理,然后使用诸如 dig
之类的工具手动发出相关的 DNS 查询以验证您的环境是否具有可用的 DNS。