Skip to content

Commit b508f6d

Browse files
jmikolabenjirewiskevinAlbs
authored
DRIVERS-1519: srvMaxHosts option for limiting SRV seeding (#1069)
* DRIVERS-1519: srvMaxHosts option for limiting SRV seeding Since this commit adds a "MongoClient Configuration" section to the SRV spec, documentation for the srvServiceName option (introduced in c48d7f4) was also added. This commit also revises existing sections of the SRV spec test README. * Specify randomization algorithm and require the same for polling * Require mongodb+srv scheme to use srvMaxHosts * Update dates for tentative changelog entries * Do not expect canonical host names for sharded tests Seeds do not get replaced for non-canonical host names in sharded topologies. That is only done for replica set topologies. * Positive srvMaxHosts conflicts with loadBalanced=true and replicaSet Adds URI Validation section to SRV spec. Notes conflict in Load Balancer spec's URI Validation section. Revises sections in URI Options spec (including directConnection validation). Adds relevant spec tests to SRV and URI Options specs. * Use correct SRV record for testing srvMaxHosts with loadBalanced=true The test4 record is intentionally missing and should not have been used in these tests. The test3 record resolves to a single host, which is suitable for testing loadBalanced=true in the connection string. Co-authored-by: Benjamin Rewis <[email protected]> Co-authored-by: Kevin Albertson <[email protected]>
1 parent 83cc66a commit b508f6d

File tree

48 files changed

+886
-122
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+886
-122
lines changed

source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.rst

Lines changed: 100 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ Initial DNS Seedlist Discovery
1010
:Authors: Derick Rethans
1111
:Status: Draft
1212
:Type: Standards
13-
:Last Modified: 2021-09-15
14-
:Version: 1.5.0
13+
:Last Modified: 2021-10-14
14+
:Version: 1.6.0
1515
:Spec Lead: Matt Broadstone
1616
:Advisory Group: \A. Jesse Jiryu Davis
1717
:Approver(s): Bernie Hackett, David Golden, Jeff Yemin, Matt Broadstone, A. Jesse Jiryu Davis
@@ -48,6 +48,9 @@ interpreted as described in `RFC 2119 <https://www.ietf.org/rfc/rfc2119.txt>`_.
4848
Specification
4949
=============
5050

51+
Connection String Format
52+
------------------------
53+
5154
The connection string parser in the driver is extended with a new protocol
5255
``mongodb+srv`` as a logical pre-processing step before it considers the
5356
connection string and SDAM specifications. In this protocol, the comma
@@ -61,35 +64,59 @@ format is::
6164
specification following the ``Host Information``. This includes the ``Auth
6265
database`` and ``Connection Options``.
6366

64-
Seedlist Discovery
65-
------------------
6667

67-
In this preprocessing step, the driver will query the DNS server for SRV
68-
records on ``{hostname}.{domainname}``, prefixed with the SRV service name
69-
and protocol. The SRV service name is provided in the ``srvServiceName`` URI option and
70-
defaults to ``mongodb``. The protocol is always ``tcp``. After prefixing, the URI
71-
should look like: ``_{srvServiceName}._tcp.{hostname}.{domainname}``. This DNS query
72-
is expected to respond with one or more SRV records. The driver MUST add all the host
73-
names and port numbers that were returned as part of the DNS SRV query result to the
74-
seedlist.
68+
MongoClient Configuration
69+
-------------------------
7570

76-
The priority and weight fields in returned SRV records MUST be ignored.
71+
srvMaxHosts
72+
~~~~~~~~~~~
7773

78-
If ``mongodb+srv`` is used, a driver MUST implicitly also enable TLS. Clients
79-
can turn this off by passing ``ssl=false`` in either the Connection String,
80-
or options passed in as parameters in code to the MongoClient constructor (or
81-
equivalent API for each driver), but not through a TXT record (discussed in
82-
the next section).
74+
This option is used to limit the number of mongos connections that may be
75+
created for sharded topologies. This option limits the number of SRV records
76+
used to populate the seedlist during initial discovery, as well as the number of
77+
additional hosts that may be added during
78+
`SRV polling <../polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.rst>`_.
79+
This option requires a non-negative integer and defaults to zero (i.e. no
80+
limit). This option MUST only be configurable at the level of a ``MongoClient``.
8381

84-
A driver MUST verify that in addition to the ``{hostname}``, the
85-
``{domainname}`` consists of at least two parts: the domain name, and a TLD.
86-
Drivers MUST raise an error and MUST NOT contact the DNS server to obtain SRV
87-
(or TXT records) if the full URI does not consists of at least three parts.
8882

89-
A driver MUST verify that the host names returned through SRV records have the
90-
same parent ``{domainname}``. Drivers MUST raise an error and MUST NOT
91-
initiate a connection to any returned host name which does not share the same
92-
``{domainname}``.
83+
srvServiceName
84+
~~~~~~~~~~~~~~
85+
86+
This option specifies a valid SRV service name according to
87+
`RFC 6335 <https://datatracker.ietf.org/doc/html/rfc6335#section-5.1>`_, with
88+
the exception that it may exceed 15 characters as long as the 63rd (62nd with
89+
prepended underscore) character DNS query limit is not surpassed. This option
90+
requires a string value and defaults to "mongodb". This option MUST only be
91+
configurable at the level of a ``MongoClient``.
92+
93+
94+
URI Validation
95+
~~~~~~~~~~~~~~
96+
97+
The driver MUST report an error if either the ``srvServiceName`` or
98+
``srvMaxHosts`` URI options are specified with a non-SRV URI (i.e. scheme other
99+
than ``mongodb+srv``). The driver MUST allow specifying the ``srvServiceName``
100+
and ``srvMaxHosts`` URI options with an SRV URI (i.e. ``mongodb+srv`` scheme).
101+
102+
If ``srvMaxHosts`` is a positive integer, the driver MUST throw an error in the
103+
following cases:
104+
105+
- The connection string contains a ``replicaSet`` option.
106+
- The connection string contains a ``loadBalanced`` option with a value of
107+
``true``.
108+
109+
When validating URI options, the driver MUST first do the SRV and TXT lookup and
110+
then perform the validation. For drivers that do SRV lookup asynchronously this
111+
may result in a ``MongoClient`` being instantiated but erroring later during
112+
operation execution.
113+
114+
115+
Seedlist Discovery
116+
------------------
117+
118+
Validation Before Querying DNS
119+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93120

94121
It is an error to specify a port in a connection string with the
95122
``mongodb+srv`` protocol, and the driver MUST raise a parse error and MUST NOT
@@ -99,14 +126,54 @@ It is an error to specify more than one host name in a connection string with
99126
the ``mongodb+srv`` protocol, and the driver MUST raise a parse error and MUST
100127
NOT do DNS resolution or contact hosts.
101128

102-
The driver MUST NOT attempt to connect to any hosts until the DNS query has
103-
returned its results.
129+
A driver MUST verify that in addition to the ``{hostname}``, the
130+
``{domainname}`` consists of at least two parts: the domain name, and a TLD.
131+
Drivers MUST raise an error and MUST NOT contact the DNS server to obtain SRV
132+
(or TXT records) if the full URI does not consist of at least three parts.
133+
134+
If ``mongodb+srv`` is used, a driver MUST implicitly also enable TLS. Clients
135+
can turn this off by passing ``tls=false`` in either the Connection String,
136+
or options passed in as parameters in code to the MongoClient constructor (or
137+
equivalent API for each driver), but not through a TXT record (discussed in a
138+
later section).
139+
140+
141+
Querying DNS
142+
~~~~~~~~~~~~
143+
144+
In this preprocessing step, the driver will query the DNS server for SRV records
145+
on ``{hostname}.{domainname}``, prefixed with the SRV service name and protocol.
146+
The SRV service name is provided in the ``srvServiceName`` URI option and
147+
defaults to ``mongodb``. The protocol is always ``tcp``. After prefixing, the
148+
URI should look like: ``_{srvServiceName}._tcp.{hostname}.{domainname}``. This
149+
DNS query is expected to respond with one or more SRV records.
150+
151+
The priority and weight fields in returned SRV records MUST be ignored.
104152

105153
If the DNS result returns no SRV records, or no records at all, or a DNS error
106154
happens, an error MUST be raised indicating that the URI could not be used to
107155
find hostnames. The error SHALL include the reason why they could not be
108156
found.
109157

158+
A driver MUST verify that the host names returned through SRV records have the
159+
same parent ``{domainname}``. Drivers MUST raise an error and MUST NOT
160+
initiate a connection to any returned host name which does not share the same
161+
``{domainname}``.
162+
163+
The driver MUST NOT attempt to connect to any hosts until the DNS query has
164+
returned its results.
165+
166+
If ``srvMaxHosts`` is zero or greater than or equal to the number of hosts in
167+
the DNS result, the driver MUST populate the seedlist with all hosts.
168+
169+
If ``srvMaxHosts`` is greater than zero and less than the number of hosts in the
170+
DNS result, the driver MUST randomly select that many hosts and use them to
171+
populate the seedlist. Drivers SHOULD use the `Fisher-Yates shuffle`_ for
172+
randomization.
173+
174+
.. _`Fisher-Yates shuffle`: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
175+
176+
110177
Default Connection String Options
111178
---------------------------------
112179

@@ -276,6 +343,11 @@ SRV records.
276343
ChangeLog
277344
=========
278345

346+
2021-10-14 - 1.6.0
347+
Add ``srvMaxHosts`` MongoClient option and restructure Seedlist Discovery
348+
section. Improve documentation for the ``srvServiceName`` MongoClient
349+
option and add a new URI Validation section.
350+
279351
2021-09-15 - 1.5.0
280352
Clarify that service name only defaults to ``mongodb``, and should be
281353
defined by the ``srvServiceName`` URI option.

source/initial-dns-seedlist-discovery/tests/README.rst

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,20 @@ Test Setup
1010

1111
The tests in the ``replica-set`` directory MUST be executed against a
1212
three-node replica set on localhost ports 27017, 27018, and 27019 with
13-
replica set name ``repl0``. The tests in ``load-balanced`` MUST be executed
14-
against a load-balanced sharded cluster with the mongos servers running on
15-
localhost ports 27017 and 27018 and load balancers, shard servers, and config
16-
servers running on any open ports. In both cases, the clusters MUST be
17-
started with SSL enabled.
13+
replica set name ``repl0``.
14+
15+
The tests in the ``load-balanced`` directory MUST be executed against a
16+
load-balanced sharded cluster with the mongos servers running on localhost ports
17+
27017 and 27018 (corresponding to the script in `drivers-evergreen-tools`_). The
18+
load balancers, shard servers, and config servers may run on any open ports.
19+
20+
.. _`drivers-evergreen-tools`: https://github.com/mongodb-labs/drivers-evergreen-tools/blob/master/.evergreen/run-load-balancer.sh
21+
22+
The tests in the ``sharded`` directory MUST be executed against a sharded
23+
cluster with the mongos servers running on localhost ports 27017 and 27018.
24+
Shard servers and config servers may run on any open ports.
25+
26+
In all cases, the clusters MUST be started with SSL enabled.
1827

1928
To run the tests that accompany this spec, you need to configure the SRV and
2029
TXT records with a real name server. The following records are required for
@@ -78,28 +87,49 @@ Test Format and Use
7887

7988
These YAML and JSON files contain the following fields:
8089

81-
- ``uri``: a mongodb+srv connection string
90+
- ``uri``: a ``mongodb+srv`` connection string
8291
- ``seeds``: the expected set of initial seeds discovered from the SRV record
92+
- ``numSeeds``: the expected number of initial seeds discovered from the SRV
93+
record. This is mainly used to test ``srvMaxHosts``, since randomly selected
94+
hosts cannot be deterministically asserted.
8395
- ``hosts``: the discovered topology's list of hosts once SDAM completes a scan
84-
- ``options``: the parsed connection string options as discovered from URI and
85-
TXT records
86-
- ``parsed_options``: additional options present in the `Connection String`_
87-
URI such as ``Userinfo`` (as ``user`` and ``password``), and ``Auth
88-
database`` (as ``auth_database``).
96+
- ``numHosts``: the expected number of hosts discovered once SDAM completes a
97+
scan. This is mainly used to test ``srvMaxHosts``, since randomly selected
98+
hosts cannot be deterministically asserted.
99+
- ``options``: the parsed `URI options`_ as discovered from the
100+
`Connection String`_'s "Connection Options" component and SRV resolution
101+
(e.g. TXT records, implicit ``tls`` default).
102+
- ``parsed_options``: additional, parsed options from other `Connection String`_
103+
components. This is mainly used for asserting ``UserInfo`` (as ``user`` and
104+
``password``) and ``Auth database`` (as ``auth_database``).
89105
- ``error``: indicates that the parsing of the URI, or the resolving or
90106
contents of the SRV or TXT records included errors.
91107
- ``comment``: a comment to indicate why a test would fail.
92108

93109
.. _`Connection String`: ../../connection-string/connection-string-spec.rst
110+
.. _`URI options`: ../../uri-options/uri-options.rst
111+
112+
For each file, create a MongoClient initialized with the ``mongodb+srv``
113+
connection string.
114+
115+
If ``seeds`` is specified, drivers SHOULD verify that the set of hosts in the
116+
client's initial seedlist matches the list in ``seeds``. If ``numSeeds`` is
117+
specified, drivers SHOULD verify that the size of that set matches ``numSeeds``.
118+
119+
If ``hosts`` is specified, drivers MUST verify that the set of
120+
ServerDescriptions in the client's TopologyDescription eventually matches the
121+
list in ``hosts``. If ``numHosts`` is specified, drivers MUST verify that the
122+
size of that set matches ``numHosts``.
123+
124+
If ``options`` is specified, drivers MUST verify each of the values under
125+
``options`` match the MongoClient's parsed value for that option. There may be
126+
other options parsed by the MongoClient as well, which a test does not verify.
127+
128+
If ``parsed_options`` is specified, drivers MUST verify that each of the values
129+
under ``parsed_options`` match the MongoClient's parsed value for that option.
130+
Supported values include, but are not limited to, ``user`` and ``password``
131+
(parsed from ``UserInfo``) and ``auth_database`` (parsed from
132+
``Auth database``).
94133

95-
For each file, create MongoClient initialized with the mongodb+srv connection
96-
string. You SHOULD verify that the client's initial seed list matches the list of
97-
seeds. You MUST verify that the set of ServerDescriptions in the client's
98-
TopologyDescription eventually matches the list of hosts. You MUST verify that
99-
each of the values of the Connection String Options under ``options`` match the
100-
Client's parsed value for that option. There may be other options parsed by
101-
the Client as well, which a test does not verify. In ``uri-with-auth`` the URI
102-
contains a user/password set and additional options are provided in
103-
``parsed_options`` so that tests can verify authentication is maintained when
104-
evaluating URIs. You MUST verify that an error has been thrown if ``error`` is
105-
present.
134+
If ``error`` is specified and ``true``, drivers MUST verify that an error has
135+
been thrown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"uri": "mongodb+srv://test20.test.build.10gen.cc/?srvMaxHosts=1",
3+
"seeds": [],
4+
"hosts": [],
5+
"error": true,
6+
"comment": "Should fail because positive integer for srvMaxHosts conflicts with loadBalanced=true (TXT)"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
uri: "mongodb+srv://test20.test.build.10gen.cc/?srvMaxHosts=1"
2+
seeds: []
3+
hosts: []
4+
error: true
5+
comment: Should fail because positive integer for srvMaxHosts conflicts with loadBalanced=true (TXT)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"uri": "mongodb+srv://test3.test.build.10gen.cc/?loadBalanced=true&srvMaxHosts=1",
3+
"seeds": [],
4+
"hosts": [],
5+
"error": true,
6+
"comment": "Should fail because positive integer for srvMaxHosts conflicts with loadBalanced=true"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
uri: "mongodb+srv://test3.test.build.10gen.cc/?loadBalanced=true&srvMaxHosts=1"
2+
seeds: []
3+
hosts: []
4+
error: true
5+
comment: Should fail because positive integer for srvMaxHosts conflicts with loadBalanced=true
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"uri": "mongodb+srv://test20.test.build.10gen.cc/?srvMaxHosts=0",
3+
"seeds": [
4+
"localhost.test.build.10gen.cc:27017"
5+
],
6+
"hosts": [
7+
"localhost.test.build.10gen.cc:27017"
8+
],
9+
"options": {
10+
"loadBalanced": true,
11+
"srvMaxHosts": 0,
12+
"ssl": true
13+
}
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# loadBalanced=true (TXT) is permitted because srvMaxHosts is non-positive
2+
uri: "mongodb+srv://test20.test.build.10gen.cc/?srvMaxHosts=0"
3+
seeds:
4+
- localhost.test.build.10gen.cc:27017
5+
hosts:
6+
- localhost.test.build.10gen.cc:27017
7+
options:
8+
loadBalanced: true
9+
srvMaxHosts: 0
10+
ssl: true
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"uri": "mongodb+srv://test3.test.build.10gen.cc/?loadBalanced=true&srvMaxHosts=0",
3+
"seeds": [
4+
"localhost.test.build.10gen.cc:27017"
5+
],
6+
"hosts": [
7+
"localhost.test.build.10gen.cc:27017"
8+
],
9+
"options": {
10+
"loadBalanced": true,
11+
"srvMaxHosts": 0,
12+
"ssl": true
13+
}
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# loadBalanced=true is permitted because srvMaxHosts is non-positive
2+
uri: "mongodb+srv://test3.test.build.10gen.cc/?loadBalanced=true&srvMaxHosts=0"
3+
seeds:
4+
- localhost.test.build.10gen.cc:27017
5+
hosts:
6+
- localhost.test.build.10gen.cc:27017
7+
options:
8+
loadBalanced: true
9+
srvMaxHosts: 0
10+
ssl: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"uri": "mongodb+srv://test5.test.build.10gen.cc/?srvMaxHosts=1",
3+
"seeds": [],
4+
"hosts": [],
5+
"error": true,
6+
"comment": "Should fail because positive integer for srvMaxHosts conflicts with replicaSet option (TXT)"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
uri: "mongodb+srv://test5.test.build.10gen.cc/?srvMaxHosts=1"
2+
seeds: []
3+
hosts: []
4+
error: true
5+
comment: Should fail because positive integer for srvMaxHosts conflicts with replicaSet option (TXT)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"uri": "mongodb+srv://test1.test.build.10gen.cc/?replicaSet=repl0&srvMaxHosts=1",
3+
"seeds": [],
4+
"hosts": [],
5+
"error": true,
6+
"comment": "Should fail because positive integer for srvMaxHosts conflicts with replicaSet option"
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
uri: "mongodb+srv://test1.test.build.10gen.cc/?replicaSet=repl0&srvMaxHosts=1"
2+
seeds: []
3+
hosts: []
4+
error: true
5+
comment: Should fail because positive integer for srvMaxHosts conflicts with replicaSet option
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=2",
3+
"numSeeds": 2,
4+
"seeds": [
5+
"localhost.test.build.10gen.cc:27017",
6+
"localhost.test.build.10gen.cc:27018"
7+
],
8+
"hosts": [
9+
"localhost:27017",
10+
"localhost:27018",
11+
"localhost:27019"
12+
],
13+
"options": {
14+
"srvMaxHosts": 2,
15+
"ssl": true
16+
}
17+
}

0 commit comments

Comments
 (0)