由于 SRV 错误,MongoDB 在本地无法运行无应答 情况问题问题

问题描述

情况

我们正在开发我们项目的后端,该后端由两个用 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。